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