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