Fix leak; report and patch supplied by Sebastian Rittau
[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 <string.h>
21
22 #include <glib-object.h>
23
24 #include "atk.h"
25 #include "atkmarshal.h"
26 #include "atk-enum-types.h"
27
28 GPtrArray *extra_roles = NULL;
29
30 enum
31 {
32   PROP_0,  /* gobject convention */
33
34   PROP_NAME,
35   PROP_DESCRIPTION,
36   PROP_PARENT,      /* ancestry has changed */
37   PROP_VALUE,
38   PROP_ROLE,
39   PROP_LAYER,
40   PROP_MDI_ZORDER,
41   PROP_TABLE_CAPTION,
42   PROP_TABLE_COLUMN_DESCRIPTION,
43   PROP_TABLE_COLUMN_HEADER,
44   PROP_TABLE_ROW_DESCRIPTION,
45   PROP_TABLE_ROW_HEADER,
46   PROP_TABLE_SUMMARY,
47   PROP_LAST         /* gobject convention */
48 };
49
50 enum {
51   CHILDREN_CHANGED,
52   FOCUS_EVENT,
53   PROPERTY_CHANGE,
54   STATE_CHANGE,
55   VISIBLE_DATA_CHANGED,
56   
57   LAST_SIGNAL
58 };
59
60 static void            atk_object_class_init        (AtkObjectClass  *klass);
61 static void            atk_object_init              (AtkObject       *accessible,
62                                                      AtkObjectClass  *klass);
63 static AtkRelationSet* atk_object_real_ref_relation_set 
64                                                     (AtkObject       *accessible);
65
66 static void            atk_object_real_set_property (GObject         *object,
67                                                      guint            prop_id,
68                                                      const GValue    *value,
69                                                      GParamSpec      *pspec);
70 static void            atk_object_real_get_property (GObject         *object,
71                                                      guint            prop_id,
72                                                      GValue          *value,
73                                                      GParamSpec      *pspec);
74 static void            atk_object_finalize          (GObject         *object);
75 static G_CONST_RETURN gchar*
76                        atk_object_real_get_name     (AtkObject       *object);
77 static G_CONST_RETURN gchar*
78                        atk_object_real_get_description    
79                                                    (AtkObject       *object);
80 static AtkObject*      atk_object_real_get_parent  (AtkObject       *object);
81 static AtkRole         atk_object_real_get_role    (AtkObject       *object);
82 static AtkLayer        atk_object_real_get_layer   (AtkObject       *object);
83 static AtkStateSet*    atk_object_real_ref_state_set
84                                                    (AtkObject       *object);
85 static void            atk_object_real_set_name    (AtkObject       *object,
86                                                     const gchar     *name);
87 static void            atk_object_real_set_description
88                                                    (AtkObject       *object,
89                                                     const gchar     *description);
90 static void            atk_object_real_set_parent  (AtkObject       *object,
91                                                     AtkObject       *parent);
92 static void            atk_object_real_set_role    (AtkObject       *object,
93                                                     AtkRole         role);
94 static guint           atk_object_real_connect_property_change_handler
95                                                    (AtkObject       *obj,
96                                                     AtkPropertyChangeHandler
97                                                                     *handler);
98 static void            atk_object_real_remove_property_change_handler
99                                                    (AtkObject       *obj,
100                                                     guint           handler_id);
101 static void            atk_object_notify           (GObject         *obj,
102                                                     GParamSpec      *pspec);
103
104
105 static guint atk_object_signals[LAST_SIGNAL] = { 0, };
106
107 static gpointer parent_class = NULL;
108
109 static const gchar* atk_object_name_property_name = "accessible-name";
110 static const gchar* atk_object_name_property_description = "accessible-description";
111 static const gchar* atk_object_name_property_parent = "accessible-parent";
112 static const gchar* atk_object_name_property_value = "accessible-value";
113 static const gchar* atk_object_name_property_role = "accessible-role";
114 static const gchar* atk_object_name_property_component_layer = "accessible-component-layer";
115 static const gchar* atk_object_name_property_component_mdi_zorder = "accessible-component-mdi-zorder";
116 static const gchar* atk_object_name_property_table_caption = "accessible-table-caption";
117 static const gchar* atk_object_name_property_table_column_description = "accessible-table-column-description";
118 static const gchar* atk_object_name_property_table_column_header = "accessible-table-column-header";
119 static const gchar* atk_object_name_property_table_row_description = "accessible-table-row-description";
120 static const gchar* atk_object_name_property_table_row_header = "accessible-table-row-header";
121 static const gchar* atk_object_name_property_table_summary = "accessible-table-summary";
122
123 GType
124 atk_object_get_type (void)
125 {
126   static GType type = 0;
127
128   if (!type)
129     {
130       static const GTypeInfo typeInfo =
131       {
132         sizeof (AtkObjectClass),
133         (GBaseInitFunc) NULL,
134         (GBaseFinalizeFunc) NULL,
135         (GClassInitFunc) atk_object_class_init,
136         (GClassFinalizeFunc) NULL,
137         NULL,
138         sizeof (AtkObject),
139         0,
140         (GInstanceInitFunc) atk_object_init,
141       } ;
142       type = g_type_register_static (G_TYPE_OBJECT, "AtkObject", &typeInfo, 0) ;
143     }
144   return type;
145 }
146
147 static void
148 atk_object_class_init (AtkObjectClass *klass)
149 {
150   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
151
152   parent_class = g_type_class_peek_parent (klass);
153
154   gobject_class->set_property = atk_object_real_set_property;
155   gobject_class->get_property = atk_object_real_get_property;
156   gobject_class->finalize = atk_object_finalize;
157   gobject_class->notify = atk_object_notify;
158
159   klass->get_name = atk_object_real_get_name;
160   klass->get_description = atk_object_real_get_description;
161   klass->get_parent = atk_object_real_get_parent;
162   klass->get_n_children = NULL;
163   klass->ref_child = NULL;
164   klass->get_index_in_parent = NULL;
165   klass->ref_relation_set = atk_object_real_ref_relation_set;
166   klass->get_role = atk_object_real_get_role;
167   klass->get_layer = atk_object_real_get_layer;
168   klass->get_mdi_zorder = NULL;
169   klass->ref_state_set = atk_object_real_ref_state_set;
170   klass->set_name = atk_object_real_set_name;
171   klass->set_description = atk_object_real_set_description;
172   klass->set_parent = atk_object_real_set_parent;
173   klass->set_role = atk_object_real_set_role;
174   klass->connect_property_change_handler = 
175          atk_object_real_connect_property_change_handler;
176   klass->remove_property_change_handler = 
177          atk_object_real_remove_property_change_handler;
178
179   /*
180    * We do not define default signal handlers here
181    */
182   klass->children_changed = NULL;
183   klass->focus_event = NULL;
184   klass->property_change = NULL;
185   klass->visible_data_changed = NULL;
186
187   g_object_class_install_property (gobject_class,
188                                    PROP_NAME,
189                                    g_param_spec_string (atk_object_name_property_name,
190                                                         "Accessible Name",
191                                                         "Object instance\'s name formatted for "
192                                                            "assistive technology access",
193                                                         NULL,
194                                                         G_PARAM_READWRITE));
195   g_object_class_install_property (gobject_class,
196                                    PROP_DESCRIPTION,
197                                    g_param_spec_string (atk_object_name_property_description,
198                                                         "Accessible Description",
199                                                         "Description of an object, formatted for "
200                                                         "assistive technology access",
201                                                         NULL,
202                                                         G_PARAM_READWRITE));
203   g_object_class_install_property (gobject_class,
204                                    PROP_PARENT,
205                                    g_param_spec_object (atk_object_name_property_parent,
206                                                         "Accessible Parent",
207                                                         "Is used to notify that the parent has changed ",
208                                                         ATK_TYPE_OBJECT,
209                                                         G_PARAM_READWRITE));
210   g_object_class_install_property (gobject_class,
211                                    PROP_VALUE,
212                                    g_param_spec_double (atk_object_name_property_value,
213                                                         "Accessible Value",
214                                                         "Is used to notify that the value has changed ",
215                                                         0.0,
216                                                         G_MAXDOUBLE,
217                                                         0.0,
218                                                         G_PARAM_READWRITE));
219   g_object_class_install_property (gobject_class,
220                                    PROP_ROLE,
221                                    g_param_spec_int    (atk_object_name_property_role,
222                                                         "Accessible Role",
223                                                         "The accessible role of this object ",
224                                                         0,
225                                                         G_MAXINT,
226                                                         0,
227                                                         G_PARAM_READWRITE));
228   g_object_class_install_property (gobject_class,
229                                    PROP_LAYER,
230                                    g_param_spec_int    (atk_object_name_property_component_layer,
231                                                         "Accessible Layer",
232                                                         "The accessible layer of this object ",
233                                                         0,
234                                                         G_MAXINT,
235                                                         0,
236                                                         G_PARAM_READABLE));
237   g_object_class_install_property (gobject_class,
238                                    PROP_MDI_ZORDER,
239                                    g_param_spec_int    (atk_object_name_property_component_mdi_zorder,
240                                                         "Accessible MDI Value",
241                                                         "The accessible MDI value of this object ",
242                                                         G_MININT,
243                                                         G_MAXINT,
244                                                         G_MININT,
245                                                         G_PARAM_READABLE));
246   g_object_class_install_property (gobject_class,
247                                    PROP_TABLE_CAPTION,
248                                    g_param_spec_string (atk_object_name_property_table_caption,
249                                                         "Accessible Table Caption",
250                                                         "Is used to notify that the table caption has changed ",
251                                                         NULL,
252                                                         G_PARAM_READWRITE));
253   g_object_class_install_property (gobject_class,
254                                    PROP_TABLE_COLUMN_HEADER,
255                                    g_param_spec_object (atk_object_name_property_table_column_header,
256                                                         "Accessible Table Column Header",
257                                                         "Is used to notify that the table column header has changed ",
258                                                         ATK_TYPE_OBJECT,
259                                                         G_PARAM_READWRITE));
260   g_object_class_install_property (gobject_class,
261                                    PROP_TABLE_COLUMN_DESCRIPTION,
262                                    g_param_spec_string (atk_object_name_property_table_column_description,
263                                                         "Accessible Table Column Description",
264                                                         "Is used to notify that the table columnscription has changed ",
265                                                         NULL,
266                                                         G_PARAM_READWRITE));
267   g_object_class_install_property (gobject_class,
268                                    PROP_TABLE_ROW_HEADER,
269                                    g_param_spec_object (atk_object_name_property_table_row_header,
270                                                         "Accessible Table Row Header",
271                                                         "Is used to notify that the table row header has changed ",
272                                                         ATK_TYPE_OBJECT,
273                                                         G_PARAM_READWRITE));
274   g_object_class_install_property (gobject_class,
275                                    PROP_TABLE_ROW_DESCRIPTION,
276                                    g_param_spec_string (atk_object_name_property_table_row_description,
277                                                         "Accessible Table Row Description",
278                                                         "Is used to notify that the table row description has changed ",
279                                                         NULL,
280                                                         G_PARAM_READWRITE));
281   g_object_class_install_property (gobject_class,
282                                    PROP_TABLE_SUMMARY,
283                                    g_param_spec_object (atk_object_name_property_table_summary,
284                                                         "Accessible Table Summary",
285                                                         "Is used to notify that the table summary has changed ",
286                                                         ATK_TYPE_OBJECT,
287                                                         G_PARAM_READWRITE));
288   /*
289    * The signal "children_changed" supports two details:
290    * "add" and "remove"
291    */
292   atk_object_signals[CHILDREN_CHANGED] =
293     g_signal_new ("children_changed",
294                   G_TYPE_FROM_CLASS (klass),
295                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
296                   G_STRUCT_OFFSET (AtkObjectClass, children_changed),
297                   NULL, NULL,
298                   g_cclosure_marshal_VOID__UINT_POINTER,
299                   G_TYPE_NONE,
300                   2, G_TYPE_UINT, G_TYPE_POINTER);
301   atk_object_signals[FOCUS_EVENT] =
302     g_signal_new ("focus_event",
303                   G_TYPE_FROM_CLASS (klass),
304                   G_SIGNAL_RUN_LAST,
305                   G_STRUCT_OFFSET (AtkObjectClass, focus_event), 
306                   NULL, NULL,
307                   g_cclosure_marshal_VOID__BOOLEAN,
308                   G_TYPE_NONE,
309                   1, G_TYPE_BOOLEAN);
310   atk_object_signals[PROPERTY_CHANGE] =
311     g_signal_new ("property_change",
312                   G_TYPE_FROM_CLASS (klass),
313                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
314                   G_STRUCT_OFFSET (AtkObjectClass, property_change),
315                   (GSignalAccumulator) NULL, NULL,
316                   g_cclosure_marshal_VOID__POINTER,
317                   G_TYPE_NONE, 1,
318                   G_TYPE_POINTER);
319   /*
320    * The "state_change" signal supports details, one for each accessible 
321    * state type
322    * (see atkstate.c).
323    */
324   atk_object_signals[STATE_CHANGE] =
325     g_signal_new ("state_change",
326                   G_TYPE_FROM_CLASS (klass),
327                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
328                   G_STRUCT_OFFSET (AtkObjectClass, state_change),
329                   (GSignalAccumulator) NULL, NULL,
330                   atk_marshal_VOID__STRING_BOOLEAN,
331                   G_TYPE_NONE, 2,
332                   G_TYPE_STRING,
333                   G_TYPE_BOOLEAN);
334   atk_object_signals[VISIBLE_DATA_CHANGED] =
335     g_signal_new ("visible_data_changed",
336                   G_TYPE_FROM_CLASS (klass),
337                   G_SIGNAL_RUN_LAST,
338                   G_STRUCT_OFFSET (AtkObjectClass, visible_data_changed),
339                   (GSignalAccumulator) NULL, NULL,
340                   g_cclosure_marshal_VOID__VOID,
341                   G_TYPE_NONE, 0);
342 }
343
344 static void
345 atk_object_init  (AtkObject        *accessible,
346                   AtkObjectClass   *klass)
347 {
348   accessible->name = NULL;
349   accessible->description = NULL;
350   accessible->accessible_parent = NULL;
351   accessible->relation_set = atk_relation_set_new();
352   accessible->role = ATK_ROLE_UNKNOWN;
353 }
354
355 GType
356 atk_implementor_get_type (void)
357 {
358   static GType type = 0;
359
360   if (!type)
361     {
362       static const GTypeInfo typeInfo =
363       {
364         sizeof (AtkImplementorIface),
365         (GBaseInitFunc) NULL,
366         (GBaseFinalizeFunc) NULL,
367       } ;
368
369       type = g_type_register_static (G_TYPE_INTERFACE, "AtkImplementorIface", &typeInfo, 0) ;
370     }
371
372   return type;
373 }
374
375 /**
376  * atk_object_get_name:
377  * @accessible: an #AtkObject
378  *
379  * Gets the accessible name of the accessible.
380  *
381  * Returns: a character string representing the accessible name of the object.
382  **/
383 G_CONST_RETURN gchar*
384 atk_object_get_name (AtkObject *accessible)
385 {
386   AtkObjectClass *klass;
387
388   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
389
390   klass = ATK_OBJECT_GET_CLASS (accessible);
391   if (klass->get_name)
392     return (klass->get_name) (accessible);
393   else
394     return NULL;
395 }
396
397 /**
398  * atk_object_get_description:
399  * @accessible: an #AtkObject
400  *
401  * Gets the accessible description of the accessible.
402  *
403  * Returns: a character string representing the accessible description
404  * of the accessible.
405  *
406  **/
407 G_CONST_RETURN gchar*
408 atk_object_get_description (AtkObject *accessible)
409 {
410   AtkObjectClass *klass;
411
412   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
413
414   klass = ATK_OBJECT_GET_CLASS (accessible);
415   if (klass->get_description)
416     return (klass->get_description) (accessible);
417   else
418     return NULL;
419 }
420
421 /**
422  * atk_object_get_parent:
423  * @accessible: an #AtkObject
424  *
425  * Gets the accessible parent of the accessible.
426  *
427  * Returns: a #AtkObject representing the accessible parent of the accessible
428  **/
429 AtkObject*
430 atk_object_get_parent (AtkObject *accessible)
431 {
432   AtkObjectClass *klass;
433
434   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
435
436   klass = ATK_OBJECT_GET_CLASS (accessible);
437   if (klass->get_parent)
438     return (klass->get_parent) (accessible);
439   else
440     return NULL;
441 }
442
443 /**
444  * atk_object_get_n_accessible_children:
445  * @accessible: an #AtkObject
446  *
447  * Gets the number of accessible children of the accessible.
448  *
449  * Returns: an integer representing the number of accessible children
450  * of the accessible.
451  **/
452 gint
453 atk_object_get_n_accessible_children (AtkObject *accessible)
454 {
455   AtkObjectClass *klass;
456
457   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
458
459   klass = ATK_OBJECT_GET_CLASS (accessible);
460   if (klass->get_n_children)
461     return (klass->get_n_children) (accessible);
462   else
463     return 0;
464 }
465
466 /**
467  * atk_object_ref_accessible_child:
468  * @accessible: an #AtkObject
469  * @i: a gint representing the position of the child, starting from 0
470  *
471  * Gets a reference to the specified accessible child of the object.
472  * The accessible children are 0-based so the first accessible child is
473  * at index 0, the second at index 1 and so on.
474  *
475  * Returns: an #AtkObject representing the specified accessible child
476  * of the accessible.
477  **/
478 AtkObject*
479 atk_object_ref_accessible_child (AtkObject   *accessible,
480                                  gint        i)
481 {
482   AtkObjectClass *klass;
483
484   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
485
486   klass = ATK_OBJECT_GET_CLASS (accessible);
487   if (klass->ref_child)
488     return (klass->ref_child) (accessible, i);
489   else
490     return NULL;
491 }
492
493 /**
494  * atk_object_ref_relation_set:
495  * @accessible: an #AtkObject
496  *
497  * Gets the #AtkRelationSet associated with the object.
498  *
499  * Returns: an #AtkRelationSet representing the relation set of the object.
500  **/
501 AtkRelationSet*
502 atk_object_ref_relation_set (AtkObject *accessible)
503 {
504   AtkObjectClass *klass;
505
506   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
507
508   klass = ATK_OBJECT_GET_CLASS (accessible);
509   if (klass->ref_relation_set)
510     return (klass->ref_relation_set) (accessible);
511   else
512     return NULL;
513 }
514
515 /**
516  * atk_role_register:
517  * @name: a character string describing the new role.
518  *
519  * Registers the role specified by @name.
520  *
521  * Returns: an #AtkRole for the new role.
522  **/
523 AtkRole
524 atk_role_register (const gchar *name)
525 {
526   if (!extra_roles)
527     extra_roles = g_ptr_array_new ();
528
529   g_ptr_array_add (extra_roles, g_strdup (name));
530   return extra_roles->len + ATK_ROLE_LAST_DEFINED;
531 }
532
533 /**
534  * atk_object_get_role:
535  * @accessible: an #AtkObject
536  *
537  * Gets the role of the accessible.
538  *
539  * Returns: an #AtkRole which is the role of the accessible
540  **/
541 AtkRole
542 atk_object_get_role (AtkObject *accessible) 
543 {
544   AtkObjectClass *klass;
545
546   g_return_val_if_fail (ATK_IS_OBJECT (accessible), ATK_ROLE_UNKNOWN);
547
548   klass = ATK_OBJECT_GET_CLASS (accessible);
549   if (klass->get_role)
550     return (klass->get_role) (accessible);
551   else
552     return ATK_ROLE_UNKNOWN;
553 }
554
555 /**
556  * atk_object_get_layer:
557  * @accessible: an #AtkObject
558  *
559  * Gets the layer of the accessible.
560  * DEPRECATED: use atk_component_get_layer instead!
561  *
562  * Returns: an #AtkLayer which is the layer of the accessible
563  **/
564 AtkLayer
565 atk_object_get_layer (AtkObject *accessible) 
566 {
567   AtkObjectClass *klass;
568
569   g_return_val_if_fail (ATK_IS_OBJECT (accessible), ATK_LAYER_INVALID);
570
571   klass = ATK_OBJECT_GET_CLASS (accessible);
572   if (klass->get_layer)
573     return (klass->get_layer) (accessible);
574   else
575     return ATK_LAYER_INVALID;
576 }
577
578 /**
579  * atk_object_get_mdi_zorder:
580  * @accessible: an #AtkObject
581  *
582  * Gets the zorder of the accessible. The value G_MININT will be returned 
583  * if the layer of the accessible is not ATK_LAYER_MDI.
584  * DEPRECATED: use atk_component_get_mdi_zorder instead!
585  *
586  * Returns: a gint which is the zorder of the accessible, i.e. the depth at 
587  * which the component is shown in relation to other components in the same 
588  * container.
589  **/
590 gint
591 atk_object_get_mdi_zorder (AtkObject *accessible) 
592 {
593   AtkObjectClass *klass;
594
595   g_return_val_if_fail (ATK_IS_OBJECT (accessible), G_MININT);
596
597   klass = ATK_OBJECT_GET_CLASS (accessible);
598   if (klass->get_mdi_zorder)
599     return (klass->get_mdi_zorder) (accessible);
600   else
601     return G_MININT;
602 }
603
604 /**
605  * atk_object_ref_state_set:
606  * @accessible: an #AtkObject
607  *
608  * Gets a reference to the state set of the accessible; the caller must
609  * unreference it when it is no longer needed.
610  *
611  * Returns: a reference to an #AtkStateSet which is the state
612  * set of the accessible
613  **/
614 AtkStateSet*
615 atk_object_ref_state_set (AtkObject *accessible) 
616 {
617   AtkObjectClass *klass;
618
619   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
620
621   klass = ATK_OBJECT_GET_CLASS (accessible);
622   if (klass->ref_state_set)
623     return (klass->ref_state_set) (accessible);
624   else
625     return NULL;
626 }
627
628 /**
629  * atk_object_get_index_in_parent:
630  * @accessible: an #AtkObject
631  *
632  * Gets the 0-based index of this accessible in its parent; returns -1 if the
633  * accessible does not have an accessible parent.
634  *
635  * Returns: an integer which is the index of the accessible in its parent
636  **/
637 gint
638 atk_object_get_index_in_parent (AtkObject *accessible)
639 {
640   AtkObjectClass *klass;
641
642   g_return_val_if_fail (ATK_OBJECT (accessible), -1);
643
644   klass = ATK_OBJECT_GET_CLASS (accessible);
645   if (klass->get_index_in_parent)
646     return (klass->get_index_in_parent) (accessible);
647   else
648     return -1;
649 }
650
651 /**
652  * atk_object_set_name:
653  * @accessible: an #AtkObject
654  * @name: a character string to be set as the accessible name
655  *
656  * Sets the accessible name of the accessible.
657  **/
658 void
659 atk_object_set_name (AtkObject    *accessible,
660                      const gchar  *name)
661 {
662   AtkObjectClass *klass;
663
664   g_return_if_fail (ATK_IS_OBJECT (accessible));
665   g_return_if_fail (name != NULL);
666
667   klass = ATK_OBJECT_GET_CLASS (accessible);
668   if (klass->set_name)
669     {
670       (klass->set_name) (accessible, name);
671       g_object_notify (G_OBJECT (accessible), atk_object_name_property_name);
672     }
673 }
674
675 /**
676  * atk_object_set_description:
677  * @accessible: an #AtkObject
678  * @description : a character string to be set as the accessible description
679  *
680  * Sets the accessible description of the accessible.
681  **/
682 void
683 atk_object_set_description (AtkObject   *accessible,
684                             const gchar *description)
685 {
686   AtkObjectClass *klass;
687
688   g_return_if_fail (ATK_IS_OBJECT (accessible));
689   g_return_if_fail (description != NULL);
690
691   klass = ATK_OBJECT_GET_CLASS (accessible);
692   if (klass->set_description)
693     {
694       (klass->set_description) (accessible, description);
695       g_object_notify (G_OBJECT (accessible), atk_object_name_property_description);
696     }
697 }
698
699 /**
700  * atk_object_set_parent:
701  * @accessible: an #AtkObject
702  * @parent : an #AtkObject to be set as the accessible parent
703  *
704  * Sets the accessible parent of the accessible.
705  **/
706 void
707 atk_object_set_parent (AtkObject *accessible,
708                        AtkObject *parent)
709 {
710   AtkObjectClass *klass;
711
712   g_return_if_fail (ATK_IS_OBJECT (accessible));
713
714   klass = ATK_OBJECT_GET_CLASS (accessible);
715   if (klass->set_parent)
716     {
717       (klass->set_parent) (accessible, parent);
718       g_object_notify (G_OBJECT (accessible), atk_object_name_property_parent);
719     }
720 }
721
722 /**
723  * atk_object_set_role:
724  * @accessible: an #AtkObject
725  * @role : an #AtkRole to be set as the role
726  *
727  * Sets the role of the accessible.
728  **/
729 void
730 atk_object_set_role (AtkObject *accessible, 
731                      AtkRole   role)
732 {
733   AtkObjectClass *klass;
734
735   g_return_if_fail (ATK_IS_OBJECT (accessible));
736
737   klass = ATK_OBJECT_GET_CLASS (accessible);
738   if (klass->set_role)
739     {
740       (klass->set_role) (accessible, role);
741       g_object_notify (G_OBJECT (accessible), atk_object_name_property_role);
742     }
743 }
744
745 /**
746  * atk_object_connect_property_change_handler:
747  * @accessible: an #AtkObject
748  * @handler : a function to be called when a property changes its value
749  *
750  * Specifies a function to be called when a property changes value.
751  *
752  * Returns: a #guint which is the handler id used in 
753  * atk_object_remove_property_change_handler()
754  **/
755 guint
756 atk_object_connect_property_change_handler (AtkObject *accessible,
757                                             AtkPropertyChangeHandler *handler)
758 {
759   AtkObjectClass *klass;
760
761   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
762   g_return_val_if_fail ((handler != NULL), 0);
763
764   klass = ATK_OBJECT_GET_CLASS (accessible);
765   if (klass->connect_property_change_handler)
766     return (klass->connect_property_change_handler) (accessible, handler);
767   else
768     return 0;
769 }
770
771 /**
772  * atk_object_remove_property_change_handler:
773  * @accessible: an #AtkObject
774  * @handler_id : a guint which identifies the handler to be removed.
775  * 
776  * Removes a property change handler.
777  **/
778 void
779 atk_object_remove_property_change_handler  (AtkObject *accessible,
780                                             guint      handler_id)
781 {
782   AtkObjectClass *klass;
783
784   g_return_if_fail (ATK_IS_OBJECT (accessible));
785
786   klass = ATK_OBJECT_GET_CLASS (accessible);
787   if (klass->remove_property_change_handler)
788     (klass->remove_property_change_handler) (accessible, handler_id);
789 }
790
791 /**
792  * atk_object_notify_state_change:
793  * @accessible: an #AtkObject
794  * @state: an #AtkState whose state is changed
795  * @value : a gboolean which indicates whether the state is being set on or off
796  * 
797  * Emits a state-change signal for the specified state. 
798  **/
799 void
800 atk_object_notify_state_change (AtkObject *accessible,
801                                 AtkState  state,
802                                 gboolean  value)
803 {
804   G_CONST_RETURN gchar* name;
805
806   name = atk_state_type_get_name (state);
807   g_signal_emit (accessible, atk_object_signals[STATE_CHANGE],
808                  g_quark_from_string (name),
809                  name, value, NULL);
810 }
811
812 /**
813  * atk_implementor_ref_accessible:
814  * @implementor: The #GObject instance which should implement #AtkImplementorIface
815  * if a non-null return value is required.
816  * 
817  * Gets a reference to an object's #AtkObject implementation, if
818  * the object implements #AtkObjectIface
819  *
820  * Returns: a reference to an object's #AtkObject implementation
821  */
822 AtkObject *
823 atk_implementor_ref_accessible (AtkImplementor *object)
824 {
825   AtkImplementorIface *iface;
826   AtkObject           *accessible = NULL;
827
828   g_return_val_if_fail (ATK_IS_IMPLEMENTOR (object), NULL);
829
830   iface = ATK_IMPLEMENTOR_GET_IFACE (object);
831
832   if (iface != NULL) 
833     accessible =  iface->ref_accessible (object);
834
835   g_return_val_if_fail ((accessible != NULL), NULL);
836
837   return accessible;
838 }
839
840 static AtkRelationSet*
841 atk_object_real_ref_relation_set (AtkObject *accessible)
842 {
843   g_return_val_if_fail (accessible->relation_set, NULL);
844   g_object_ref (accessible->relation_set); 
845
846   return accessible->relation_set;
847 }
848
849 static void
850 atk_object_real_set_property (GObject      *object,
851                               guint         prop_id,
852                               const GValue *value,
853                               GParamSpec   *pspec)
854 {
855   AtkObject *accessible;
856
857   accessible = ATK_OBJECT (object);
858
859   switch (prop_id)
860     {
861     case PROP_NAME:
862       atk_object_set_name (accessible, g_value_get_string (value));
863       break;
864     case PROP_DESCRIPTION:
865       atk_object_set_description (accessible, g_value_get_string (value));
866       break;
867     case PROP_ROLE:
868       atk_object_set_role (accessible, g_value_get_int (value));
869       break;
870     case PROP_PARENT:
871       atk_object_set_parent (accessible, g_value_get_object (value));
872       break;
873     case PROP_VALUE:
874       if (ATK_IS_VALUE (accessible))
875         atk_value_set_current_value (ATK_VALUE (accessible), value);
876       break;
877     default:
878       break;
879     }
880 }
881
882 static void
883 atk_object_real_get_property (GObject      *object,
884                               guint         prop_id,
885                               GValue       *value,
886                               GParamSpec   *pspec)
887 {
888   AtkObject *accessible;
889
890   accessible = ATK_OBJECT (object);
891
892   switch (prop_id)
893     {
894     case PROP_NAME:
895       g_value_set_string (value, atk_object_get_name (accessible));
896       break;
897     case PROP_DESCRIPTION:
898       g_value_set_string (value, atk_object_get_description (accessible));
899       break;
900     case PROP_ROLE:
901       g_value_set_int (value, atk_object_get_role (accessible));
902       break;
903     case PROP_LAYER:
904       if (ATK_IS_COMPONENT (accessible))
905         g_value_set_int (value, atk_component_get_layer (ATK_COMPONENT (accessible)));
906       break;
907     case PROP_MDI_ZORDER:
908       if (ATK_IS_COMPONENT (accessible))
909         g_value_set_int (value, atk_component_get_mdi_zorder (ATK_COMPONENT (accessible)));
910       break;
911     case PROP_PARENT:
912       g_value_set_object (value, atk_object_get_parent (accessible));
913       break;
914     case PROP_VALUE:
915       if (ATK_IS_VALUE (accessible))
916         atk_value_get_current_value (ATK_VALUE (accessible), value);
917       break;
918     default:
919       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
920       break;
921     }
922 }
923
924 static void
925 atk_object_finalize (GObject *object)
926 {
927   AtkObject        *accessible;
928
929   g_return_if_fail (ATK_IS_OBJECT (object));
930
931   accessible = ATK_OBJECT (object);
932
933   g_free (accessible->name);
934   g_free (accessible->description);
935
936   /*
937    * Free memory allocated for relation set if it have been allocated.
938    */
939   if (accessible->relation_set)
940     g_object_unref (accessible->relation_set);
941
942   if (accessible->accessible_parent)
943     g_object_unref (accessible->accessible_parent);
944
945   G_OBJECT_CLASS (parent_class)->finalize (object);
946 }
947
948 static G_CONST_RETURN gchar*
949 atk_object_real_get_name (AtkObject *object)
950 {
951   return object->name;
952 }
953
954 static G_CONST_RETURN gchar*
955 atk_object_real_get_description (AtkObject *object)
956 {
957   return object->description;
958 }
959
960 static AtkObject*
961 atk_object_real_get_parent (AtkObject       *object)
962 {
963   return object->accessible_parent;
964 }
965
966 static AtkRole
967 atk_object_real_get_role (AtkObject       *object)
968 {
969   return object->role;
970 }
971
972 static AtkLayer
973 atk_object_real_get_layer (AtkObject       *object)
974 {
975   return object->layer;
976 }
977
978 static AtkStateSet*
979 atk_object_real_ref_state_set (AtkObject *accessible) 
980 {
981   AtkStateSet *state_set;
982   AtkObject *ap;
983
984   state_set = atk_state_set_new ();
985
986   ap = atk_object_get_parent (accessible);
987   if (ap)
988     if (ATK_IS_SELECTION (ap))
989       {
990         int i;
991
992         atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE);
993
994         i = atk_object_get_index_in_parent (accessible);
995         if (i >= 0)
996           if (atk_selection_is_child_selected(ATK_SELECTION (ap), i))
997             atk_state_set_add_state (state_set, ATK_STATE_SELECTED);
998       } 
999
1000   return state_set; 
1001 }
1002
1003 static void
1004 atk_object_real_set_name (AtkObject       *object,
1005                           const gchar     *name)
1006 {
1007   g_free (object->name);
1008   object->name = g_strdup (name);
1009 }
1010
1011 static void
1012 atk_object_real_set_description (AtkObject       *object,
1013                                  const gchar     *description)
1014 {
1015   g_free (object->description);
1016   object->description = g_strdup (description);
1017 }
1018
1019 static void
1020 atk_object_real_set_parent (AtkObject       *object,
1021                             AtkObject       *parent)
1022 {
1023   if (object->accessible_parent)
1024     g_object_unref (object->accessible_parent);
1025
1026   object->accessible_parent = parent;
1027   if (object->accessible_parent)
1028     g_object_ref (object->accessible_parent);
1029 }
1030
1031 static void
1032 atk_object_real_set_role (AtkObject *object,
1033                           AtkRole   role)
1034 {
1035   object->role = role;
1036 }
1037
1038 static guint
1039 atk_object_real_connect_property_change_handler (AtkObject                *obj,
1040                                                  AtkPropertyChangeHandler *handler)
1041 {
1042   return g_signal_connect_closure_by_id (obj,
1043                                          atk_object_signals[PROPERTY_CHANGE],
1044                                          0,
1045                                          g_cclosure_new (
1046                                          G_CALLBACK (handler), NULL,
1047                                          (GClosureNotify) NULL),
1048                                          FALSE);
1049 }
1050
1051 static void
1052 atk_object_real_remove_property_change_handler (AtkObject           *obj,
1053                                           guint               handler_id)
1054 {
1055   g_signal_handler_disconnect (obj, handler_id);
1056 }
1057
1058 /**
1059  * atk_object_initialize:
1060  * @accessible: a #AtkObject
1061  * @data: a #gpointer which identifies the object for which the AtkObject was created.
1062  *
1063  * This function is called when implementing subclasses of #AtkObject.
1064  * It does initialization required for the new object. It is intended
1065  * that this function should called only in the ..._new() functions used
1066  * to create an instance of a subclass of #AtkObject
1067  **/
1068 void
1069 atk_object_initialize (AtkObject  *accessible,
1070                        gpointer   data)
1071 {
1072   AtkObjectClass *klass;
1073
1074   g_return_if_fail (ATK_IS_OBJECT (accessible));
1075
1076   klass = ATK_OBJECT_GET_CLASS (accessible);
1077   if (klass->initialize)
1078     klass->initialize (accessible, data);
1079 }
1080
1081 /*
1082  * This function is a signal handler for notify signal which gets emitted
1083  * when a property changes value.
1084  *
1085  * It constructs an AtkPropertyValues structure and emits a "property_changed"
1086  * signal which causes the user specified AtkPropertyChangeHandler
1087  * to be called.
1088  */
1089 static void
1090 atk_object_notify (GObject     *obj,
1091                    GParamSpec  *pspec)
1092 {
1093   AtkPropertyValues values = { 0, };
1094
1095   g_value_init (&values.new_value, pspec->value_type);
1096   g_object_get_property (obj, pspec->name, &values.new_value);
1097   values.property_name = pspec->name;
1098   g_signal_emit (obj, atk_object_signals[PROPERTY_CHANGE],
1099                  g_quark_from_string (pspec->name),
1100                  &values, NULL);
1101   g_value_unset (&values.new_value);
1102 }
1103
1104 /**
1105  * atk_role_get_name:
1106  * @role: The #AtkRole whose name is required
1107  *
1108  * Gets the description string describing the #Roleype @role.
1109  *
1110  * Returns: the string describing the AtkRole
1111  */
1112 G_CONST_RETURN gchar*
1113 atk_role_get_name (AtkRole role)
1114 {
1115   GTypeClass *type_class;
1116   GEnumValue *value;
1117   gchar *name = NULL;
1118
1119   type_class = g_type_class_ref (ATK_TYPE_ROLE);
1120   g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), NULL);
1121
1122   value = g_enum_get_value (G_ENUM_CLASS (type_class), role);
1123
1124   if (value)
1125     {
1126       name = value->value_nick;
1127     }
1128   else
1129     {
1130       if (extra_roles)
1131         {
1132           gint n = role;
1133
1134           n -= ATK_ROLE_LAST_DEFINED + 1;
1135
1136           if (n < extra_roles->len)
1137             name = g_ptr_array_index (extra_roles, n);
1138         }
1139     }
1140   g_type_class_unref (type_class);
1141   return name;
1142 }
1143
1144 /**
1145  * atk_role_for_name:
1146  * @name: a string which is the (non-localized) name of an ATK role.
1147  *
1148  * Get the #AtkRole type corresponding to a rolew name.
1149  *
1150  * Returns: the #AtkRole enumerated type corresponding to the specified
1151 name,
1152  *          or #ATK_ROLE_INVALID if no matching role is found.
1153  **/
1154 AtkRole
1155 atk_role_for_name (const gchar *name)
1156 {
1157   GTypeClass *type_class;
1158   GEnumValue *value;
1159   AtkRole role = ATK_ROLE_INVALID;
1160
1161   g_return_val_if_fail (name, ATK_ROLE_INVALID);
1162
1163   type_class = g_type_class_ref (ATK_TYPE_ROLE);
1164   g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), ATK_ROLE_INVALID);
1165
1166   value = g_enum_get_value_by_nick (G_ENUM_CLASS (type_class), name);
1167
1168   if (value)
1169     {
1170       role = value->value;
1171     }
1172   else
1173     {
1174      gint i;
1175
1176       if (extra_roles)
1177         {
1178           for (i = 0; i < extra_roles->len; i++)
1179             {
1180               gchar *extra_role = (gchar *)g_ptr_array_index (extra_roles, i);
1181
1182               g_return_val_if_fail (extra_role, ATK_ROLE_INVALID);
1183
1184               if (strcmp (name, extra_role) == 0)
1185                 {
1186                   role = i + 1 + ATK_ROLE_LAST_DEFINED;
1187                   break;
1188                 }
1189             }
1190         }
1191     }
1192   g_type_class_unref (type_class);
1193   
1194   return role;
1195 }