Latest rev (previous commit was out of date). Added README and NEWS.
[platform/upstream/atk.git] / atk / atkobject.c
1 /* ATK -  Accessibility Toolkit
2  * Copyright 2001 Sun Microsystems Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <glib-object.h>
21
22 #include "atk.h"
23
24 #define NUM_POSSIBLE_STATES                     (sizeof(AtkStateMask)*8)
25
26 /* New GObject properties registered by AtkObject */
27 enum
28 {
29   PROP_0,  /* gobject convention */
30
31   PROP_NAME,
32   PROP_DESCRIPTION,
33   PROP_PARENT,      /* ancestry has changed */
34   PROP_CHILD,       /* children have changed in number or identity */
35   PROP_ROLE,        /* AtkRole has changed  */
36   PROP_STATE,       /* AtkState has changed */
37   PROP_TEXT,        /* Used only by AtkText implementors */
38   PROP_CARET,       /* Used only by AtkText implementors */
39   PROP_LAST         /* gobject convention */
40 };
41
42 enum {
43   CHILDREN_CHANGED,
44   LAST_SIGNAL
45 };
46
47 struct _AtkRelationSet
48 {
49   GArray     *relations;
50 };
51
52 struct _AtkRelation
53 {
54   GArray              *target;
55   AtkRelationType     relationship;
56 };
57
58
59 static void            atk_object_class_init       (AtkObjectClass  *klass);
60 static void            atk_object_init             (AtkObject       *accessible,
61                                                     AtkObjectClass  *klass);
62 static AtkRelationSet* atk_object_real_get_relation_set (AtkObject *accessible);
63
64 static void            atk_object_real_set_property(GObject         *object,
65                                                     guint            prop_id,
66                                                     const GValue    *value,
67                                                     GParamSpec      *pspec);
68 static void            atk_object_real_get_property(GObject         *object,
69                                                     guint            prop_id,
70                                                     GValue          *value,
71                                                     GParamSpec      *pspec);
72 static void            atk_object_finalize         (GObject         *object);
73
74 static gchar* state_names[NUM_POSSIBLE_STATES];
75
76 #if 0
77 static guint atk_object_signals[LAST_SIGNAL] = { 0, };
78 #endif
79
80 static gpointer parent_class = NULL;
81
82 static const gchar* atk_object_name_property_name = "accessible-name";
83 static const gchar* atk_object_name_property_state = "accessible-state";
84 static const gchar* atk_object_name_property_description = "accessible-description";
85
86 GType
87 atk_object_get_type (void)
88 {
89   static GType type = 0;
90
91   if (!type)
92     {
93       static const GTypeInfo typeInfo =
94       {
95         sizeof (AtkObjectClass),
96         (GBaseInitFunc) NULL,
97         (GBaseFinalizeFunc) NULL,
98         (GClassInitFunc) atk_object_class_init,
99         (GClassFinalizeFunc) NULL,
100         NULL,
101         sizeof (AtkObject),
102         0,
103         (GInstanceInitFunc) atk_object_init,
104       } ;
105       type = g_type_register_static (G_TYPE_OBJECT, "AtkObject", &typeInfo, 0) ;
106     }
107   return type;
108 }
109
110 static void
111 atk_object_class_init (AtkObjectClass *klass)
112 {
113   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
114
115   parent_class = g_type_class_ref (G_TYPE_OBJECT);
116
117   gobject_class->set_property = atk_object_real_set_property;
118   gobject_class->get_property = atk_object_real_get_property;
119   gobject_class->finalize = atk_object_finalize;
120
121   klass->get_relation_set = atk_object_real_get_relation_set;
122
123   state_names[ATK_STATE_ARMED]           = "armed";
124   state_names[ATK_STATE_BUSY]            = "busy";
125   state_names[ATK_STATE_CHECKED]         = "checked";
126   state_names[ATK_STATE_COLLAPSED]       = "collapsed";
127   state_names[ATK_STATE_EDITABLE]        = "editable";
128   state_names[ATK_STATE_EXPANDABLE]      = "expandable";
129   state_names[ATK_STATE_EXPANDED]        = "expanded";
130   state_names[ATK_STATE_FOCUSABLE]       = "focusable";
131   state_names[ATK_STATE_FOCUSED]         = "focused";
132   state_names[ATK_STATE_HORIZONTAL]      = "horizontal";
133   state_names[ATK_STATE_ICONIFIED]       = "iconified";
134   state_names[ATK_STATE_MODAL]           = "modal";
135   state_names[ATK_STATE_MULTI_LINE]      = "multi-line";
136   state_names[ATK_STATE_MULTISELECTABLE] = "multiselectable";
137   state_names[ATK_STATE_OPAQUE]          = "opaque";
138   state_names[ATK_STATE_PRESSED]         = "pressed";
139   state_names[ATK_STATE_RESIZABLE]       = "resizeable";
140   state_names[ATK_STATE_SELECTABLE]      = "selectable";
141   state_names[ATK_STATE_SELECTED]        = "selected";
142   state_names[ATK_STATE_SENSITIVE]       = "sensitive";
143   state_names[ATK_STATE_SHOWING]         = "showing";
144   state_names[ATK_STATE_SINGLE_LINE]     = "single-line";
145   state_names[ATK_STATE_TRANSIENT]       = "transient";
146   state_names[ATK_STATE_VERTICAL]        = "vertical";
147   state_names[ATK_STATE_VISIBLE]         = "visible";
148
149   klass->children_changed = NULL;
150
151   g_object_class_install_property (gobject_class,
152                                    PROP_NAME,
153                                    g_param_spec_string (atk_object_name_property_name,
154                                                         "Accessible Name",
155                                                         "Object instance\'s name formatted for "
156                                                            "assistive technology access",
157                                                         NULL,
158                                                         G_PARAM_READWRITE));
159   g_object_class_install_property (gobject_class,
160                                    PROP_DESCRIPTION,
161                                    g_param_spec_string (atk_object_name_property_description,
162                                                         "Accessible Description",
163                                                         "Description of an object, formatted for "
164                                                         "assistive technology access",
165                                                         NULL,
166                                                         G_PARAM_READWRITE));
167   g_object_class_install_property (gobject_class,
168                                    PROP_STATE,
169                                    g_param_spec_int    (atk_object_name_property_state,
170                                                         "Accessible State",
171                                                         "The current state of this object "
172                                                         "or its UI component",
173                                                         0,
174                                                         G_MAXINT,
175                                                         0,
176                                                         G_PARAM_WRITABLE));
177 #if 0
178   /* register some properties - these could be change signals instead */
179   g_object_class_install_property (gobject_class,
180                                    PROP_PARENT,
181                                    g_param_spec_ccallback ("accessible_parent", "Accessible Parent",
182                                                            "First accessible ancestor (container or object) "
183                                                            "which this object is a descendant of",
184                                                            G_PARAM_READWRITE));
185
186
187   g_object_class_install_property (gobject_class,
188                                    PROP_ROLE,
189                                    g_param_spec_ccallback ("accessible_role", "Accessible Role",
190                                                            "The user-interface role of this object",
191                                                            G_PARAM_READWRITE));
192   g_object_class_install_property (gobject_class,
193                                    PROP_STATE,
194                                    g_param_spec_ccallback ("accessible_state", "Accessible State",
195                                                            "The current state of this object "
196                                                            "or its UI component",
197                                                            G_PARAM_READWRITE));
198   g_object_class_install_property (gobject_class,
199                                    PROP_TEXT,
200                                    g_param_spec_ccallback ("accessible_text", "Accessible Text",
201                                                            "This object\'s accessible text contents",
202                                                            G_PARAM_READWRITE));
203   g_object_class_install_property (gobject_class,
204                                    PROP_CARET,
205                                    g_param_spec_ccallback ("accessible_caret", "Accessible Text Caret",
206                                                            "The current text caret state and position "
207                                                            "for this component",
208                                                            G_PARAM_READWRITE));
209   gaccessible_signals[CHILDREN_CHANGED] =
210     g_signal_newc ("accessible_children_changed",
211                    G_TYPE_FROM_CLASS (klass),
212                    G_SIGNAL_RUN_LAST,
213                    G_STRUCT_OFFSET (AtkObjectClass, children_changed), /* still need to declare and define this func */
214                    NULL,
215                    g_cclosure_marshal_VOID__UINT_POINTER,
216                    G_TYPE_NONE,
217                    2, G_TYPE_UINT, ATK_TYPE_OBJECT);
218 #endif
219 }
220
221 static void
222 atk_object_init  (AtkObject        *accessible,
223                   AtkObjectClass   *klass)
224 {
225     accessible->relation_set = g_malloc (sizeof (AtkRelationSet));
226     g_return_if_fail (accessible->relation_set != NULL);
227     accessible->relation_set->relations = NULL;
228 }
229
230 GType
231 atk_implementor_get_type (void)
232 {
233   static GType type = 0;
234
235   if (!type)
236     {
237       static const GTypeInfo typeInfo =
238       {
239         sizeof (AtkImplementorIface),
240         (GBaseInitFunc) NULL,
241         (GBaseFinalizeFunc) NULL,
242       } ;
243
244       type = g_type_register_static (G_TYPE_INTERFACE, "AtkImplementorIface", &typeInfo, 0) ;
245     }
246
247   return type;
248 }
249
250 G_CONST_RETURN gchar*
251 atk_object_get_name (AtkObject *accessible)
252 {
253   AtkObjectClass *klass;
254
255   g_return_val_if_fail (accessible != NULL, NULL);
256   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
257
258   klass = ATK_OBJECT_GET_CLASS (accessible);
259   if (klass->get_name)
260     return (klass->get_name) (accessible);
261   else
262     return NULL;
263 }
264
265 G_CONST_RETURN gchar*
266 atk_object_get_description (AtkObject *accessible)
267 {
268   AtkObjectClass *klass;
269
270   g_return_val_if_fail (accessible != NULL, NULL);
271   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
272
273   klass = ATK_OBJECT_GET_CLASS (accessible);
274   if (klass->get_description)
275     return (klass->get_description) (accessible);
276   else
277     return NULL;
278 }
279
280 AtkObject*
281 atk_object_get_parent (AtkObject *accessible)
282 {
283   AtkObjectClass *klass;
284
285   g_return_val_if_fail (accessible != NULL, NULL);
286   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
287
288   klass = ATK_OBJECT_GET_CLASS (accessible);
289   if (klass->get_parent)
290     return (klass->get_parent) (accessible);
291   else
292     return NULL;
293 }
294
295 gint
296 atk_object_get_n_accessible_children (AtkObject *accessible)
297 {
298   AtkObjectClass *klass;
299
300   g_return_val_if_fail (accessible != NULL, 0);
301   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
302
303   klass = ATK_OBJECT_GET_CLASS (accessible);
304   if (klass->get_n_children)
305     return (klass->get_n_children) (accessible);
306   else
307     return 0;
308 }
309
310 AtkObject*
311 atk_object_ref_accessible_child (AtkObject   *accessible,
312                                  gint        i)
313 {
314   AtkObjectClass *klass;
315
316   g_return_val_if_fail (accessible != NULL, NULL);
317   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
318
319   klass = ATK_OBJECT_GET_CLASS (accessible);
320   if (klass->ref_child)
321     return (klass->ref_child) (accessible, i);
322   else
323     return NULL;
324 }
325
326 AtkRelationSet*
327 atk_object_get_relation_set (AtkObject *accessible)
328 {
329   AtkObjectClass *klass;
330
331   g_return_val_if_fail (accessible != NULL, NULL);
332   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
333
334   klass = ATK_OBJECT_GET_CLASS (accessible);
335   if (klass->get_relation_set)
336     return (klass->get_relation_set) (accessible);
337   else
338     return NULL;
339 }
340
341 AtkRole
342 atk_role_register (const gchar *name)
343 {
344   /* TODO: associate name with new type */
345   static guint type = ATK_ROLE_LAST_DEFINED;
346   return (++type);
347 }
348
349 AtkRole
350 atk_object_get_role (AtkObject *accessible) {
351   AtkObjectClass *klass;
352
353   g_return_val_if_fail (accessible != NULL, ATK_ROLE_UNKNOWN);
354   g_return_val_if_fail (ATK_IS_OBJECT (accessible), ATK_ROLE_UNKNOWN);
355
356   klass = ATK_OBJECT_GET_CLASS (accessible);
357   if (klass->get_role)
358     return (klass->get_role) (accessible);
359   else
360     return ATK_ROLE_UNKNOWN;
361 }
362
363 AtkStateType
364 atk_state_type_register (const gchar *name)
365 {
366   /* TODO: associate name with new type */
367   static guint type = ATK_STATE_LAST_DEFINED;
368   if (type < NUM_POSSIBLE_STATES) {
369     return (++type);
370   }
371   return ATK_STATE_INVALID; /* caller needs to check */
372 }
373
374 AtkState
375 atk_object_get_state (AtkObject *accessible) {
376   AtkObjectClass *klass;
377
378   g_return_val_if_fail (accessible != NULL, 0);
379   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
380
381   klass = ATK_OBJECT_GET_CLASS (accessible);
382   if (klass->get_state)
383     return (klass->get_state) (accessible);
384   else
385     return 0;
386 }
387
388 gint
389 atk_object_get_index_in_parent (AtkObject *accessible)
390 {
391   AtkObjectClass *klass;
392
393   g_return_val_if_fail (accessible != NULL, -1);
394   g_return_val_if_fail (ATK_OBJECT (accessible), -1);
395
396   klass = ATK_OBJECT_GET_CLASS (accessible);
397   if (klass->get_index_in_parent)
398     return (klass->get_index_in_parent) (accessible);
399   else
400     return -1;
401 }
402
403 void
404 atk_object_set_name (AtkObject    *accessible,
405                      const gchar  *name)
406 {
407   AtkObjectClass *klass;
408
409   g_return_if_fail (accessible != NULL);
410   g_return_if_fail (ATK_IS_OBJECT (accessible));
411   g_return_if_fail (name != NULL);
412
413   klass = ATK_OBJECT_GET_CLASS (accessible);
414   if (klass->set_name)
415   {
416     (klass->set_name) (accessible, name);
417     g_object_notify (G_OBJECT (accessible), atk_object_name_property_name);
418   }
419 }
420
421 void
422 atk_object_set_description (AtkObject   *accessible,
423                             const gchar *description)
424 {
425   AtkObjectClass *klass;
426
427   g_return_if_fail (accessible != NULL);
428   g_return_if_fail (ATK_IS_OBJECT (accessible));
429   g_return_if_fail (description != NULL);
430
431   klass = ATK_OBJECT_GET_CLASS (accessible);
432   if (klass->set_description)
433   {
434     (klass->set_description) (accessible, description);
435     g_object_notify (G_OBJECT (accessible), atk_object_name_property_description);
436   }
437 }
438
439 void
440 atk_object_set_parent (AtkObject *accessible,
441                        AtkObject *parent)
442 {
443   AtkObjectClass *klass;
444
445   g_return_if_fail (accessible != NULL);
446   g_return_if_fail (ATK_IS_OBJECT (accessible));
447
448   klass = ATK_OBJECT_GET_CLASS (accessible);
449   if (klass->set_parent)
450     (klass->set_parent) (accessible, parent);
451 }
452
453 void
454 atk_object_set_role (AtkObject *accessible, 
455                      AtkRole   role)
456 {
457   AtkObjectClass *klass;
458
459   g_return_if_fail (accessible != NULL);
460   g_return_if_fail (ATK_IS_OBJECT (accessible));
461
462   klass = ATK_OBJECT_GET_CLASS (accessible);
463   if (klass->set_role)
464     (klass->set_role) (accessible, role);
465 }
466
467 guint
468 atk_object_connect_property_change_handler (AtkObject *accessible,
469                                             AtkPropertyChangeHandler *handler)
470 {
471   AtkObjectClass *klass;
472
473   g_return_val_if_fail (accessible != NULL, 0);
474   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
475   g_return_val_if_fail ((handler != NULL), 0);
476
477   klass = ATK_OBJECT_GET_CLASS (accessible);
478   if (klass->connect_property_change_handler)
479     return (klass->connect_property_change_handler) (accessible, handler);
480   else
481     return 0;
482 }
483
484 void
485 atk_object_remove_property_change_handler  (AtkObject *accessible,
486                                             guint      handler_id)
487 {
488   AtkObjectClass *klass;
489
490   g_return_if_fail (accessible != NULL);
491   g_return_if_fail (ATK_IS_OBJECT (accessible));
492
493   klass = ATK_OBJECT_GET_CLASS (accessible);
494   if (klass->remove_property_change_handler)
495     (klass->remove_property_change_handler) (accessible, handler_id);
496 }
497
498 AtkRelationType
499 atk_relation_type_register (const gchar *name)
500 {
501   /* TODO: associate name with new type */
502   static guint type = ATK_RELATION_LAST_DEFINED;
503   return (++type);
504 }
505
506 AtkRelation*
507 atk_relation_new (GArray          *target,
508                   AtkRelationType relationship)
509 {
510   AtkRelation* relation;
511   g_return_val_if_fail (target != NULL, NULL);
512
513   relation = (AtkRelation *) g_malloc (sizeof (AtkRelation));
514
515   g_return_val_if_fail ((relation != NULL), NULL);
516
517   relation->target = target;
518   relation->relationship = relationship;
519
520   return relation;
521 }
522
523 gboolean
524 atk_relation_set_contains (AtkRelationSet   *set,
525                            AtkRelationType  relationship)
526 {
527   GArray *array_item;
528   AtkRelation *item;
529   gint  i;
530
531   g_return_val_if_fail (set != NULL, FALSE);
532
533   array_item = set->relations;
534   if (array_item == NULL)
535     return FALSE;
536   for (i = 0; i < array_item->len; i++)
537   {
538     item = g_array_index (array_item, AtkRelation*, i);
539     if (item->relationship == relationship)
540       return TRUE;
541   }
542   return FALSE;
543 }
544
545 void
546 atk_relation_set_remove (AtkRelationSet *set,
547                          AtkRelation    *relation)
548 {
549   GArray *array_item;
550   AtkRelation *item;
551   gint  i;
552
553   g_return_if_fail (set != NULL);
554   g_return_if_fail (relation != NULL);
555
556   array_item = set->relations;
557   if (array_item == NULL)
558     return;
559   for (i = 0; i < array_item->len; i++)
560   {
561     item = g_array_index (array_item, AtkRelation*, i);
562     if (item == relation)
563     {
564       g_array_remove_index (array_item, i);
565       return;
566     }
567   }
568 }
569
570 void
571 atk_relation_set_add (AtkRelationSet *set,
572                       AtkRelation    *relation)
573 {
574   g_return_if_fail (set != NULL);
575   g_return_if_fail (relation != NULL);
576
577   if (set->relations == NULL)
578   {
579     set->relations = g_array_new (FALSE, TRUE, sizeof (AtkRelation));
580   }
581   set->relations = g_array_append_val (set->relations, relation);
582 }
583
584 gint
585 atk_relation_set_get_n_relations (AtkRelationSet *set)
586 {
587   g_return_val_if_fail (set != NULL, 0);
588
589   if (set->relations == NULL)
590     return 0;
591
592   return set->relations->len;
593 }
594
595 AtkRelation*
596 atk_relation_set_get_relation (AtkRelationSet *set,
597                                gint           i)
598 {
599   GArray *array_item;
600   AtkRelation* item;
601
602   g_return_val_if_fail (set != NULL, NULL);
603   g_return_val_if_fail (i >= 0, NULL);
604
605   array_item = set->relations;
606   if (array_item == NULL)
607     return NULL;
608   item = g_array_index (array_item, AtkRelation*, i);
609   if (item == NULL)
610     return NULL;
611
612   return item;
613 }
614
615 AtkRelation*
616 atk_relation_set_get_relation_by_type (AtkRelationSet  *set,
617                                        AtkRelationType relationship)
618 {
619   GArray *array_item;
620   AtkRelation *item;
621   gint i;
622
623   g_return_val_if_fail (set != NULL, NULL);
624
625   array_item = set->relations;
626   if (array_item == NULL)
627     return NULL;
628   for (i = 0; i < array_item->len; i++)
629   {
630     item = g_array_index (array_item, AtkRelation*, i);
631     if (item->relationship == relationship)
632       return item;
633   }
634   return NULL;
635 }
636
637 AtkRelationType
638 atk_relation_get_type (AtkRelation *relation)
639 {
640   g_return_val_if_fail (relation != NULL, 0);
641   return relation->relationship;
642 }
643
644 GArray*
645 atk_relation_get_target (AtkRelation *relation)
646 {
647   g_return_val_if_fail (relation != NULL, 0);
648   return relation->target;
649 }
650
651 G_CONST_RETURN gchar*
652 atk_state_mask_get_name (AtkStateMask state)
653 {
654   gint n;
655
656   if (state == 0)
657     return NULL;
658
659   for (n=0; n<NUM_POSSIBLE_STATES; ++n)
660     {
661       /* fall through and return null if multiple bits are set */
662       if (state == (1 << n)) return state_names[n];
663     }
664
665   return NULL;
666 }
667
668 AtkStateMask
669 atk_state_mask_for_name (const gchar *name)
670 {
671   gint i;
672
673   g_return_val_if_fail ((strlen(name)>0), 0);
674   for (i=0; i<NUM_POSSIBLE_STATES; ++i)
675     {
676       if (!strcmp(name, state_names[i])) return ATK_STATE(i);
677     }
678   return 0;
679 }
680
681 /**
682  * Return a reference to an object's AtkObject implementation, if
683  * the object implements AtkObjectIface.
684  * @object: The GObject instance which should implement #AtkImplementorIface
685  * if a non-null return value is required.
686  */
687 AtkObject *
688 atk_implementor_ref_accessible (AtkImplementor *object)
689 {
690   AtkImplementorIface *iface;
691   AtkObject           *accessible = NULL;
692
693   g_return_val_if_fail (object != NULL, NULL);
694   g_return_val_if_fail (ATK_IS_IMPLEMENTOR (object), NULL);
695
696   iface = ATK_IMPLEMENTOR_GET_IFACE (object);
697
698   if (iface != NULL) 
699      accessible =  iface->ref_accessible (object);
700
701   g_return_val_if_fail ((accessible != NULL), NULL);
702
703   return accessible;
704 }
705
706 AtkRelationSet*
707 atk_object_real_get_relation_set (AtkObject *accessible)
708 {
709     return accessible->relation_set;
710 }
711
712 static void
713 atk_object_real_set_property (GObject      *object,
714                               guint         prop_id,
715                               const GValue *value,
716                               GParamSpec   *pspec)
717 {
718   AtkObject *accessible;
719
720   accessible = ATK_OBJECT (object);
721
722   switch (prop_id)
723   {
724     case PROP_NAME:
725       atk_object_set_name (accessible, g_value_get_string (value));
726       break;
727     case PROP_DESCRIPTION:
728       atk_object_set_description (accessible, g_value_get_string (value));
729       break;
730     case PROP_STATE:
731       g_print ("This interface does not support setting the state of an accessible object\n");
732       break;
733     default:
734       break;
735   }
736 }
737
738 static void
739 atk_object_real_get_property (GObject      *object,
740                          guint         prop_id,
741                          GValue       *value,
742                          GParamSpec   *pspec)
743 {
744   AtkObject *accessible;
745
746   accessible = ATK_OBJECT (object);
747
748   switch (prop_id)
749   {
750     case PROP_NAME:
751       g_value_set_string (value, atk_object_get_name (accessible));
752       break;
753     case PROP_DESCRIPTION:
754       g_value_set_string (value, atk_object_get_description (accessible));
755       break;
756     case PROP_STATE:
757       g_value_set_int (value, atk_object_get_state (accessible));
758       break;
759     default:
760       break;
761   }
762 }
763
764 static void
765 atk_object_finalize (GObject *object)
766 {
767   AtkObject        *accessible;
768   GArray           *relations;
769
770   g_return_if_fail (ATK_IS_OBJECT (object));
771
772   accessible = ATK_OBJECT (object);
773
774   g_free (accessible->name);
775   g_free (accessible->description);
776
777   /*
778    * Free memory allocated for relations and relation sets;
779    */
780   relations = accessible->relation_set->relations;
781   if (relations)
782   {
783     gint        len = relations->len;
784     gint        i;
785     AtkRelation *relation;
786
787     for (i = 0; i < len; i++)
788     {
789       relation = g_array_index (relations, AtkRelation*, i);
790       g_array_free (relation->target, TRUE);
791     }
792     g_array_free (relations, TRUE);
793   }
794   g_free (accessible->relation_set);
795
796   G_OBJECT_CLASS (parent_class)->finalize (object);
797 }