787f556cbcf93de14c14dc37e93aab9751334077
[platform/core/uifw/at-spi2-atk.git] / atk-tests / test-simple-table.c
1 /* This file contains both declaration and definition of the TestSimpleTable,
2  * a GObject that pretends to implement the AtkTableIface interface (it 
3  * registers appropriate interface), but provides no implementation for any of the
4  * methods of this interface (NULL-filled vftbl).
5  */
6
7 #include "test-simple-table.h"
8
9 #include <stdio.h>
10 #include <string.h>
11
12 GType 
13 test_simple_table_get_type (void);
14
15 ///////////////////////////////////////////////////////////////////////////
16 // Helper functions and data
17 ///////////////////////////////////////////////////////////////////////////
18
19 // row/column selection schemes
20 gboolean ss_rows_none[NROWS] = {FALSE, FALSE, FALSE, FALSE};
21 gboolean ss_rows_02[NROWS]   = {TRUE,  FALSE, TRUE,  FALSE};
22
23 gboolean ss_cols_none[NCOLS] = {FALSE, FALSE, FALSE, FALSE, FALSE};
24 gboolean ss_cols_24[NCOLS]   = {FALSE, FALSE, TRUE,  FALSE, TRUE};
25
26 // Select table rows or columns according to the specified selection scheme.
27 // TRUE means 'selected', FALSE - 'not selected'.
28 void
29 test_simple_table_select_rows (TestSimpleTable* table, gboolean sel_scheme[])
30 {
31     int i;
32     for (i = 0; i < NROWS; ++i)
33     {
34         table->row[i].selected = sel_scheme[i];
35     }    
36 }
37
38 void
39 test_simple_table_select_columns (TestSimpleTable* table, gboolean sel_scheme[])
40 {
41     int i;
42     for (i = 0; i < NCOLS; ++i)
43     {
44         table->col[i].selected = sel_scheme[i];
45     }    
46 }
47
48 // Reset row and column headers to their default values
49 void
50 test_simple_table_reset_headers (TestSimpleTable* table)
51 {
52     int i, j;
53     
54     // initialize row and column descriptors
55     for (i = 0; i < NROWS; ++i)
56     {
57         sprintf (TEST_SIMPLE_TEXT (table->row[i].hdr)->text, DEF_ROW_DESCR_TPL, i);
58     }
59     
60     for (j = 0; j < NCOLS; ++j)
61     {
62         sprintf (TEST_SIMPLE_TEXT (table->col[j].hdr)->text, DEF_COL_DESCR_TPL, j);
63     }
64 }
65
66 ///////////////////////////////////////////////////////////////////////////
67 // Implementation
68 ///////////////////////////////////////////////////////////////////////////
69 static GObjectClass *parent_class_simple_table = NULL;
70
71 static AtkObject* 
72 test_simple_table_ref_at (AtkTable *table, gint row, gint column)
73 {
74     TestSimpleTable* self = (TestSimpleTable*)table;
75     if ((!self) || self->disposed)
76     {
77         return NULL;
78     }
79     
80     if ((row >=0) && (row < self->nrows) && 
81         (column >= 0) && (column < self->ncols))
82     {
83         return ATK_OBJECT (self->tbl[row][column].elem);
84     }
85     else
86     { 
87         return NULL;
88     }
89 }
90
91 static gint 
92 test_simple_table_get_index_at (AtkTable *table, gint row, gint column)
93 {
94     TestSimpleTable* self = (TestSimpleTable*)table;
95     if ((!self) || self->disposed)
96     {
97         return -1;
98     }
99
100     if ((row >=0) && (row < self->nrows) && 
101         (column >= 0) && (column < self->ncols))
102     {
103         // non-child objects have ID=-1 by default.
104         return (self->tbl[row][column].elem->id);
105     }
106     else
107     { 
108         return -1;
109     }
110 }
111
112 static gint 
113 test_simple_table_get_column_at_index (AtkTable *table, gint index_)
114 {
115     TestSimpleTable* self = (TestSimpleTable*)table;
116     if ((!self) || self->disposed)
117     {
118         return -1;
119     }
120
121     int i, j;
122     for (i = 0; i < self->nrows; ++i)
123     {
124         for (j = 0; j < self->ncols; ++j)
125         {
126             if (self->tbl[i][j].elem->id == index_)
127             {
128                 return j;
129             }
130         }
131     }
132     
133     return -1;
134 }
135
136 static gint 
137 test_simple_table_get_row_at_index (AtkTable *table, gint index_)
138 {
139     TestSimpleTable* self = (TestSimpleTable*)table;
140     if ((!self) || self->disposed)
141     {
142         return -1;
143     }
144     
145     if (index_ < 0)
146     {
147         return -1;
148     }
149     
150     int i, j;
151     for (i = 0; i < self->nrows; ++i)
152     {
153         for (j = 0; j < self->ncols; ++j)
154         {
155             if (self->tbl[i][j].elem->id == index_)
156             {
157                 return i;
158             }
159         }
160     }
161     return -1;
162 }
163
164 static gint 
165 test_simple_table_get_n_columns (AtkTable *table)
166 {
167     TestSimpleTable* self = (TestSimpleTable*)table;
168     if ((!self) || self->disposed)
169     {
170         return 0;
171     }
172
173     return self->ncols;
174 }
175
176 static gint 
177 test_simple_table_get_n_rows (AtkTable *table)
178 {
179     TestSimpleTable* self = (TestSimpleTable*)table;
180     if ((!self) || self->disposed)
181     {
182         return 0;
183     }
184
185     return self->nrows;
186 }
187
188 static gint 
189 test_simple_table_get_column_extent_at (AtkTable *table, gint row, gint column)
190 {
191     TestSimpleTable* self = (TestSimpleTable*)table;
192     if ((!self) || self->disposed)
193     {
194         return 0;
195     }
196
197     if ((row >=0) && (row < self->nrows) && 
198         (column >= 0) && (column < self->ncols))
199     {
200         return (self->tbl[row][column].ext_col);
201     }
202     else
203     { 
204         return 0;
205     }
206 }
207
208 static gint 
209 test_simple_table_get_row_extent_at (AtkTable *table, gint row, gint column)
210 {
211     TestSimpleTable* self = (TestSimpleTable*)table;
212     if ((!self) || self->disposed)
213     {
214         return 0;
215     }
216
217     if ((row >=0) && (row < self->nrows) && 
218         (column >= 0) && (column < self->ncols))
219     {
220         return (self->tbl[row][column].ext_row);
221     }
222     else
223     { 
224         return 0;
225     }
226
227     return 0;
228 }
229
230 static AtkObject* 
231 test_simple_table_get_caption (AtkTable *table)
232 {
233     TestSimpleTable* self = (TestSimpleTable*)table;
234     if ((!self) || self->disposed)
235     {
236         return NULL;
237     }
238
239     return (self->caption);
240 }
241
242 static const gchar* 
243 test_simple_table_get_column_description (AtkTable *table, gint column)
244 {
245     TestSimpleTable* self = (TestSimpleTable*)table;
246     if ((!self) || self->disposed)
247     {
248         return NULL;
249     }
250     
251     if ((column < 0) || (column >= self->ncols))
252     {
253         return NULL;
254     }
255     
256     return TEST_SIMPLE_TEXT (self->col[column].hdr)->text;
257 }
258
259 static AtkObject* 
260 test_simple_table_get_column_header (AtkTable *table, gint column)
261 {
262     TestSimpleTable* self = (TestSimpleTable*)table;
263     if ((!self) || self->disposed)
264     {
265         return NULL;
266     }
267
268     if ((column < 0) || (column >= self->ncols))
269     {
270         return NULL;
271     }
272     
273     return (self->col[column].hdr);
274 }
275
276 static const gchar* 
277 test_simple_table_get_row_description (AtkTable *table, gint row)
278 {
279     TestSimpleTable* self = (TestSimpleTable*)table;
280     if ((!self) || self->disposed)
281     {
282         return NULL;
283     }
284
285     if ((row < 0) || (row >= self->nrows))
286     {
287         return NULL;
288     }
289     
290     return TEST_SIMPLE_TEXT (self->row[row].hdr)->text;
291 }
292
293 static AtkObject* 
294 test_simple_table_get_row_header (AtkTable *table, gint row)
295 {
296     TestSimpleTable* self = (TestSimpleTable*)table;
297     if ((!self) || self->disposed)
298     {
299         return NULL;
300     }
301
302     if ((row < 0) || (row >= self->nrows))
303     {
304         return NULL;
305     }
306     
307     return (self->row[row].hdr);
308 }
309
310 static AtkObject* 
311 test_simple_table_get_summary (AtkTable *table)
312 {
313     TestSimpleTable* self = (TestSimpleTable*)table;
314     if ((!self) || self->disposed)
315     {
316         return NULL;
317     }
318
319     return (self->summary);
320 }
321
322 static void 
323 test_simple_table_set_caption (AtkTable *table, AtkObject *caption)
324 {
325     TestSimpleTable* self = (TestSimpleTable*)table;
326     if ((!self) || self->disposed || !caption)
327     {
328         return;
329     }
330
331     // unref the old caption
332     g_object_unref (G_OBJECT (self->caption));
333     
334     // and replace it with a new one
335     self->caption = caption;
336     g_object_ref (G_OBJECT (self->caption));
337     return;
338 }
339
340 static void 
341 test_simple_table_set_column_description (AtkTable *table, gint column, const gchar *description)
342 {
343     TestSimpleTable* self = (TestSimpleTable*)table;
344     if ((!self) || self->disposed)
345     {
346         return;
347     }
348
349     if ((column < 0) || (column >= self->ncols) || !description)
350     {
351         return;
352     }
353     
354     strncpy (TEST_SIMPLE_TEXT (self->col[column].hdr)->text, description, MAX_DESCR_LENGTH);
355     return;
356 }
357
358 static void 
359 test_simple_table_set_column_header (AtkTable *table, gint column, AtkObject *header)
360 {
361     TestSimpleTable* self = (TestSimpleTable*)table;
362     if ((!self) || self->disposed)
363     {
364         return;
365     }
366
367     if ((column < 0) || (column >= self->ncols) || !header)
368     {
369         return;
370     }
371     
372     // unref old header
373     g_object_unref (G_OBJECT (self->col[column].hdr));
374     
375     // and replace it with a new one
376     g_object_ref (G_OBJECT (header));
377     self->col[column].hdr = header;
378     return;
379 }
380
381 static void 
382 test_simple_table_set_row_description (AtkTable *table, gint row, const gchar *description)
383 {
384     TestSimpleTable* self = (TestSimpleTable*)table;
385     if ((!self) || self->disposed)
386     {
387         return;
388     }
389
390     if ((row < 0) || (row >= self->nrows) || !description)
391     {
392         return;
393     }
394     
395     strncpy (TEST_SIMPLE_TEXT (self->row[row].hdr)->text, description, MAX_DESCR_LENGTH);
396     return;
397 }
398
399 static void 
400 test_simple_table_set_row_header (AtkTable *table, gint row, AtkObject *header)
401 {
402     TestSimpleTable* self = (TestSimpleTable*)table;
403     if ((!self) || self->disposed)
404     {
405         return;
406     }
407
408     if ((row < 0) || (row >= self->nrows) || !header)
409     {
410         return;
411     }
412     
413     // unref old header
414     g_object_unref (G_OBJECT (self->row[row].hdr));
415     
416     // and replace it with a new one
417     g_object_ref (G_OBJECT (header));
418     self->row[row].hdr = header;
419     
420     return;
421 }
422
423 static void 
424 test_simple_table_set_summary (AtkTable *table, AtkObject *accessible)
425 {
426     TestSimpleTable* self = (TestSimpleTable*)table;
427     if ((!self) || self->disposed || !accessible)
428     {
429         return;
430     }
431
432     // unref the old summary
433     g_object_unref (G_OBJECT (self->summary));
434     
435     // and replace it with a new one
436     self->summary = accessible;
437     g_object_ref (G_OBJECT (self->summary));
438     return;
439 }
440
441 static gint 
442 test_simple_table_get_selected_columns (AtkTable *table, gint **selected)
443 {
444     TestSimpleTable* self = (TestSimpleTable*)table;
445     if ((!self) || self->disposed || !selected)
446     {
447         return 0;
448     }
449
450     // count the selected columns
451     int i;
452     int nsel = 0;
453     for (i = 0; i < self->ncols; ++i)
454     {
455         if (self->col[i].selected)
456         {
457             ++nsel;
458         }
459     }
460     
461     if (nsel > 0)
462     {
463         // store the indexes of the selected columns 
464         int pos = 0;
465         *selected = g_new (gint, nsel);
466         for (i = 0; i < self->ncols; ++i)
467         {
468             if (self->col[i].selected)
469             {
470                 (*selected)[pos] = i;
471                 ++pos;
472             }
473         } // end for i
474     }
475     
476     return nsel;
477 }
478
479 static gint 
480 test_simple_table_get_selected_rows (AtkTable *table, gint **selected)
481 {
482     TestSimpleTable* self = (TestSimpleTable*)table;
483     if ((!self) || self->disposed || !selected)
484     {
485         return 0;
486     }
487
488     // count the selected rows
489     int i;
490     int nsel = 0;
491     for (i = 0; i < self->nrows; ++i)
492     {
493         if (self->row[i].selected)
494         {
495             ++nsel;
496         }
497     }
498     
499     if (nsel > 0)
500     {
501         // store the indexes of the selected rows 
502         int pos = 0;
503         *selected = g_new (gint, nsel);
504         for (i = 0; i < self->nrows; ++i)
505         {
506             if (self->row[i].selected)
507             {
508                 (*selected)[pos] = i;
509                 ++pos;
510             }
511         } // end for i
512     }
513     
514     return nsel;
515 }
516
517 static gboolean 
518 test_simple_table_is_column_selected (AtkTable *table, gint column)
519 {
520     TestSimpleTable* self = (TestSimpleTable*)table;
521     if ((!self) || self->disposed)
522     {
523         return FALSE;
524     }
525
526     if ((column < 0) || (column >= self->ncols))
527     {
528         return FALSE;
529     }
530     
531     return self->col[column].selected;
532 }
533
534 static gboolean 
535 test_simple_table_is_row_selected (AtkTable *table, gint row)
536 {
537     TestSimpleTable* self = (TestSimpleTable*)table;
538     if ((!self) || self->disposed)
539     {
540         return FALSE;
541     }
542
543     if ((row < 0) || (row >= self->nrows))
544     {
545         return FALSE;
546     }
547     
548     return self->row[row].selected;
549 }
550
551 static gboolean 
552 test_simple_table_is_selected (AtkTable *table, gint row, gint column)
553 {
554     TestSimpleTable* self = (TestSimpleTable*)table;
555     if ((!self) || self->disposed)
556     {
557         return FALSE;
558     }
559
560     if ((row < 0) || (row >= self->nrows) ||
561         (column < 0) || (column >= self->ncols))
562     {
563         return FALSE;
564     }
565     
566     // In this implementation a cell is selected if and only if the
567     // corresponding row and column are both selected.
568     
569     return (self->row[row].selected && self->col[column].selected);
570 }
571
572 static gboolean 
573 test_simple_table_add_row_selection (AtkTable *table, gint row)
574 {
575     TestSimpleTable* self = (TestSimpleTable*)table;
576     if ((!self) || self->disposed)
577     {
578         return FALSE;
579     }
580
581     if ((row < 0) || (row >= self->nrows))
582     {
583         return FALSE;
584     }
585     
586     gboolean was_selected = self->row[row].selected;
587     self->row[row].selected = TRUE;
588     return !was_selected;
589 }
590
591 static gboolean 
592 test_simple_table_remove_row_selection (AtkTable *table, gint row)
593 {
594     TestSimpleTable* self = (TestSimpleTable*)table;
595     if ((!self) || self->disposed)
596     {
597         return FALSE;
598     }
599
600     gboolean was_selected = self->row[row].selected;
601     self->row[row].selected = FALSE;
602     return was_selected;
603 }
604
605 static gboolean 
606 test_simple_table_add_column_selection (AtkTable *table, gint column)
607 {
608     TestSimpleTable* self = (TestSimpleTable*)table;
609     if ((!self) || self->disposed)
610     {
611         return FALSE;
612     }
613
614     if ((column < 0) || (column >= self->ncols))
615     {
616         return FALSE;
617     }
618     
619     gboolean was_selected = self->col[column].selected;
620     self->col[column].selected = TRUE;
621     return !was_selected;
622 }
623
624 static gboolean 
625 test_simple_table_remove_column_selection (AtkTable *table, gint column)
626 {
627     TestSimpleTable* self = (TestSimpleTable*)table;
628     if ((!self) || self->disposed)
629     {
630         return FALSE;
631     }
632
633     gboolean was_selected = self->col[column].selected;
634     self->col[column].selected = FALSE;
635     return was_selected;
636 }
637
638 // Signal emitters
639 // "column-deleted"
640 static void
641 emit_column_deleted (TestSimpleTable* table, gint arg1, gint arg2)
642 {
643     g_signal_emit_by_name ((gpointer)table, "column-deleted", arg1, arg2);
644     return;
645 }
646
647 // "column-inserted"
648 static void
649 emit_column_inserted (TestSimpleTable* table, gint arg1, gint arg2)
650 {
651     g_signal_emit_by_name ((gpointer)table, "column-inserted", arg1, arg2);
652     return;
653 }
654     
655 // "column-reordered"
656 static void
657 emit_column_reordered (TestSimpleTable* table)
658 {
659     g_signal_emit_by_name ((gpointer)table, "column-reordered");
660     return;
661 }
662     
663 // "model-changed"
664 static void
665 emit_model_changed (TestSimpleTable* table)
666 {
667     g_signal_emit_by_name ((gpointer)table, "model-changed");
668     return;
669 }
670     
671 // "row-deleted"
672 static void
673 emit_row_deleted (TestSimpleTable* table, gint arg1, gint arg2)
674 {
675     g_signal_emit_by_name ((gpointer)table, "row-deleted", arg1, arg2);
676     return;
677 }
678     
679 // "row-inserted"
680 static void
681 emit_row_inserted (TestSimpleTable* table, gint arg1, gint arg2)
682 {
683     g_signal_emit_by_name ((gpointer)table, "row-inserted", arg1, arg2);
684     return;
685 }
686     
687 // "row-reordered"
688 static void
689 emit_row_reordered (TestSimpleTable* table)
690 {
691     g_signal_emit_by_name ((gpointer)table, "row-reordered");
692     return;
693 }
694
695
696 /******************************************************************/
697 static void
698 simple_table_interface_init (gpointer g_iface, gpointer iface_data)
699 {
700     AtkTableIface *klass = (AtkTableIface *)g_iface;
701     
702     /* set up overrides here */
703     klass-> ref_at =
704         (AtkObject* (*) (AtkTable *table, gint row, gint column)) test_simple_table_ref_at;
705     klass-> get_index_at =
706         (gint (*) (AtkTable *table, gint row, gint column)) test_simple_table_get_index_at;
707     klass-> get_column_at_index =
708         (gint (*) (AtkTable *table, gint index_)) test_simple_table_get_column_at_index;
709     klass-> get_row_at_index =
710         (gint (*) (AtkTable *table, gint index_)) test_simple_table_get_row_at_index;
711     klass-> get_n_columns =
712         (gint (*) (AtkTable *table)) test_simple_table_get_n_columns;
713     klass-> get_n_rows =
714         (gint (*) (AtkTable *table)) test_simple_table_get_n_rows;
715     klass-> get_column_extent_at =
716         (gint (*) (AtkTable *table, gint row, gint column)) test_simple_table_get_column_extent_at;
717     klass-> get_row_extent_at =
718         (gint (*) (AtkTable *table, gint row, gint column)) test_simple_table_get_row_extent_at;
719     klass-> get_caption =
720         (AtkObject* (*) (AtkTable *table)) test_simple_table_get_caption;
721     klass-> get_column_description =
722         (const gchar* (*) (AtkTable *table, gint column)) test_simple_table_get_column_description;
723     klass-> get_column_header =
724         (AtkObject* (*) (AtkTable *table, gint column)) test_simple_table_get_column_header;
725     klass-> get_row_description =
726         (const gchar* (*) (AtkTable *table, gint row)) test_simple_table_get_row_description;
727     klass-> get_row_header =
728         (AtkObject* (*) (AtkTable *table, gint row)) test_simple_table_get_row_header;
729     klass-> get_summary =
730         (AtkObject* (*) (AtkTable *table)) test_simple_table_get_summary;
731     klass-> set_caption =
732         (void (*) (AtkTable *table, AtkObject *caption)) test_simple_table_set_caption;
733     klass-> set_column_description =
734         (void (*) (AtkTable *table, gint column, const gchar *description)) test_simple_table_set_column_description;
735     klass-> set_column_header =
736         (void (*) (AtkTable *table, gint column, AtkObject *header)) test_simple_table_set_column_header;
737     klass-> set_row_description =
738         (void (*) (AtkTable *table, gint row, const gchar *description)) test_simple_table_set_row_description;
739     klass-> set_row_header =
740         (void (*) (AtkTable *table, gint row, AtkObject *header)) test_simple_table_set_row_header ;
741     klass-> set_summary =
742         (void (*) (AtkTable *table, AtkObject *accessible)) test_simple_table_set_summary ;
743     klass-> get_selected_columns =
744         (gint (*) (AtkTable *table, gint **selected)) test_simple_table_get_selected_columns;
745     klass-> get_selected_rows =
746         (gint (*) (AtkTable *table, gint **selected)) test_simple_table_get_selected_rows;
747     klass-> is_column_selected =
748         (gboolean (*) (AtkTable *table, gint column)) test_simple_table_is_column_selected;
749     klass-> is_row_selected =
750         (gboolean (*) (AtkTable *table, gint row)) test_simple_table_is_row_selected;
751     klass-> is_selected =
752         (gboolean (*) (AtkTable *table, gint row, gint column)) test_simple_table_is_selected;
753     klass-> add_row_selection =
754         (gboolean (*) (AtkTable *table, gint row)) test_simple_table_add_row_selection;
755     klass-> remove_row_selection =
756         (gboolean (*) (AtkTable *table, gint row)) test_simple_table_remove_row_selection;
757     klass-> add_column_selection =
758         (gboolean (*) (AtkTable *table, gint column)) test_simple_table_add_column_selection;
759     klass-> remove_column_selection =
760         (gboolean (*) (AtkTable *table, gint column)) test_simple_table_remove_column_selection;
761 }
762
763 static void
764 simple_table_instance_init (GTypeInstance *instance, gpointer g_class)
765 {
766     TestSimpleTable *self = (TestSimpleTable *)instance;
767     
768     self->disposed = FALSE;
769     
770     self->nrows = NROWS;
771     self->ncols = NCOLS;
772     
773     /* create & initialize child objects */
774     int i, j;
775     for (i = 0; i < NCHILDREN; ++i)
776     {
777         self->child[i] = TEST_SIMPLE_CHILD (g_object_new (TEST_TYPE_SIMPLE_CHILD, NULL));
778         self->child[i]->id = i;
779     }
780     
781     self->not_a_child = TEST_SIMPLE_CHILD (g_object_new (TEST_TYPE_SIMPLE_CHILD, NULL));
782     
783     // initialize table cells
784     for (i = 0; i < NROWS; ++i)
785     {
786         for (j = 0; j < NCOLS; ++j)
787         {
788             if (ids[i][j] >= 0)
789             {
790                 self->tbl[i][j].elem = self->child[ids[i][j]];
791             }
792             else
793             {
794                 self->tbl[i][j].elem = self->not_a_child;
795             }
796             
797             self->tbl[i][j].ext_row = row_ext[i][j];
798             self->tbl[i][j].ext_col = col_ext[i][j];
799         } // end for j
800     } // end for i
801     
802     self->caption = ATK_OBJECT (g_object_new (TEST_TYPE_SIMPLE_TEXT, NULL));
803     strncpy (TEST_SIMPLE_TEXT (self->caption)->text, DEF_CAPTION_TEXT, MAX_DESCR_LENGTH);
804     
805     self->summary = ATK_OBJECT (g_object_new (TEST_TYPE_SIMPLE_TEXT, NULL));
806     strncpy (TEST_SIMPLE_TEXT (self->summary)->text, DEF_SUMMARY_TEXT, MAX_DESCR_LENGTH);
807     
808     // initialize row and column descriptors
809     for (i = 0; i < NROWS; ++i)
810     {
811         self->row[i].hdr = ATK_OBJECT (g_object_new (TEST_TYPE_SIMPLE_TEXT, NULL));
812         self->row[i].selected = FALSE;
813     }
814     
815     for (j = 0; j < NCOLS; ++j)
816     {
817         self->col[j].hdr = ATK_OBJECT (g_object_new (TEST_TYPE_SIMPLE_TEXT, NULL));
818         self->col[j].selected = FALSE;
819     }
820     
821     test_simple_table_reset_headers(self);
822 }
823
824 static void
825 test_simple_table_dispose (GObject *obj)
826 {
827     TestSimpleTable *self = (TestSimpleTable *)obj;
828
829     if (self->disposed) 
830     {
831         return;
832     }
833     
834     /* Make sure dispose does not run twice. */
835     self->disposed = TRUE;
836
837     int i;
838     for (i = 0; i < NCHILDREN; ++i)
839     {
840         g_object_unref (G_OBJECT (self->child[i]));
841     }
842     g_object_unref (G_OBJECT (self->not_a_child));
843
844     for (i = 0; i < NROWS; ++i)
845     {
846         g_object_unref (G_OBJECT (self->row[i].hdr));
847     }
848     
849     for (i = 0; i < NCOLS; ++i)
850     {
851         g_object_unref (G_OBJECT (self->col[i].hdr));
852     }
853     
854     g_object_unref (G_OBJECT (self->caption));
855     g_object_unref (G_OBJECT (self->summary));
856
857     /* Chain up to the parent class */
858     G_OBJECT_CLASS (parent_class_simple_table)->dispose (obj);
859 }
860
861 static void
862 test_simple_table_finalize (GObject *obj)
863 {
864     /* Chain up to the parent class */
865     G_OBJECT_CLASS (parent_class_simple_table)->finalize (obj);
866 }
867
868 static void
869 test_simple_table_class_init (gpointer g_class, gpointer g_class_data)
870 {
871     GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
872     TestSimpleTableClass *klass = TEST_SIMPLE_TABLE_CLASS (g_class);
873
874     gobject_class->dispose = test_simple_table_dispose;
875     gobject_class->finalize = test_simple_table_finalize;
876
877     parent_class_simple_table = g_type_class_peek_parent (klass);
878 }
879
880 GType 
881 test_simple_table_get_type (void)
882 {
883     static GType type = 0;
884     if (type == 0) 
885     {
886         static const GTypeInfo info = 
887         {
888             sizeof (TestSimpleTableClass),
889             NULL,   /* base_init */
890             NULL,   /* base_finalize */
891             test_simple_table_class_init, /* class_init */
892             NULL,   /* class_finalize */
893             NULL,   /* class_data */
894             sizeof (TestSimpleTable),
895             0,      /* n_preallocs */
896             simple_table_instance_init    /* instance_init */
897         };
898                 
899         static const GInterfaceInfo iface_info = 
900         {
901             (GInterfaceInitFunc) simple_table_interface_init,    /* interface_init */
902             NULL,                                       /* interface_finalize */
903             NULL                                        /* interface_data */
904         };
905         type = g_type_register_static (ATK_TYPE_OBJECT,
906                                        "TestSimpleTableType",
907                                        &info, 0);
908         g_type_add_interface_static (type,
909                                      ATK_TYPE_TABLE,
910                                      &iface_info);
911     }
912     return type;
913 }