Added better gtk-doc comments.
[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_CHILD,       /* a child has been added or removed */
35   PROP_STATE,       /* AtkStateSet for the object has changed */
36   PROP_TEXT,        /* Used only by AtkText implementors */
37   PROP_CARET,       /* Used only by AtkText implementors */
38   PROP_LAST         /* gobject convention */
39 };
40
41 enum {
42   CHILDREN_CHANGED,
43   FOCUS_EVENT,
44   LAST_SIGNAL
45 };
46
47 static void            atk_object_class_init       (AtkObjectClass  *klass);
48 static void            atk_object_init             (AtkObject       *accessible,
49                                                     AtkObjectClass  *klass);
50 static AtkRelationSet* atk_object_real_ref_relation_set (AtkObject *accessible);
51
52 static void            atk_object_real_set_property(GObject         *object,
53                                                     guint            prop_id,
54                                                     const GValue    *value,
55                                                     GParamSpec      *pspec);
56 static void            atk_object_real_get_property(GObject         *object,
57                                                     guint            prop_id,
58                                                     GValue          *value,
59                                                     GParamSpec      *pspec);
60 static void            atk_object_finalize         (GObject         *object);
61 static void            atk_object_real_set_role    (AtkObject       *object,
62                                                     AtkRole         role);
63 static void            atk_object_focus_event_unimplemented
64                                                    (AtkObject       *object,
65                                                     gboolean        focus_in);
66
67 static guint atk_object_signals[LAST_SIGNAL] = { 0, };
68
69 static gpointer parent_class = NULL;
70
71 static const gchar* atk_object_name_property_name = "accessible-name";
72 static const gchar* atk_object_name_property_state = "accessible-state";
73 static const gchar* atk_object_name_property_description = "accessible-description";
74 static const gchar* atk_object_name_property_child = "accessible-child";
75 static const gchar* atk_object_name_property_parent = "accessible-parent";
76
77 GType
78 atk_object_get_type (void)
79 {
80   static GType type = 0;
81
82   if (!type)
83     {
84       static const GTypeInfo typeInfo =
85       {
86         sizeof (AtkObjectClass),
87         (GBaseInitFunc) NULL,
88         (GBaseFinalizeFunc) NULL,
89         (GClassInitFunc) atk_object_class_init,
90         (GClassFinalizeFunc) NULL,
91         NULL,
92         sizeof (AtkObject),
93         0,
94         (GInstanceInitFunc) atk_object_init,
95       } ;
96       type = g_type_register_static (G_TYPE_OBJECT, "AtkObject", &typeInfo, 0) ;
97     }
98   return type;
99 }
100
101 static void
102 atk_object_class_init (AtkObjectClass *klass)
103 {
104   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
105
106   parent_class = g_type_class_ref (G_TYPE_OBJECT);
107
108   gobject_class->set_property = atk_object_real_set_property;
109   gobject_class->get_property = atk_object_real_get_property;
110   gobject_class->finalize = atk_object_finalize;
111
112   klass->ref_relation_set = atk_object_real_ref_relation_set;
113   klass->set_role = atk_object_real_set_role;
114   klass->focus_event = atk_object_focus_event_unimplemented;
115
116   klass->children_changed = NULL;
117
118   g_object_class_install_property (gobject_class,
119                                    PROP_NAME,
120                                    g_param_spec_string (atk_object_name_property_name,
121                                                         "Accessible Name",
122                                                         "Object instance\'s name formatted for "
123                                                            "assistive technology access",
124                                                         NULL,
125                                                         G_PARAM_READWRITE));
126   g_object_class_install_property (gobject_class,
127                                    PROP_DESCRIPTION,
128                                    g_param_spec_string (atk_object_name_property_description,
129                                                         "Accessible Description",
130                                                         "Description of an object, formatted for "
131                                                         "assistive technology access",
132                                                         NULL,
133                                                         G_PARAM_READWRITE));
134   g_object_class_install_property (gobject_class,
135                                    PROP_STATE,
136                                    g_param_spec_int    (atk_object_name_property_state,
137                                                         "Accessible State Set",
138                                                         "The accessible state set of this object "
139                                                         "or its UI component",
140                                                         0,
141                                                         G_MAXINT,
142                                                         0,
143                                                         G_PARAM_READWRITE));
144   g_object_class_install_property (gobject_class,
145                                    PROP_CHILD,
146                                    g_param_spec_object (atk_object_name_property_child,
147                                                         "Accessible Child",
148                                                         "Is used to notify that a child has been added or removed ",
149                                                         ATK_TYPE_OBJECT,
150                                                         G_PARAM_READWRITE));
151    g_object_class_install_property (gobject_class,
152                                     PROP_PARENT,
153                                    g_param_spec_object (atk_object_name_property_parent,
154                                                         "Accessible Parent",
155                                                         "Is used to notify that the parent has been changed ",
156                                                         ATK_TYPE_OBJECT,
157                                                         G_PARAM_READWRITE));
158 #if 0
159   g_object_class_install_property (gobject_class,
160                                    PROP_TEXT,
161                                    g_param_spec_ccallback ("accessible_text", "Accessible Text",
162                                                            "This object\'s accessible text contents",
163                                                            G_PARAM_READWRITE));
164   g_object_class_install_property (gobject_class,
165                                    PROP_CARET,
166                                    g_param_spec_ccallback ("accessible_caret", "Accessible Text Caret",
167                                                            "The current text caret state and position "
168                                                            "for this component",
169                                                            G_PARAM_READWRITE));
170 #endif
171   atk_object_signals[CHILDREN_CHANGED] =
172     g_signal_newc ("accessible_children_changed",
173                    G_TYPE_FROM_CLASS (klass),
174                    G_SIGNAL_RUN_LAST,
175                    G_STRUCT_OFFSET (AtkObjectClass, children_changed), /* still need to declare and define this func */
176                    NULL, NULL,
177                    g_cclosure_marshal_VOID__UINT_POINTER,
178                    G_TYPE_NONE,
179                    2, G_TYPE_UINT, ATK_TYPE_OBJECT);
180   atk_object_signals[FOCUS_EVENT] =
181     g_signal_newc ("focus_event",
182                    G_TYPE_FROM_CLASS (klass),
183                    G_SIGNAL_RUN_LAST,
184                    G_STRUCT_OFFSET (AtkObjectClass, focus_event), 
185                    NULL, NULL,
186                    g_cclosure_marshal_VOID__BOOLEAN,
187                    G_TYPE_NONE,
188                    1, G_TYPE_BOOLEAN);
189 }
190
191 static void
192 atk_object_init  (AtkObject        *accessible,
193                   AtkObjectClass   *klass)
194 {
195 }
196
197 /**
198  *atk_implementor_get_type:
199  *
200  *Returns: a #GType
201  **/
202 GType
203 atk_implementor_get_type (void)
204 {
205   static GType type = 0;
206
207   if (!type)
208     {
209       static const GTypeInfo typeInfo =
210       {
211         sizeof (AtkImplementorIface),
212         (GBaseInitFunc) NULL,
213         (GBaseFinalizeFunc) NULL,
214       } ;
215
216       type = g_type_register_static (G_TYPE_INTERFACE, "AtkImplementorIface", &typeInfo, 0) ;
217     }
218
219   return type;
220 }
221
222 /**
223  * atk_object_get_name:
224  * @accessible: a #AtkObject
225  *
226  * Gets the accessible name of the accessible
227  *
228  * Returns: a character string representing the accessible name of the object.
229  **/
230 G_CONST_RETURN gchar*
231 atk_object_get_name (AtkObject *accessible)
232 {
233   AtkObjectClass *klass;
234
235   g_return_val_if_fail (accessible != NULL, NULL);
236   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
237
238   klass = ATK_OBJECT_GET_CLASS (accessible);
239   if (klass->get_name)
240     return (klass->get_name) (accessible);
241   else
242     return NULL;
243 }
244
245 /**
246  * atk_object_get_description:
247  * @accessible: a #AtkObject
248  *
249  * Gets the accessible description of the accessible
250  *
251  * Returns: a character string representing the accessible description of the accessible.
252  *
253  **/
254 G_CONST_RETURN gchar*
255 atk_object_get_description (AtkObject *accessible)
256 {
257   AtkObjectClass *klass;
258
259   g_return_val_if_fail (accessible != NULL, NULL);
260   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
261
262   klass = ATK_OBJECT_GET_CLASS (accessible);
263   if (klass->get_description)
264     return (klass->get_description) (accessible);
265   else
266     return NULL;
267 }
268
269 /**
270  * atk_object_get_parent:
271  * @accessible: a #AtkObject
272  *
273  * Gets the accessible description of the accessible
274  *
275  * Returns: a #AtkObject representing the accessible parent of the accessible.
276  **/
277 AtkObject*
278 atk_object_get_parent (AtkObject *accessible)
279 {
280   AtkObjectClass *klass;
281
282   g_return_val_if_fail (accessible != NULL, NULL);
283   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
284
285   klass = ATK_OBJECT_GET_CLASS (accessible);
286   if (klass->get_parent)
287     return (klass->get_parent) (accessible);
288   else
289     return NULL;
290 }
291
292 /**
293  * atk_object_get_n_accessible_children:
294  * @accessible: a #AtkObject
295  *
296  * Gets the number of accessible children of the accessible
297  *
298  * Returns: a gint representing the number of accessible children of the accessible.
299  **/
300 gint
301 atk_object_get_n_accessible_children (AtkObject *accessible)
302 {
303   AtkObjectClass *klass;
304
305   g_return_val_if_fail (accessible != NULL, 0);
306   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
307
308   klass = ATK_OBJECT_GET_CLASS (accessible);
309   if (klass->get_n_children)
310     return (klass->get_n_children) (accessible);
311   else
312     return 0;
313 }
314
315 /**
316  * atk_object_ref_accessible_child:
317  * @accessible: a #AtkObject
318  * @i: a gint representing the position of the child, starting from 0
319  *
320  * Gets a reference to the specified accessible child of the object.
321  * The accessible children are 0-based so the first accessible child is
322  * at index 0, the second at index 1 and so on.
323  *
324  * Returns: a #AtkObject representing the specified accessible child of the accessible.
325  **/
326 AtkObject*
327 atk_object_ref_accessible_child (AtkObject   *accessible,
328                                  gint        i)
329 {
330   AtkObjectClass *klass;
331
332   g_return_val_if_fail (accessible != NULL, NULL);
333   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
334
335   klass = ATK_OBJECT_GET_CLASS (accessible);
336   if (klass->ref_child)
337     return (klass->ref_child) (accessible, i);
338   else
339     return NULL;
340 }
341
342 /**
343  * atk_object_ref_relation_set:
344  * @accessible: a #AtkObject
345  *
346  * Gets the RelationSet associated with the object
347  *
348  * Returns: a #AtkRelationSet representing the relation set of the object.
349  **/
350 AtkRelationSet*
351 atk_object_ref_relation_set (AtkObject *accessible)
352 {
353   AtkObjectClass *klass;
354
355   g_return_val_if_fail (accessible != NULL, NULL);
356   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
357
358   klass = ATK_OBJECT_GET_CLASS (accessible);
359   if (klass->ref_relation_set)
360     return (klass->ref_relation_set) (accessible);
361   else
362     return NULL;
363 }
364
365 /**
366  * atk_role_register:
367  * @name: a character string describing the new role.
368  *
369  * Returns: a #AtkRole value for the new role.
370  **/
371 AtkRole
372 atk_role_register (const gchar *name)
373 {
374   /* TODO: associate name with new type */
375   static guint type = ATK_ROLE_LAST_DEFINED;
376   return (++type);
377 }
378
379 /**
380  * atk_object_get_role:
381  * @accessible: a #AtkObject
382  *
383  * Gets the role of the accessible
384  *
385  * Returns: a #AtkRole which is the role of the accessible
386  **/
387 AtkRole
388 atk_object_get_role (AtkObject *accessible) {
389   AtkObjectClass *klass;
390
391   g_return_val_if_fail (accessible != NULL, ATK_ROLE_UNKNOWN);
392   g_return_val_if_fail (ATK_IS_OBJECT (accessible), ATK_ROLE_UNKNOWN);
393
394   klass = ATK_OBJECT_GET_CLASS (accessible);
395   if (klass->get_role)
396     return (klass->get_role) (accessible);
397   else
398     return ATK_ROLE_UNKNOWN;
399 }
400
401 /**
402  * atk_object_ref_state_set:
403  * @accessible: a #AtkObject
404  *
405  * Gets a reference to the state set of the accessible; the caller should
406  * unreference it.
407  *
408  * Returns: a reference to a #AtkStateSet which is the state set of the accessible
409  **/
410 AtkStateSet*
411 atk_object_ref_state_set (AtkObject *accessible) {
412   AtkObjectClass *klass;
413
414   g_return_val_if_fail (accessible != NULL, NULL);
415   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
416
417   klass = ATK_OBJECT_GET_CLASS (accessible);
418   if (klass->ref_state_set)
419     return (klass->ref_state_set) (accessible);
420   else
421     return NULL;
422 }
423
424 /**
425  * atk_object_get_index_in_parent:
426  * @accessible: a #AtkObject
427  *
428  * Gets the 0-based index of this accessible in its parent; returns -1 if the
429  * accessible does not have an accessible parent.
430  *
431  * Returns: a gint which is the index of the accessible in its parent
432  **/
433 gint
434 atk_object_get_index_in_parent (AtkObject *accessible)
435 {
436   AtkObjectClass *klass;
437
438   g_return_val_if_fail (accessible != NULL, -1);
439   g_return_val_if_fail (ATK_OBJECT (accessible), -1);
440
441   klass = ATK_OBJECT_GET_CLASS (accessible);
442   if (klass->get_index_in_parent)
443     return (klass->get_index_in_parent) (accessible);
444   else
445     return -1;
446 }
447
448 /**
449  * atk_object_set_name:
450  * @accessible: a #AtkObject
451  * @name: a character string to be set as the accessible name
452  *
453  * Sets the accessible name of the accessible
454  **/
455 void
456 atk_object_set_name (AtkObject    *accessible,
457                      const gchar  *name)
458 {
459   AtkObjectClass *klass;
460
461   g_return_if_fail (accessible != NULL);
462   g_return_if_fail (ATK_IS_OBJECT (accessible));
463   g_return_if_fail (name != NULL);
464
465   klass = ATK_OBJECT_GET_CLASS (accessible);
466   if (klass->set_name)
467   {
468     (klass->set_name) (accessible, name);
469     g_object_notify (G_OBJECT (accessible), atk_object_name_property_name);
470   }
471 }
472
473 /**
474  * atk_object_set_description:
475  * @accessible: a #AtkObject
476  * @description : a character string to be set as the accessible description
477  *
478  * Sets the accessible description of the accessible
479  **/
480 void
481 atk_object_set_description (AtkObject   *accessible,
482                             const gchar *description)
483 {
484   AtkObjectClass *klass;
485
486   g_return_if_fail (accessible != NULL);
487   g_return_if_fail (ATK_IS_OBJECT (accessible));
488   g_return_if_fail (description != NULL);
489
490   klass = ATK_OBJECT_GET_CLASS (accessible);
491   if (klass->set_description)
492   {
493     (klass->set_description) (accessible, description);
494     g_object_notify (G_OBJECT (accessible), atk_object_name_property_description);
495   }
496 }
497
498 /**
499  * atk_object_set_parent:
500  * @accessible: a #AtkObject
501  * @parent : a #AtkObject to be set as the accessible parent
502  *
503  * Sets the accessible parent of the accessible
504  **/
505 void
506 atk_object_set_parent (AtkObject *accessible,
507                        AtkObject *parent)
508 {
509   AtkObjectClass *klass;
510
511   g_return_if_fail (accessible != NULL);
512   g_return_if_fail (ATK_IS_OBJECT (accessible));
513
514   klass = ATK_OBJECT_GET_CLASS (accessible);
515   if (klass->set_parent)
516     (klass->set_parent) (accessible, parent);
517 }
518
519 /**
520  * atk_object_set_role:
521  * @accessible: a #AtkObject
522  * @role : a #AtkRole to be set as the role
523  *
524  * Sets the role of the accessible
525  **/
526 void
527 atk_object_set_role (AtkObject *accessible, 
528                      AtkRole   role)
529 {
530   AtkObjectClass *klass;
531
532   g_return_if_fail (accessible != NULL);
533   g_return_if_fail (ATK_IS_OBJECT (accessible));
534
535   klass = ATK_OBJECT_GET_CLASS (accessible);
536   if (klass->set_role)
537     (klass->set_role) (accessible, role);
538 }
539
540 /**
541  * atk_object_connect_property_change_handler:
542  * @accessible: a #AtkObject
543  * @handler : a #AtkPropertyChangeHandler, a function to be called when a property changes its value
544  *
545  * Specifies a function to be called when a property changes value.
546  *
547  * Returns: a guint which is the handler id used in atk_object_remove_property_change_handler
548  **/
549 guint
550 atk_object_connect_property_change_handler (AtkObject *accessible,
551                                             AtkPropertyChangeHandler *handler)
552 {
553   AtkObjectClass *klass;
554
555   g_return_val_if_fail (accessible != NULL, 0);
556   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
557   g_return_val_if_fail ((handler != NULL), 0);
558
559   klass = ATK_OBJECT_GET_CLASS (accessible);
560   if (klass->connect_property_change_handler)
561     return (klass->connect_property_change_handler) (accessible, handler);
562   else
563     return 0;
564 }
565
566 /**
567  * atk_object_remove_property_change_handler:
568  * @accessible: a #AtkObject
569  * @handler_id : a guint which identifies the handler to be removed.
570  * 
571  * Removes a property change handler.
572  **/
573 void
574 atk_object_remove_property_change_handler  (AtkObject *accessible,
575                                             guint      handler_id)
576 {
577   AtkObjectClass *klass;
578
579   g_return_if_fail (accessible != NULL);
580   g_return_if_fail (ATK_IS_OBJECT (accessible));
581
582   klass = ATK_OBJECT_GET_CLASS (accessible);
583   if (klass->remove_property_change_handler)
584     (klass->remove_property_change_handler) (accessible, handler_id);
585 }
586
587 /**
588  * atk_implementor_ref_accessible:
589  * @implementor: The GObject instance which should implement #AtkImplementorIface
590  * if a non-null return value is required.
591  * 
592  * Returns a reference to an object's #AtkObject implementation, if
593  * the object implements #AtkObjectIface
594  *
595  * Returns: a reference to an object's #AtkObject implementation, if
596  * the object implements #AtkObjectIface
597  */
598 AtkObject *
599 atk_implementor_ref_accessible (AtkImplementor *object)
600 {
601   AtkImplementorIface *iface;
602   AtkObject           *accessible = NULL;
603
604   g_return_val_if_fail (object != NULL, NULL);
605   g_return_val_if_fail (ATK_IS_IMPLEMENTOR (object), NULL);
606
607   iface = ATK_IMPLEMENTOR_GET_IFACE (object);
608
609   if (iface != NULL) 
610     accessible =  iface->ref_accessible (object);
611
612   g_return_val_if_fail ((accessible != NULL), NULL);
613
614   return accessible;
615 }
616
617 static AtkRelationSet*
618 atk_object_real_ref_relation_set (AtkObject *accessible)
619 {
620   if (accessible->relation_set)
621     g_object_ref (accessible->relation_set); 
622
623   return accessible->relation_set;
624 }
625
626 static void
627 atk_object_real_set_property (GObject      *object,
628                               guint         prop_id,
629                               const GValue *value,
630                               GParamSpec   *pspec)
631 {
632   AtkObject *accessible;
633
634   accessible = ATK_OBJECT (object);
635
636   switch (prop_id)
637   {
638     case PROP_NAME:
639       atk_object_set_name (accessible, g_value_get_string (value));
640       break;
641     case PROP_DESCRIPTION:
642       atk_object_set_description (accessible, g_value_get_string (value));
643       break;
644     case PROP_STATE:
645       g_print ("This interface does not support setting the state set of an accessible object\n");
646       break;
647     default:
648       break;
649   }
650 }
651
652 static void
653 atk_object_real_get_property (GObject      *object,
654                               guint         prop_id,
655                               GValue       *value,
656                               GParamSpec   *pspec)
657 {
658   AtkObject *accessible;
659
660   accessible = ATK_OBJECT (object);
661
662   switch (prop_id)
663   {
664     case PROP_NAME:
665       g_value_set_string (value, atk_object_get_name (accessible));
666       break;
667     case PROP_DESCRIPTION:
668       g_value_set_string (value, atk_object_get_description (accessible));
669       break;
670     default:
671       break;
672   }
673 }
674
675 static void
676 atk_object_finalize (GObject *object)
677 {
678   AtkObject        *accessible;
679
680   g_return_if_fail (ATK_IS_OBJECT (object));
681
682   accessible = ATK_OBJECT (object);
683
684   g_free (accessible->name);
685   g_free (accessible->description);
686
687   /*
688    * Free memory allocated for relation set if it have been allocated.
689    */
690   if (accessible->relation_set)
691   {
692     g_object_unref (accessible->relation_set);
693   }
694
695   G_OBJECT_CLASS (parent_class)->finalize (object);
696 }
697
698 static void
699 atk_object_real_set_role (AtkObject *object,
700                           AtkRole   role)
701 {
702   object->role = role;
703 }
704
705 static void
706 atk_object_focus_event_unimplemented (AtkObject       *object,
707                                       gboolean        focus_in)
708 {
709   g_warning ("AtkObjectClass::focus_event not implemented for `%s'", 
710               g_type_name (G_OBJECT_TYPE (object)));
711 }