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