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