Released 0.1
[atk.git] / atk / atkobject.c
blobb71ea338677857b521c22810cf0cb524a2f0ac7c
1 /* ATK - Accessibility Toolkit
2 * Copyright 2001 Sun Microsystems Inc.
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.
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.
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.
20 #include <string.h>
22 #include <glib-object.h>
24 #include "atk.h"
26 #define NUM_POSSIBLE_STATES (sizeof(AtkStateMask)*8)
28 #define ATK_STATE(state_enum) ((AtkStateMask)(1 << ((guint64)(state_enum)%64)))
30 /* New GObject properties registered by AtkObject */
31 enum
33 PROP_0, /* gobject convention */
35 PROP_NAME,
36 PROP_DESCRIPTION,
37 PROP_PARENT, /* ancestry has changed */
38 PROP_CHILD, /* children have changed in number or identity */
39 PROP_ROLE, /* AtkRole has changed */
40 PROP_STATE, /* AtkState has changed */
41 PROP_TEXT, /* Used only by AtkText implementors */
42 PROP_CARET, /* Used only by AtkText implementors */
43 PROP_LAST /* gobject convention */
46 enum {
47 CHILDREN_CHANGED,
48 LAST_SIGNAL
51 static void atk_object_class_init (AtkObjectClass *klass);
52 static void atk_object_init (AtkObject *accessible,
53 AtkObjectClass *klass);
54 static AtkRelationSet* atk_object_real_ref_relation_set (AtkObject *accessible);
56 static void atk_object_real_set_property(GObject *object,
57 guint prop_id,
58 const GValue *value,
59 GParamSpec *pspec);
60 static void atk_object_real_get_property(GObject *object,
61 guint prop_id,
62 GValue *value,
63 GParamSpec *pspec);
64 static void atk_object_finalize (GObject *object);
66 static gchar* state_names[NUM_POSSIBLE_STATES];
68 #if 0
69 static guint atk_object_signals[LAST_SIGNAL] = { 0, };
70 #endif
72 static gpointer parent_class = NULL;
74 static const gchar* atk_object_name_property_name = "accessible-name";
75 static const gchar* atk_object_name_property_state = "accessible-state";
76 static const gchar* atk_object_name_property_description = "accessible-description";
78 GType
79 atk_object_get_type (void)
81 static GType type = 0;
83 if (!type)
85 static const GTypeInfo typeInfo =
87 sizeof (AtkObjectClass),
88 (GBaseInitFunc) NULL,
89 (GBaseFinalizeFunc) NULL,
90 (GClassInitFunc) atk_object_class_init,
91 (GClassFinalizeFunc) NULL,
92 NULL,
93 sizeof (AtkObject),
95 (GInstanceInitFunc) atk_object_init,
96 } ;
97 type = g_type_register_static (G_TYPE_OBJECT, "AtkObject", &typeInfo, 0) ;
99 return type;
102 static void
103 atk_object_class_init (AtkObjectClass *klass)
105 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
107 parent_class = g_type_class_ref (G_TYPE_OBJECT);
109 gobject_class->set_property = atk_object_real_set_property;
110 gobject_class->get_property = atk_object_real_get_property;
111 gobject_class->finalize = atk_object_finalize;
113 klass->ref_relation_set = atk_object_real_ref_relation_set;
115 state_names[ATK_STATE_ARMED] = "armed";
116 state_names[ATK_STATE_BUSY] = "busy";
117 state_names[ATK_STATE_CHECKED] = "checked";
118 state_names[ATK_STATE_COLLAPSED] = "collapsed";
119 state_names[ATK_STATE_EDITABLE] = "editable";
120 state_names[ATK_STATE_EXPANDABLE] = "expandable";
121 state_names[ATK_STATE_EXPANDED] = "expanded";
122 state_names[ATK_STATE_FOCUSABLE] = "focusable";
123 state_names[ATK_STATE_FOCUSED] = "focused";
124 state_names[ATK_STATE_HORIZONTAL] = "horizontal";
125 state_names[ATK_STATE_ICONIFIED] = "iconified";
126 state_names[ATK_STATE_MODAL] = "modal";
127 state_names[ATK_STATE_MULTI_LINE] = "multi-line";
128 state_names[ATK_STATE_MULTISELECTABLE] = "multiselectable";
129 state_names[ATK_STATE_OPAQUE] = "opaque";
130 state_names[ATK_STATE_PRESSED] = "pressed";
131 state_names[ATK_STATE_RESIZABLE] = "resizeable";
132 state_names[ATK_STATE_SELECTABLE] = "selectable";
133 state_names[ATK_STATE_SELECTED] = "selected";
134 state_names[ATK_STATE_SENSITIVE] = "sensitive";
135 state_names[ATK_STATE_SHOWING] = "showing";
136 state_names[ATK_STATE_SINGLE_LINE] = "single-line";
137 state_names[ATK_STATE_TRANSIENT] = "transient";
138 state_names[ATK_STATE_VERTICAL] = "vertical";
139 state_names[ATK_STATE_VISIBLE] = "visible";
141 klass->children_changed = NULL;
143 g_object_class_install_property (gobject_class,
144 PROP_NAME,
145 g_param_spec_string (atk_object_name_property_name,
146 "Accessible Name",
147 "Object instance\'s name formatted for "
148 "assistive technology access",
149 NULL,
150 G_PARAM_READWRITE));
151 g_object_class_install_property (gobject_class,
152 PROP_DESCRIPTION,
153 g_param_spec_string (atk_object_name_property_description,
154 "Accessible Description",
155 "Description of an object, formatted for "
156 "assistive technology access",
157 NULL,
158 G_PARAM_READWRITE));
159 g_object_class_install_property (gobject_class,
160 PROP_STATE,
161 g_param_spec_int (atk_object_name_property_state,
162 "Accessible State",
163 "The current state of this object "
164 "or its UI component",
166 G_MAXINT,
168 G_PARAM_WRITABLE));
169 #if 0
170 /* register some properties - these could be change signals instead */
171 g_object_class_install_property (gobject_class,
172 PROP_PARENT,
173 g_param_spec_ccallback ("accessible_parent", "Accessible Parent",
174 "First accessible ancestor (container or object) "
175 "which this object is a descendant of",
176 G_PARAM_READWRITE));
179 g_object_class_install_property (gobject_class,
180 PROP_ROLE,
181 g_param_spec_ccallback ("accessible_role", "Accessible Role",
182 "The user-interface role of this object",
183 G_PARAM_READWRITE));
184 g_object_class_install_property (gobject_class,
185 PROP_STATE,
186 g_param_spec_ccallback ("accessible_state", "Accessible State",
187 "The current state of this object "
188 "or its UI component",
189 G_PARAM_READWRITE));
190 g_object_class_install_property (gobject_class,
191 PROP_TEXT,
192 g_param_spec_ccallback ("accessible_text", "Accessible Text",
193 "This object\'s accessible text contents",
194 G_PARAM_READWRITE));
195 g_object_class_install_property (gobject_class,
196 PROP_CARET,
197 g_param_spec_ccallback ("accessible_caret", "Accessible Text Caret",
198 "The current text caret state and position "
199 "for this component",
200 G_PARAM_READWRITE));
201 gaccessible_signals[CHILDREN_CHANGED] =
202 g_signal_newc ("accessible_children_changed",
203 G_TYPE_FROM_CLASS (klass),
204 G_SIGNAL_RUN_LAST,
205 G_STRUCT_OFFSET (AtkObjectClass, children_changed), /* still need to declare and define this func */
206 NULL,
207 g_cclosure_marshal_VOID__UINT_POINTER,
208 G_TYPE_NONE,
209 2, G_TYPE_UINT, ATK_TYPE_OBJECT);
210 #endif
213 static void
214 atk_object_init (AtkObject *accessible,
215 AtkObjectClass *klass)
219 GType
220 atk_implementor_get_type (void)
222 static GType type = 0;
224 if (!type)
226 static const GTypeInfo typeInfo =
228 sizeof (AtkImplementorIface),
229 (GBaseInitFunc) NULL,
230 (GBaseFinalizeFunc) NULL,
233 type = g_type_register_static (G_TYPE_INTERFACE, "AtkImplementorIface", &typeInfo, 0) ;
236 return type;
240 * atk_object_get_name
241 * @accessible: a #AtkObject
242 * return values: a character string representing the accessible name of the object.
244 * Gets the accessible name of the accessible
246 G_CONST_RETURN gchar*
247 atk_object_get_name (AtkObject *accessible)
249 AtkObjectClass *klass;
251 g_return_val_if_fail (accessible != NULL, NULL);
252 g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
254 klass = ATK_OBJECT_GET_CLASS (accessible);
255 if (klass->get_name)
256 return (klass->get_name) (accessible);
257 else
258 return NULL;
262 * atk_object_get_description
263 * @accessible: a #AtkObject
264 * return values: a character string representing the accessible description of the accessible.
266 * Gets the accessible description of the accessible
268 G_CONST_RETURN gchar*
269 atk_object_get_description (AtkObject *accessible)
271 AtkObjectClass *klass;
273 g_return_val_if_fail (accessible != NULL, NULL);
274 g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
276 klass = ATK_OBJECT_GET_CLASS (accessible);
277 if (klass->get_description)
278 return (klass->get_description) (accessible);
279 else
280 return NULL;
284 * atk_object_get_parent
285 * @accessible: a #AtkObject
286 * return values: a #AtkObject representing the accessible parent of the accessible.
288 * Gets the accessible description of the accessible
290 AtkObject*
291 atk_object_get_parent (AtkObject *accessible)
293 AtkObjectClass *klass;
295 g_return_val_if_fail (accessible != NULL, NULL);
296 g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
298 klass = ATK_OBJECT_GET_CLASS (accessible);
299 if (klass->get_parent)
300 return (klass->get_parent) (accessible);
301 else
302 return NULL;
306 * atk_object_get_n_accessible_children
307 * @accessible: a #AtkObject
308 * return values: a gint representing the number of accessible children of the accessible.
310 * Gets the number of accessible children of the accessible
312 gint
313 atk_object_get_n_accessible_children (AtkObject *accessible)
315 AtkObjectClass *klass;
317 g_return_val_if_fail (accessible != NULL, 0);
318 g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
320 klass = ATK_OBJECT_GET_CLASS (accessible);
321 if (klass->get_n_children)
322 return (klass->get_n_children) (accessible);
323 else
324 return 0;
328 * atk_object_ref_accessible_child
329 * @accessible: a #AtkObject
330 * @i: a gint representing the position of the child, starting from 0
331 * return values: a #AtkObject representing the specified accessible child of the accessible.
333 * Returns a reference to the specified accessible child of the object.
334 * The accessible children are 0-based so the first accessible child is
335 * at index 0, the second at index 1 and so on.
337 AtkObject*
338 atk_object_ref_accessible_child (AtkObject *accessible,
339 gint i)
341 AtkObjectClass *klass;
343 g_return_val_if_fail (accessible != NULL, NULL);
344 g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
346 klass = ATK_OBJECT_GET_CLASS (accessible);
347 if (klass->ref_child)
348 return (klass->ref_child) (accessible, i);
349 else
350 return NULL;
354 * atk_object_ref_accessible_child
355 * @accessible: a #AtkObject
356 * return values: a #AtkRelationSet representing the relation set of the object.
358 * Returns a relation to the relation set associated of the accessible.
360 AtkRelationSet*
361 atk_object_ref_relation_set (AtkObject *accessible)
363 AtkObjectClass *klass;
365 g_return_val_if_fail (accessible != NULL, NULL);
366 g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
368 klass = ATK_OBJECT_GET_CLASS (accessible);
369 if (klass->ref_relation_set)
370 return (klass->ref_relation_set) (accessible);
371 else
372 return NULL;
376 * atk_role_register
377 * @name: a character string describing the new role.
378 * return values: a #AtkRole value for the new role.
380 * Returns a #AtkRole value for the new role.
382 AtkRole
383 atk_role_register (const gchar *name)
385 /* TODO: associate name with new type */
386 static guint type = ATK_ROLE_LAST_DEFINED;
387 return (++type);
391 * atk_object_get_role
392 * @accessible: a #AtkObject
393 * return values: a #AtkRole which is the role of the accessible
395 * Gets the role of the accessible
397 AtkRole
398 atk_object_get_role (AtkObject *accessible) {
399 AtkObjectClass *klass;
401 g_return_val_if_fail (accessible != NULL, ATK_ROLE_UNKNOWN);
402 g_return_val_if_fail (ATK_IS_OBJECT (accessible), ATK_ROLE_UNKNOWN);
404 klass = ATK_OBJECT_GET_CLASS (accessible);
405 if (klass->get_role)
406 return (klass->get_role) (accessible);
407 else
408 return ATK_ROLE_UNKNOWN;
412 * atk_state_register
413 * @name: a character string describing the new state.
414 * return values: a #AtkState value for the new state.
416 * Returns a #AtkState value for the new state.
418 AtkStateType
419 atk_state_type_register (const gchar *name)
421 /* TODO: associate name with new type */
422 static guint type = ATK_STATE_LAST_DEFINED;
423 if (type < NUM_POSSIBLE_STATES) {
424 return (++type);
426 return ATK_STATE_INVALID; /* caller needs to check */
430 * atk_object_ref_state_set
431 * @accessible: a #AtkObject
432 * return values: a reference to a #AtkStateSet which is the state set of the accessible
434 * returns a reference to the state set of the accessible; the caller should
435 * unreference it.
437 AtkStateSet*
438 atk_object_ref_state_set (AtkObject *accessible) {
439 AtkObjectClass *klass;
441 g_return_val_if_fail (accessible != NULL, NULL);
442 g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
444 klass = ATK_OBJECT_GET_CLASS (accessible);
445 if (klass->ref_state_set)
446 return (klass->ref_state_set) (accessible);
447 else
448 return NULL;
452 * atk_object_get_index_in_parent
453 * @accessible: a #AtkObject
454 * return values: a gint which is the index of the accessible in its parent
456 * Gets the 0-based index of this accessible in its parent; returns -1 if the
457 * accessible does not have an accessible parent.
459 gint
460 atk_object_get_index_in_parent (AtkObject *accessible)
462 AtkObjectClass *klass;
464 g_return_val_if_fail (accessible != NULL, -1);
465 g_return_val_if_fail (ATK_OBJECT (accessible), -1);
467 klass = ATK_OBJECT_GET_CLASS (accessible);
468 if (klass->get_index_in_parent)
469 return (klass->get_index_in_parent) (accessible);
470 else
471 return -1;
475 * atk_object_set_name
476 * @accessible: a #AtkObject
477 * @name : a character string to be set as the accessible name
479 * Sets the accessible name of the accessible
481 void
482 atk_object_set_name (AtkObject *accessible,
483 const gchar *name)
485 AtkObjectClass *klass;
487 g_return_if_fail (accessible != NULL);
488 g_return_if_fail (ATK_IS_OBJECT (accessible));
489 g_return_if_fail (name != NULL);
491 klass = ATK_OBJECT_GET_CLASS (accessible);
492 if (klass->set_name)
494 (klass->set_name) (accessible, name);
495 g_object_notify (G_OBJECT (accessible), atk_object_name_property_name);
500 * atk_object_set_name
501 * @accessible: a #AtkObject
502 * @description : a character string to be set as the accessible description
504 * Sets the accessible description of the accessible
506 void
507 atk_object_set_description (AtkObject *accessible,
508 const gchar *description)
510 AtkObjectClass *klass;
512 g_return_if_fail (accessible != NULL);
513 g_return_if_fail (ATK_IS_OBJECT (accessible));
514 g_return_if_fail (description != NULL);
516 klass = ATK_OBJECT_GET_CLASS (accessible);
517 if (klass->set_description)
519 (klass->set_description) (accessible, description);
520 g_object_notify (G_OBJECT (accessible), atk_object_name_property_description);
525 * atk_object_set_name
526 * @accessible: a #AtkObject
527 * @parent : a #AtkObject to be set as the accessible parent
529 * Sets the accessible parent of the accessible
531 void
532 atk_object_set_parent (AtkObject *accessible,
533 AtkObject *parent)
535 AtkObjectClass *klass;
537 g_return_if_fail (accessible != NULL);
538 g_return_if_fail (ATK_IS_OBJECT (accessible));
540 klass = ATK_OBJECT_GET_CLASS (accessible);
541 if (klass->set_parent)
542 (klass->set_parent) (accessible, parent);
546 * atk_object_set_name
547 * @accessible: a #AtkObject
548 * @role : a #AtkRole to be set as the role
550 * Sets the role of the accessible
552 void
553 atk_object_set_role (AtkObject *accessible,
554 AtkRole role)
556 AtkObjectClass *klass;
558 g_return_if_fail (accessible != NULL);
559 g_return_if_fail (ATK_IS_OBJECT (accessible));
561 klass = ATK_OBJECT_GET_CLASS (accessible);
562 if (klass->set_role)
563 (klass->set_role) (accessible, role);
566 guint
567 atk_object_connect_property_change_handler (AtkObject *accessible,
568 AtkPropertyChangeHandler *handler)
570 AtkObjectClass *klass;
572 g_return_val_if_fail (accessible != NULL, 0);
573 g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
574 g_return_val_if_fail ((handler != NULL), 0);
576 klass = ATK_OBJECT_GET_CLASS (accessible);
577 if (klass->connect_property_change_handler)
578 return (klass->connect_property_change_handler) (accessible, handler);
579 else
580 return 0;
583 void
584 atk_object_remove_property_change_handler (AtkObject *accessible,
585 guint handler_id)
587 AtkObjectClass *klass;
589 g_return_if_fail (accessible != NULL);
590 g_return_if_fail (ATK_IS_OBJECT (accessible));
592 klass = ATK_OBJECT_GET_CLASS (accessible);
593 if (klass->remove_property_change_handler)
594 (klass->remove_property_change_handler) (accessible, handler_id);
597 G_CONST_RETURN gchar*
598 atk_state_mask_get_name (AtkStateMask state)
600 gint n;
602 if (state == 0)
603 return NULL;
605 for (n=0; n<NUM_POSSIBLE_STATES; ++n)
607 /* fall through and return null if multiple bits are set */
608 if (state == (1 << n)) return state_names[n];
611 return NULL;
614 AtkStateMask
615 atk_state_mask_for_name (const gchar *name)
617 gint i;
619 g_return_val_if_fail ((strlen(name)>0), 0);
620 for (i=0; i<NUM_POSSIBLE_STATES; ++i)
622 if (!strcmp(name, state_names[i])) return ATK_STATE(i);
624 return 0;
628 * atk_implementor_ref_accessible
629 * @object: The GObject instance which should implement #AtkImplementorIface
630 * if a non-null return value is required.
631 * Return a reference to an object's AtkObject implementation, if
632 * the object implements AtkObjectIface.
634 AtkObject *
635 atk_implementor_ref_accessible (AtkImplementor *object)
637 AtkImplementorIface *iface;
638 AtkObject *accessible = NULL;
640 g_return_val_if_fail (object != NULL, NULL);
641 g_return_val_if_fail (ATK_IS_IMPLEMENTOR (object), NULL);
643 iface = ATK_IMPLEMENTOR_GET_IFACE (object);
645 if (iface != NULL)
646 accessible = iface->ref_accessible (object);
648 g_return_val_if_fail ((accessible != NULL), NULL);
650 return accessible;
653 static AtkRelationSet*
654 atk_object_real_ref_relation_set (AtkObject *accessible)
656 if (accessible->relation_set)
657 g_object_ref (accessible->relation_set);
659 return accessible->relation_set;
662 static void
663 atk_object_real_set_property (GObject *object,
664 guint prop_id,
665 const GValue *value,
666 GParamSpec *pspec)
668 AtkObject *accessible;
670 accessible = ATK_OBJECT (object);
672 switch (prop_id)
674 case PROP_NAME:
675 atk_object_set_name (accessible, g_value_get_string (value));
676 break;
677 case PROP_DESCRIPTION:
678 atk_object_set_description (accessible, g_value_get_string (value));
679 break;
680 case PROP_STATE:
681 g_print ("This interface does not support setting the state of an accessible object\n");
682 break;
683 default:
684 break;
688 static void
689 atk_object_real_get_property (GObject *object,
690 guint prop_id,
691 GValue *value,
692 GParamSpec *pspec)
694 AtkObject *accessible;
696 accessible = ATK_OBJECT (object);
698 switch (prop_id)
700 case PROP_NAME:
701 g_value_set_string (value, atk_object_get_name (accessible));
702 break;
703 case PROP_DESCRIPTION:
704 g_value_set_string (value, atk_object_get_description (accessible));
705 break;
706 default:
707 break;
711 static void
712 atk_object_finalize (GObject *object)
714 AtkObject *accessible;
716 g_return_if_fail (ATK_IS_OBJECT (object));
718 accessible = ATK_OBJECT (object);
720 g_free (accessible->name);
721 g_free (accessible->description);
724 * Free memory allocated for relation set if it have been allocated.
726 if (accessible->relation_set)
728 g_object_unref (accessible->relation_set);
731 G_OBJECT_CLASS (parent_class)->finalize (object);