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