Define new properties accessible-text, accessible-caret,
[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   /*
188    * XXX We need to reconsider the value type for this
189    */
190   g_object_class_install_property (gobject_class,
191                                    PROP_VALUE,
192                                    g_param_spec_int    (atk_object_name_property_value,
193                                                         "Accessible Value",
194                                                         "Is used to notify that the value has been changed ",
195                                                         0,
196                                                         G_MAXINT,
197                                                         0,
198                                                         G_PARAM_READWRITE));
199   /*
200    * The signal "children_changed" supports two details:
201    * "add" and "remove"
202    */
203   atk_object_signals[CHILDREN_CHANGED] =
204     g_signal_newc ("children_changed",
205                    G_TYPE_FROM_CLASS (klass),
206                    G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
207                    G_STRUCT_OFFSET (AtkObjectClass, children_changed),
208                    NULL, NULL,
209                    g_cclosure_marshal_VOID__UINT_POINTER,
210                    G_TYPE_NONE,
211                    2, G_TYPE_UINT, ATK_TYPE_OBJECT);
212   atk_object_signals[FOCUS_EVENT] =
213     g_signal_newc ("focus_event",
214                    G_TYPE_FROM_CLASS (klass),
215                    G_SIGNAL_RUN_LAST,
216                    G_STRUCT_OFFSET (AtkObjectClass, focus_event), 
217                    NULL, NULL,
218                    g_cclosure_marshal_VOID__BOOLEAN,
219                    G_TYPE_NONE,
220                    1, G_TYPE_BOOLEAN);
221 }
222
223 static void
224 atk_object_init  (AtkObject        *accessible,
225                   AtkObjectClass   *klass)
226 {
227 }
228
229 GType
230 atk_implementor_get_type (void)
231 {
232   static GType type = 0;
233
234   if (!type)
235     {
236       static const GTypeInfo typeInfo =
237       {
238         sizeof (AtkImplementorIface),
239         (GBaseInitFunc) NULL,
240         (GBaseFinalizeFunc) NULL,
241       } ;
242
243       type = g_type_register_static (G_TYPE_INTERFACE, "AtkImplementorIface", &typeInfo, 0) ;
244     }
245
246   return type;
247 }
248
249 /**
250  * atk_object_get_name:
251  * @accessible: an #AtkObject
252  *
253  * Gets the accessible name of the accessible
254  *
255  * Returns: a character string representing the accessible name of the object.
256  **/
257 G_CONST_RETURN gchar*
258 atk_object_get_name (AtkObject *accessible)
259 {
260   AtkObjectClass *klass;
261
262   g_return_val_if_fail (accessible != NULL, NULL);
263   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
264
265   klass = ATK_OBJECT_GET_CLASS (accessible);
266   if (klass->get_name)
267     return (klass->get_name) (accessible);
268   else
269     return NULL;
270 }
271
272 /**
273  * atk_object_get_description:
274  * @accessible: an #AtkObject
275  *
276  * Gets the accessible description of the accessible
277  *
278  * Returns: a character string representing the accessible description
279  * of the accessible.
280  *
281  **/
282 G_CONST_RETURN gchar*
283 atk_object_get_description (AtkObject *accessible)
284 {
285   AtkObjectClass *klass;
286
287   g_return_val_if_fail (accessible != NULL, NULL);
288   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
289
290   klass = ATK_OBJECT_GET_CLASS (accessible);
291   if (klass->get_description)
292     return (klass->get_description) (accessible);
293   else
294     return NULL;
295 }
296
297 /**
298  * atk_object_get_parent:
299  * @accessible: an #AtkObject
300  *
301  * Gets the accessible parent of the accessible
302  *
303  * Returns: a #AtkObject representing the accessible parent of the accessible
304  **/
305 AtkObject*
306 atk_object_get_parent (AtkObject *accessible)
307 {
308   AtkObjectClass *klass;
309
310   g_return_val_if_fail (accessible != NULL, NULL);
311   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
312
313   klass = ATK_OBJECT_GET_CLASS (accessible);
314   if (klass->get_parent)
315     return (klass->get_parent) (accessible);
316   else
317     return NULL;
318 }
319
320 /**
321  * atk_object_get_n_accessible_children:
322  * @accessible: an #AtkObject
323  *
324  * Gets the number of accessible children of the accessible
325  *
326  * Returns: an integer representing the number of accessible children
327  * of the accessible.
328  **/
329 gint
330 atk_object_get_n_accessible_children (AtkObject *accessible)
331 {
332   AtkObjectClass *klass;
333
334   g_return_val_if_fail (accessible != NULL, 0);
335   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
336
337   klass = ATK_OBJECT_GET_CLASS (accessible);
338   if (klass->get_n_children)
339     return (klass->get_n_children) (accessible);
340   else
341     return 0;
342 }
343
344 /**
345  * atk_object_ref_accessible_child:
346  * @accessible: an #AtkObject
347  * @i: a gint representing the position of the child, starting from 0
348  *
349  * Gets a reference to the specified accessible child of the object.
350  * The accessible children are 0-based so the first accessible child is
351  * at index 0, the second at index 1 and so on.
352  *
353  * Returns: an #AtkObject representing the specified accessible child
354  * of the accessible.
355  **/
356 AtkObject*
357 atk_object_ref_accessible_child (AtkObject   *accessible,
358                                  gint        i)
359 {
360   AtkObjectClass *klass;
361
362   g_return_val_if_fail (accessible != NULL, NULL);
363   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
364
365   klass = ATK_OBJECT_GET_CLASS (accessible);
366   if (klass->ref_child)
367     return (klass->ref_child) (accessible, i);
368   else
369     return NULL;
370 }
371
372 /**
373  * atk_object_ref_relation_set:
374  * @accessible: an #AtkObject
375  *
376  * Gets the RelationSet associated with the object
377  *
378  * Returns: an #AtkRelationSet representing the relation set of the object.
379  **/
380 AtkRelationSet*
381 atk_object_ref_relation_set (AtkObject *accessible)
382 {
383   AtkObjectClass *klass;
384
385   g_return_val_if_fail (accessible != NULL, NULL);
386   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
387
388   klass = ATK_OBJECT_GET_CLASS (accessible);
389   if (klass->ref_relation_set)
390     return (klass->ref_relation_set) (accessible);
391   else
392     return NULL;
393 }
394
395 /**
396  * atk_role_register:
397  * @name: a character string describing the new role.
398  *
399  * Returns: an #AtkRole for the new role.
400  **/
401 AtkRole
402 atk_role_register (const gchar *name)
403 {
404   /* TODO: associate name with new type */
405   static guint type = ATK_ROLE_LAST_DEFINED;
406   return (++type);
407 }
408
409 /**
410  * atk_object_get_role:
411  * @accessible: an #AtkObject
412  *
413  * Gets the role of the accessible
414  *
415  * Returns: an #AtkRole which is the role of the accessible
416  **/
417 AtkRole
418 atk_object_get_role (AtkObject *accessible) {
419   AtkObjectClass *klass;
420
421   g_return_val_if_fail (accessible != NULL, ATK_ROLE_UNKNOWN);
422   g_return_val_if_fail (ATK_IS_OBJECT (accessible), ATK_ROLE_UNKNOWN);
423
424   klass = ATK_OBJECT_GET_CLASS (accessible);
425   if (klass->get_role)
426     return (klass->get_role) (accessible);
427   else
428     return ATK_ROLE_UNKNOWN;
429 }
430
431 /**
432  * atk_object_ref_state_set:
433  * @accessible: an #AtkObject
434  *
435  * Gets a reference to the state set of the accessible; the caller should
436  * unreference it.
437  *
438  * Returns: a reference to an #AtkStateSet which is the state
439  * set of the accessible
440  **/
441 AtkStateSet*
442 atk_object_ref_state_set (AtkObject *accessible) {
443   AtkObjectClass *klass;
444
445   g_return_val_if_fail (accessible != NULL, NULL);
446   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
447
448   klass = ATK_OBJECT_GET_CLASS (accessible);
449   if (klass->ref_state_set)
450     return (klass->ref_state_set) (accessible);
451   else
452     return NULL;
453 }
454
455 /**
456  * atk_object_get_index_in_parent:
457  * @accessible: an #AtkObject
458  *
459  * Gets the 0-based index of this accessible in its parent; returns -1 if the
460  * accessible does not have an accessible parent.
461  *
462  * Returns: an integer which is the index of the accessible in its parent
463  **/
464 gint
465 atk_object_get_index_in_parent (AtkObject *accessible)
466 {
467   AtkObjectClass *klass;
468
469   g_return_val_if_fail (accessible != NULL, -1);
470   g_return_val_if_fail (ATK_OBJECT (accessible), -1);
471
472   klass = ATK_OBJECT_GET_CLASS (accessible);
473   if (klass->get_index_in_parent)
474     return (klass->get_index_in_parent) (accessible);
475   else
476     return -1;
477 }
478
479 /**
480  * atk_object_set_name:
481  * @accessible: an #AtkObject
482  * @name: a character string to be set as the accessible name
483  *
484  * Sets the accessible name of the accessible
485  **/
486 void
487 atk_object_set_name (AtkObject    *accessible,
488                      const gchar  *name)
489 {
490   AtkObjectClass *klass;
491
492   g_return_if_fail (accessible != NULL);
493   g_return_if_fail (ATK_IS_OBJECT (accessible));
494   g_return_if_fail (name != NULL);
495
496   klass = ATK_OBJECT_GET_CLASS (accessible);
497   if (klass->set_name)
498   {
499     (klass->set_name) (accessible, name);
500     g_object_notify (G_OBJECT (accessible), atk_object_name_property_name);
501   }
502 }
503
504 /**
505  * atk_object_set_description:
506  * @accessible: an #AtkObject
507  * @description : a character string to be set as the accessible description
508  *
509  * Sets the accessible description of the accessible
510  **/
511 void
512 atk_object_set_description (AtkObject   *accessible,
513                             const gchar *description)
514 {
515   AtkObjectClass *klass;
516
517   g_return_if_fail (accessible != NULL);
518   g_return_if_fail (ATK_IS_OBJECT (accessible));
519   g_return_if_fail (description != NULL);
520
521   klass = ATK_OBJECT_GET_CLASS (accessible);
522   if (klass->set_description)
523   {
524     (klass->set_description) (accessible, description);
525     g_object_notify (G_OBJECT (accessible), atk_object_name_property_description);
526   }
527 }
528
529 /**
530  * atk_object_set_parent:
531  * @accessible: an #AtkObject
532  * @parent : an #AtkObject to be set as the accessible parent
533  *
534  * Sets the accessible parent of the accessible
535  **/
536 void
537 atk_object_set_parent (AtkObject *accessible,
538                        AtkObject *parent)
539 {
540   AtkObjectClass *klass;
541
542   g_return_if_fail (accessible != NULL);
543   g_return_if_fail (ATK_IS_OBJECT (accessible));
544
545   klass = ATK_OBJECT_GET_CLASS (accessible);
546   if (klass->set_parent)
547     (klass->set_parent) (accessible, parent);
548 }
549
550 /**
551  * atk_object_set_role:
552  * @accessible: an #AtkObject
553  * @role : an #AtkRole to be set as the role
554  *
555  * Sets the role of the accessible
556  **/
557 void
558 atk_object_set_role (AtkObject *accessible, 
559                      AtkRole   role)
560 {
561   AtkObjectClass *klass;
562
563   g_return_if_fail (accessible != NULL);
564   g_return_if_fail (ATK_IS_OBJECT (accessible));
565
566   klass = ATK_OBJECT_GET_CLASS (accessible);
567   if (klass->set_role)
568     (klass->set_role) (accessible, role);
569 }
570
571 /**
572  * atk_object_connect_property_change_handler:
573  * @accessible: an #AtkObject
574  * @handler : a function to be called when a property changes its value
575  *
576  * Specifies a function to be called when a property changes value.
577  *
578  * Returns: a #guint which is the handler id used in 
579  * atk_object_remove_property_change_handler()
580  **/
581 guint
582 atk_object_connect_property_change_handler (AtkObject *accessible,
583                                             AtkPropertyChangeHandler *handler)
584 {
585   AtkObjectClass *klass;
586
587   g_return_val_if_fail (accessible != NULL, 0);
588   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
589   g_return_val_if_fail ((handler != NULL), 0);
590
591   klass = ATK_OBJECT_GET_CLASS (accessible);
592   if (klass->connect_property_change_handler)
593     return (klass->connect_property_change_handler) (accessible, handler);
594   else
595     return 0;
596 }
597
598 /**
599  * atk_object_remove_property_change_handler:
600  * @accessible: an #AtkObject
601  * @handler_id : a guint which identifies the handler to be removed.
602  * 
603  * Removes a property change handler.
604  **/
605 void
606 atk_object_remove_property_change_handler  (AtkObject *accessible,
607                                             guint      handler_id)
608 {
609   AtkObjectClass *klass;
610
611   g_return_if_fail (accessible != NULL);
612   g_return_if_fail (ATK_IS_OBJECT (accessible));
613
614   klass = ATK_OBJECT_GET_CLASS (accessible);
615   if (klass->remove_property_change_handler)
616     (klass->remove_property_change_handler) (accessible, handler_id);
617 }
618
619 /**
620  * atk_implementor_ref_accessible:
621  * @implementor: The #GObject instance which should implement #AtkImplementorIface
622  * if a non-null return value is required.
623  * 
624  * Gets a reference to an object's #AtkObject implementation, if
625  * the object implements #AtkObjectIface
626  *
627  * Returns: a reference to an object's #AtkObject implementation
628  */
629 AtkObject *
630 atk_implementor_ref_accessible (AtkImplementor *object)
631 {
632   AtkImplementorIface *iface;
633   AtkObject           *accessible = NULL;
634
635   g_return_val_if_fail (object != NULL, NULL);
636   g_return_val_if_fail (ATK_IS_IMPLEMENTOR (object), NULL);
637
638   iface = ATK_IMPLEMENTOR_GET_IFACE (object);
639
640   if (iface != NULL) 
641     accessible =  iface->ref_accessible (object);
642
643   g_return_val_if_fail ((accessible != NULL), NULL);
644
645   return accessible;
646 }
647
648 static AtkRelationSet*
649 atk_object_real_ref_relation_set (AtkObject *accessible)
650 {
651   if (accessible->relation_set)
652     g_object_ref (accessible->relation_set); 
653
654   return accessible->relation_set;
655 }
656
657 static void
658 atk_object_real_set_property (GObject      *object,
659                               guint         prop_id,
660                               const GValue *value,
661                               GParamSpec   *pspec)
662 {
663   AtkObject *accessible;
664
665   accessible = ATK_OBJECT (object);
666
667   switch (prop_id)
668   {
669     case PROP_NAME:
670       atk_object_set_name (accessible, g_value_get_string (value));
671       break;
672     case PROP_DESCRIPTION:
673       atk_object_set_description (accessible, g_value_get_string (value));
674       break;
675     case PROP_STATE:
676       g_print ("This interface does not support setting the state set of an accessible object\n");
677       break;
678     default:
679       break;
680   }
681 }
682
683 static void
684 atk_object_real_get_property (GObject      *object,
685                               guint         prop_id,
686                               GValue       *value,
687                               GParamSpec   *pspec)
688 {
689   AtkObject *accessible;
690
691   accessible = ATK_OBJECT (object);
692
693   switch (prop_id)
694   {
695     case PROP_NAME:
696       g_value_set_string (value, atk_object_get_name (accessible));
697       break;
698     case PROP_DESCRIPTION:
699       g_value_set_string (value, atk_object_get_description (accessible));
700       break;
701     default:
702       break;
703   }
704 }
705
706 static void
707 atk_object_finalize (GObject *object)
708 {
709   AtkObject        *accessible;
710
711   g_return_if_fail (ATK_IS_OBJECT (object));
712
713   accessible = ATK_OBJECT (object);
714
715   g_free (accessible->name);
716   g_free (accessible->description);
717
718   /*
719    * Free memory allocated for relation set if it have been allocated.
720    */
721   if (accessible->relation_set)
722   {
723     g_object_unref (accessible->relation_set);
724   }
725
726   G_OBJECT_CLASS (parent_class)->finalize (object);
727 }
728
729 static void
730 atk_object_real_set_role (AtkObject *object,
731                           AtkRole   role)
732 {
733   object->role = role;
734 }