Add po directory
[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 #include "atkmarshal.h"
26 #include "atk-enum-types.h"
27 #include "atkintl.h"
28
29 GPtrArray *extra_roles = NULL;
30
31 enum
32 {
33   PROP_0,  /* gobject convention */
34
35   PROP_NAME,
36   PROP_DESCRIPTION,
37   PROP_PARENT,      /* ancestry has changed */
38   PROP_VALUE,
39   PROP_ROLE,
40   PROP_LAYER,
41   PROP_MDI_ZORDER,
42   PROP_TABLE_CAPTION,
43   PROP_TABLE_COLUMN_DESCRIPTION,
44   PROP_TABLE_COLUMN_HEADER,
45   PROP_TABLE_ROW_DESCRIPTION,
46   PROP_TABLE_ROW_HEADER,
47   PROP_TABLE_SUMMARY,
48   PROP_LAST         /* gobject convention */
49 };
50
51 enum {
52   CHILDREN_CHANGED,
53   FOCUS_EVENT,
54   PROPERTY_CHANGE,
55   STATE_CHANGE,
56   VISIBLE_DATA_CHANGED,
57   
58   LAST_SIGNAL
59 };
60
61 static void            atk_object_class_init        (AtkObjectClass  *klass);
62 static void            atk_object_init              (AtkObject       *accessible,
63                                                      AtkObjectClass  *klass);
64 static AtkRelationSet* atk_object_real_ref_relation_set 
65                                                     (AtkObject       *accessible);
66
67 static void            atk_object_real_set_property (GObject         *object,
68                                                      guint            prop_id,
69                                                      const GValue    *value,
70                                                      GParamSpec      *pspec);
71 static void            atk_object_real_get_property (GObject         *object,
72                                                      guint            prop_id,
73                                                      GValue          *value,
74                                                      GParamSpec      *pspec);
75 static void            atk_object_finalize          (GObject         *object);
76 static G_CONST_RETURN gchar*
77                        atk_object_real_get_name     (AtkObject       *object);
78 static G_CONST_RETURN gchar*
79                        atk_object_real_get_description    
80                                                    (AtkObject       *object);
81 static AtkObject*      atk_object_real_get_parent  (AtkObject       *object);
82 static AtkRole         atk_object_real_get_role    (AtkObject       *object);
83 static AtkLayer        atk_object_real_get_layer   (AtkObject       *object);
84 static AtkStateSet*    atk_object_real_ref_state_set
85                                                    (AtkObject       *object);
86 static void            atk_object_real_set_name    (AtkObject       *object,
87                                                     const gchar     *name);
88 static void            atk_object_real_set_description
89                                                    (AtkObject       *object,
90                                                     const gchar     *description);
91 static void            atk_object_real_set_parent  (AtkObject       *object,
92                                                     AtkObject       *parent);
93 static void            atk_object_real_set_role    (AtkObject       *object,
94                                                     AtkRole         role);
95 static guint           atk_object_real_connect_property_change_handler
96                                                    (AtkObject       *obj,
97                                                     AtkPropertyChangeHandler
98                                                                     *handler);
99 static void            atk_object_real_remove_property_change_handler
100                                                    (AtkObject       *obj,
101                                                     guint           handler_id);
102 static void            atk_object_notify           (GObject         *obj,
103                                                     GParamSpec      *pspec);
104
105
106 static guint atk_object_signals[LAST_SIGNAL] = { 0, };
107
108 static gpointer parent_class = NULL;
109
110 static const gchar* atk_object_name_property_name = "accessible-name";
111 static const gchar* atk_object_name_property_description = "accessible-description";
112 static const gchar* atk_object_name_property_parent = "accessible-parent";
113 static const gchar* atk_object_name_property_value = "accessible-value";
114 static const gchar* atk_object_name_property_role = "accessible-role";
115 static const gchar* atk_object_name_property_component_layer = "accessible-component-layer";
116 static const gchar* atk_object_name_property_component_mdi_zorder = "accessible-component-mdi-zorder";
117 static const gchar* atk_object_name_property_table_caption = "accessible-table-caption";
118 static const gchar* atk_object_name_property_table_column_description = "accessible-table-column-description";
119 static const gchar* atk_object_name_property_table_column_header = "accessible-table-column-header";
120 static const gchar* atk_object_name_property_table_row_description = "accessible-table-row-description";
121 static const gchar* atk_object_name_property_table_row_header = "accessible-table-row-header";
122 static const gchar* atk_object_name_property_table_summary = "accessible-table-summary";
123
124 GType
125 atk_object_get_type (void)
126 {
127   static GType type = 0;
128
129   if (!type)
130     {
131       static const GTypeInfo typeInfo =
132       {
133         sizeof (AtkObjectClass),
134         (GBaseInitFunc) NULL,
135         (GBaseFinalizeFunc) NULL,
136         (GClassInitFunc) atk_object_class_init,
137         (GClassFinalizeFunc) NULL,
138         NULL,
139         sizeof (AtkObject),
140         0,
141         (GInstanceInitFunc) atk_object_init,
142       } ;
143       type = g_type_register_static (G_TYPE_OBJECT, "AtkObject", &typeInfo, 0) ;
144     }
145   return type;
146 }
147
148 static void
149 atk_object_class_init (AtkObjectClass *klass)
150 {
151   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
152
153   parent_class = g_type_class_peek_parent (klass);
154
155   gobject_class->set_property = atk_object_real_set_property;
156   gobject_class->get_property = atk_object_real_get_property;
157   gobject_class->finalize = atk_object_finalize;
158   gobject_class->notify = atk_object_notify;
159
160   klass->get_name = atk_object_real_get_name;
161   klass->get_description = atk_object_real_get_description;
162   klass->get_parent = atk_object_real_get_parent;
163   klass->get_n_children = NULL;
164   klass->ref_child = NULL;
165   klass->get_index_in_parent = NULL;
166   klass->ref_relation_set = atk_object_real_ref_relation_set;
167   klass->get_role = atk_object_real_get_role;
168   klass->get_layer = atk_object_real_get_layer;
169   klass->get_mdi_zorder = NULL;
170   klass->ref_state_set = atk_object_real_ref_state_set;
171   klass->set_name = atk_object_real_set_name;
172   klass->set_description = atk_object_real_set_description;
173   klass->set_parent = atk_object_real_set_parent;
174   klass->set_role = atk_object_real_set_role;
175   klass->connect_property_change_handler = 
176          atk_object_real_connect_property_change_handler;
177   klass->remove_property_change_handler = 
178          atk_object_real_remove_property_change_handler;
179
180   /*
181    * We do not define default signal handlers here
182    */
183   klass->children_changed = NULL;
184   klass->focus_event = NULL;
185   klass->property_change = NULL;
186   klass->visible_data_changed = NULL;
187
188   g_object_class_install_property (gobject_class,
189                                    PROP_NAME,
190                                    g_param_spec_string (atk_object_name_property_name,
191                                                         "Accessible Name",
192                                                         "Object instance\'s name formatted for "
193                                                            "assistive technology access",
194                                                         NULL,
195                                                         G_PARAM_READWRITE));
196   g_object_class_install_property (gobject_class,
197                                    PROP_DESCRIPTION,
198                                    g_param_spec_string (atk_object_name_property_description,
199                                                         "Accessible Description",
200                                                         "Description of an object, formatted for "
201                                                         "assistive technology access",
202                                                         NULL,
203                                                         G_PARAM_READWRITE));
204   g_object_class_install_property (gobject_class,
205                                    PROP_PARENT,
206                                    g_param_spec_object (atk_object_name_property_parent,
207                                                         "Accessible Parent",
208                                                         "Is used to notify that the parent has changed ",
209                                                         ATK_TYPE_OBJECT,
210                                                         G_PARAM_READWRITE));
211   g_object_class_install_property (gobject_class,
212                                    PROP_VALUE,
213                                    g_param_spec_double (atk_object_name_property_value,
214                                                         "Accessible Value",
215                                                         "Is used to notify that the value has changed ",
216                                                         0.0,
217                                                         G_MAXDOUBLE,
218                                                         0.0,
219                                                         G_PARAM_READWRITE));
220   g_object_class_install_property (gobject_class,
221                                    PROP_ROLE,
222                                    g_param_spec_int    (atk_object_name_property_role,
223                                                         "Accessible Role",
224                                                         "The accessible role of this object ",
225                                                         0,
226                                                         G_MAXINT,
227                                                         0,
228                                                         G_PARAM_READWRITE));
229   g_object_class_install_property (gobject_class,
230                                    PROP_LAYER,
231                                    g_param_spec_int    (atk_object_name_property_component_layer,
232                                                         "Accessible Layer",
233                                                         "The accessible layer of this object ",
234                                                         0,
235                                                         G_MAXINT,
236                                                         0,
237                                                         G_PARAM_READABLE));
238   g_object_class_install_property (gobject_class,
239                                    PROP_MDI_ZORDER,
240                                    g_param_spec_int    (atk_object_name_property_component_mdi_zorder,
241                                                         "Accessible MDI Value",
242                                                         "The accessible MDI value of this object ",
243                                                         G_MININT,
244                                                         G_MAXINT,
245                                                         G_MININT,
246                                                         G_PARAM_READABLE));
247   g_object_class_install_property (gobject_class,
248                                    PROP_TABLE_CAPTION,
249                                    g_param_spec_string (atk_object_name_property_table_caption,
250                                                         "Accessible Table Caption",
251                                                         "Is used to notify that the table caption has changed ",
252                                                         NULL,
253                                                         G_PARAM_READWRITE));
254   g_object_class_install_property (gobject_class,
255                                    PROP_TABLE_COLUMN_HEADER,
256                                    g_param_spec_object (atk_object_name_property_table_column_header,
257                                                         "Accessible Table Column Header",
258                                                         "Is used to notify that the table column header has changed ",
259                                                         ATK_TYPE_OBJECT,
260                                                         G_PARAM_READWRITE));
261   g_object_class_install_property (gobject_class,
262                                    PROP_TABLE_COLUMN_DESCRIPTION,
263                                    g_param_spec_string (atk_object_name_property_table_column_description,
264                                                         "Accessible Table Column Description",
265                                                         "Is used to notify that the table columnscription has changed ",
266                                                         NULL,
267                                                         G_PARAM_READWRITE));
268   g_object_class_install_property (gobject_class,
269                                    PROP_TABLE_ROW_HEADER,
270                                    g_param_spec_object (atk_object_name_property_table_row_header,
271                                                         "Accessible Table Row Header",
272                                                         "Is used to notify that the table row header has changed ",
273                                                         ATK_TYPE_OBJECT,
274                                                         G_PARAM_READWRITE));
275   g_object_class_install_property (gobject_class,
276                                    PROP_TABLE_ROW_DESCRIPTION,
277                                    g_param_spec_string (atk_object_name_property_table_row_description,
278                                                         "Accessible Table Row Description",
279                                                         "Is used to notify that the table row description has changed ",
280                                                         NULL,
281                                                         G_PARAM_READWRITE));
282   g_object_class_install_property (gobject_class,
283                                    PROP_TABLE_SUMMARY,
284                                    g_param_spec_object (atk_object_name_property_table_summary,
285                                                         "Accessible Table Summary",
286                                                         "Is used to notify that the table summary has changed ",
287                                                         ATK_TYPE_OBJECT,
288                                                         G_PARAM_READWRITE));
289   /*
290    * The signal "children_changed" supports two details:
291    * "add" and "remove"
292    */
293   atk_object_signals[CHILDREN_CHANGED] =
294     g_signal_new ("children_changed",
295                   G_TYPE_FROM_CLASS (klass),
296                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
297                   G_STRUCT_OFFSET (AtkObjectClass, children_changed),
298                   NULL, NULL,
299                   g_cclosure_marshal_VOID__UINT_POINTER,
300                   G_TYPE_NONE,
301                   2, G_TYPE_UINT, G_TYPE_POINTER);
302   atk_object_signals[FOCUS_EVENT] =
303     g_signal_new ("focus_event",
304                   G_TYPE_FROM_CLASS (klass),
305                   G_SIGNAL_RUN_LAST,
306                   G_STRUCT_OFFSET (AtkObjectClass, focus_event), 
307                   NULL, NULL,
308                   g_cclosure_marshal_VOID__BOOLEAN,
309                   G_TYPE_NONE,
310                   1, G_TYPE_BOOLEAN);
311   atk_object_signals[PROPERTY_CHANGE] =
312     g_signal_new ("property_change",
313                   G_TYPE_FROM_CLASS (klass),
314                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
315                   G_STRUCT_OFFSET (AtkObjectClass, property_change),
316                   (GSignalAccumulator) NULL, NULL,
317                   g_cclosure_marshal_VOID__POINTER,
318                   G_TYPE_NONE, 1,
319                   G_TYPE_POINTER);
320   /*
321    * The "state_change" signal supports details, one for each accessible 
322    * state type
323    * (see atkstate.c).
324    */
325   atk_object_signals[STATE_CHANGE] =
326     g_signal_new ("state_change",
327                   G_TYPE_FROM_CLASS (klass),
328                   G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
329                   G_STRUCT_OFFSET (AtkObjectClass, state_change),
330                   (GSignalAccumulator) NULL, NULL,
331                   atk_marshal_VOID__STRING_BOOLEAN,
332                   G_TYPE_NONE, 2,
333                   G_TYPE_STRING,
334                   G_TYPE_BOOLEAN);
335   atk_object_signals[VISIBLE_DATA_CHANGED] =
336     g_signal_new ("visible_data_changed",
337                   G_TYPE_FROM_CLASS (klass),
338                   G_SIGNAL_RUN_LAST,
339                   G_STRUCT_OFFSET (AtkObjectClass, visible_data_changed),
340                   (GSignalAccumulator) NULL, NULL,
341                   g_cclosure_marshal_VOID__VOID,
342                   G_TYPE_NONE, 0);
343 }
344
345 static void
346 atk_object_init  (AtkObject        *accessible,
347                   AtkObjectClass   *klass)
348 {
349   accessible->name = NULL;
350   accessible->description = NULL;
351   accessible->accessible_parent = NULL;
352   accessible->relation_set = atk_relation_set_new();
353   accessible->role = ATK_ROLE_UNKNOWN;
354 }
355
356 GType
357 atk_implementor_get_type (void)
358 {
359   static GType type = 0;
360
361   if (!type)
362     {
363       static const GTypeInfo typeInfo =
364       {
365         sizeof (AtkImplementorIface),
366         (GBaseInitFunc) NULL,
367         (GBaseFinalizeFunc) NULL,
368       } ;
369
370       type = g_type_register_static (G_TYPE_INTERFACE, "AtkImplementorIface", &typeInfo, 0) ;
371     }
372
373   return type;
374 }
375
376 /**
377  * atk_object_get_name:
378  * @accessible: an #AtkObject
379  *
380  * Gets the accessible name of the accessible.
381  *
382  * Returns: a character string representing the accessible name of the object.
383  **/
384 G_CONST_RETURN gchar*
385 atk_object_get_name (AtkObject *accessible)
386 {
387   AtkObjectClass *klass;
388
389   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
390
391   klass = ATK_OBJECT_GET_CLASS (accessible);
392   if (klass->get_name)
393     return (klass->get_name) (accessible);
394   else
395     return NULL;
396 }
397
398 /**
399  * atk_object_get_description:
400  * @accessible: an #AtkObject
401  *
402  * Gets the accessible description of the accessible.
403  *
404  * Returns: a character string representing the accessible description
405  * of the accessible.
406  *
407  **/
408 G_CONST_RETURN gchar*
409 atk_object_get_description (AtkObject *accessible)
410 {
411   AtkObjectClass *klass;
412
413   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
414
415   klass = ATK_OBJECT_GET_CLASS (accessible);
416   if (klass->get_description)
417     return (klass->get_description) (accessible);
418   else
419     return NULL;
420 }
421
422 /**
423  * atk_object_get_parent:
424  * @accessible: an #AtkObject
425  *
426  * Gets the accessible parent of the accessible.
427  *
428  * Returns: a #AtkObject representing the accessible parent of the accessible
429  **/
430 AtkObject*
431 atk_object_get_parent (AtkObject *accessible)
432 {
433   AtkObjectClass *klass;
434
435   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
436
437   klass = ATK_OBJECT_GET_CLASS (accessible);
438   if (klass->get_parent)
439     return (klass->get_parent) (accessible);
440   else
441     return NULL;
442 }
443
444 /**
445  * atk_object_get_n_accessible_children:
446  * @accessible: an #AtkObject
447  *
448  * Gets the number of accessible children of the accessible.
449  *
450  * Returns: an integer representing the number of accessible children
451  * of the accessible.
452  **/
453 gint
454 atk_object_get_n_accessible_children (AtkObject *accessible)
455 {
456   AtkObjectClass *klass;
457
458   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
459
460   klass = ATK_OBJECT_GET_CLASS (accessible);
461   if (klass->get_n_children)
462     return (klass->get_n_children) (accessible);
463   else
464     return 0;
465 }
466
467 /**
468  * atk_object_ref_accessible_child:
469  * @accessible: an #AtkObject
470  * @i: a gint representing the position of the child, starting from 0
471  *
472  * Gets a reference to the specified accessible child of the object.
473  * The accessible children are 0-based so the first accessible child is
474  * at index 0, the second at index 1 and so on.
475  *
476  * Returns: an #AtkObject representing the specified accessible child
477  * of the accessible.
478  **/
479 AtkObject*
480 atk_object_ref_accessible_child (AtkObject   *accessible,
481                                  gint        i)
482 {
483   AtkObjectClass *klass;
484
485   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
486
487   klass = ATK_OBJECT_GET_CLASS (accessible);
488   if (klass->ref_child)
489     return (klass->ref_child) (accessible, i);
490   else
491     return NULL;
492 }
493
494 /**
495  * atk_object_ref_relation_set:
496  * @accessible: an #AtkObject
497  *
498  * Gets the #AtkRelationSet associated with the object.
499  *
500  * Returns: an #AtkRelationSet representing the relation set of the object.
501  **/
502 AtkRelationSet*
503 atk_object_ref_relation_set (AtkObject *accessible)
504 {
505   AtkObjectClass *klass;
506
507   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
508
509   klass = ATK_OBJECT_GET_CLASS (accessible);
510   if (klass->ref_relation_set)
511     return (klass->ref_relation_set) (accessible);
512   else
513     return NULL;
514 }
515
516 /**
517  * atk_role_register:
518  * @name: a character string describing the new role.
519  *
520  * Registers the role specified by @name.
521  *
522  * Returns: an #AtkRole for the new role.
523  **/
524 AtkRole
525 atk_role_register (const gchar *name)
526 {
527   if (!extra_roles)
528     extra_roles = g_ptr_array_new ();
529
530   g_ptr_array_add (extra_roles, g_strdup (name));
531   return extra_roles->len + ATK_ROLE_LAST_DEFINED;
532 }
533
534 /**
535  * atk_object_get_role:
536  * @accessible: an #AtkObject
537  *
538  * Gets the role of the accessible.
539  *
540  * Returns: an #AtkRole which is the role of the accessible
541  **/
542 AtkRole
543 atk_object_get_role (AtkObject *accessible) 
544 {
545   AtkObjectClass *klass;
546
547   g_return_val_if_fail (ATK_IS_OBJECT (accessible), ATK_ROLE_UNKNOWN);
548
549   klass = ATK_OBJECT_GET_CLASS (accessible);
550   if (klass->get_role)
551     return (klass->get_role) (accessible);
552   else
553     return ATK_ROLE_UNKNOWN;
554 }
555
556 /**
557  * atk_object_get_layer:
558  * @accessible: an #AtkObject
559  *
560  * Gets the layer of the accessible.
561  * DEPRECATED: use atk_component_get_layer instead!
562  *
563  * Returns: an #AtkLayer which is the layer of the accessible
564  **/
565 AtkLayer
566 atk_object_get_layer (AtkObject *accessible) 
567 {
568   AtkObjectClass *klass;
569
570   g_return_val_if_fail (ATK_IS_OBJECT (accessible), ATK_LAYER_INVALID);
571
572   klass = ATK_OBJECT_GET_CLASS (accessible);
573   if (klass->get_layer)
574     return (klass->get_layer) (accessible);
575   else
576     return ATK_LAYER_INVALID;
577 }
578
579 /**
580  * atk_object_get_mdi_zorder:
581  * @accessible: an #AtkObject
582  *
583  * Gets the zorder of the accessible. The value G_MININT will be returned 
584  * if the layer of the accessible is not ATK_LAYER_MDI.
585  * DEPRECATED: use atk_component_get_mdi_zorder instead!
586  *
587  * Returns: a gint which is the zorder of the accessible, i.e. the depth at 
588  * which the component is shown in relation to other components in the same 
589  * container.
590  **/
591 gint
592 atk_object_get_mdi_zorder (AtkObject *accessible) 
593 {
594   AtkObjectClass *klass;
595
596   g_return_val_if_fail (ATK_IS_OBJECT (accessible), G_MININT);
597
598   klass = ATK_OBJECT_GET_CLASS (accessible);
599   if (klass->get_mdi_zorder)
600     return (klass->get_mdi_zorder) (accessible);
601   else
602     return G_MININT;
603 }
604
605 /**
606  * atk_object_ref_state_set:
607  * @accessible: an #AtkObject
608  *
609  * Gets a reference to the state set of the accessible; the caller must
610  * unreference it when it is no longer needed.
611  *
612  * Returns: a reference to an #AtkStateSet which is the state
613  * set of the accessible
614  **/
615 AtkStateSet*
616 atk_object_ref_state_set (AtkObject *accessible) 
617 {
618   AtkObjectClass *klass;
619
620   g_return_val_if_fail (ATK_IS_OBJECT (accessible), NULL);
621
622   klass = ATK_OBJECT_GET_CLASS (accessible);
623   if (klass->ref_state_set)
624     return (klass->ref_state_set) (accessible);
625   else
626     return NULL;
627 }
628
629 /**
630  * atk_object_get_index_in_parent:
631  * @accessible: an #AtkObject
632  *
633  * Gets the 0-based index of this accessible in its parent; returns -1 if the
634  * accessible does not have an accessible parent.
635  *
636  * Returns: an integer which is the index of the accessible in its parent
637  **/
638 gint
639 atk_object_get_index_in_parent (AtkObject *accessible)
640 {
641   AtkObjectClass *klass;
642
643   g_return_val_if_fail (ATK_OBJECT (accessible), -1);
644
645   klass = ATK_OBJECT_GET_CLASS (accessible);
646   if (klass->get_index_in_parent)
647     return (klass->get_index_in_parent) (accessible);
648   else
649     return -1;
650 }
651
652 /**
653  * atk_object_set_name:
654  * @accessible: an #AtkObject
655  * @name: a character string to be set as the accessible name
656  *
657  * Sets the accessible name of the accessible.
658  **/
659 void
660 atk_object_set_name (AtkObject    *accessible,
661                      const gchar  *name)
662 {
663   AtkObjectClass *klass;
664
665   g_return_if_fail (ATK_IS_OBJECT (accessible));
666   g_return_if_fail (name != NULL);
667
668   klass = ATK_OBJECT_GET_CLASS (accessible);
669   if (klass->set_name)
670     {
671       (klass->set_name) (accessible, name);
672       g_object_notify (G_OBJECT (accessible), atk_object_name_property_name);
673     }
674 }
675
676 /**
677  * atk_object_set_description:
678  * @accessible: an #AtkObject
679  * @description : a character string to be set as the accessible description
680  *
681  * Sets the accessible description of the accessible.
682  **/
683 void
684 atk_object_set_description (AtkObject   *accessible,
685                             const gchar *description)
686 {
687   AtkObjectClass *klass;
688
689   g_return_if_fail (ATK_IS_OBJECT (accessible));
690   g_return_if_fail (description != NULL);
691
692   klass = ATK_OBJECT_GET_CLASS (accessible);
693   if (klass->set_description)
694     {
695       (klass->set_description) (accessible, description);
696       g_object_notify (G_OBJECT (accessible), atk_object_name_property_description);
697     }
698 }
699
700 /**
701  * atk_object_set_parent:
702  * @accessible: an #AtkObject
703  * @parent : an #AtkObject to be set as the accessible parent
704  *
705  * Sets the accessible parent of the accessible.
706  **/
707 void
708 atk_object_set_parent (AtkObject *accessible,
709                        AtkObject *parent)
710 {
711   AtkObjectClass *klass;
712
713   g_return_if_fail (ATK_IS_OBJECT (accessible));
714
715   klass = ATK_OBJECT_GET_CLASS (accessible);
716   if (klass->set_parent)
717     {
718       (klass->set_parent) (accessible, parent);
719       g_object_notify (G_OBJECT (accessible), atk_object_name_property_parent);
720     }
721 }
722
723 /**
724  * atk_object_set_role:
725  * @accessible: an #AtkObject
726  * @role : an #AtkRole to be set as the role
727  *
728  * Sets the role of the accessible.
729  **/
730 void
731 atk_object_set_role (AtkObject *accessible, 
732                      AtkRole   role)
733 {
734   AtkObjectClass *klass;
735
736   g_return_if_fail (ATK_IS_OBJECT (accessible));
737
738   klass = ATK_OBJECT_GET_CLASS (accessible);
739   if (klass->set_role)
740     {
741       (klass->set_role) (accessible, role);
742       g_object_notify (G_OBJECT (accessible), atk_object_name_property_role);
743     }
744 }
745
746 /**
747  * atk_object_connect_property_change_handler:
748  * @accessible: an #AtkObject
749  * @handler : a function to be called when a property changes its value
750  *
751  * Specifies a function to be called when a property changes value.
752  *
753  * Returns: a #guint which is the handler id used in 
754  * atk_object_remove_property_change_handler()
755  **/
756 guint
757 atk_object_connect_property_change_handler (AtkObject *accessible,
758                                             AtkPropertyChangeHandler *handler)
759 {
760   AtkObjectClass *klass;
761
762   g_return_val_if_fail (ATK_IS_OBJECT (accessible), 0);
763   g_return_val_if_fail ((handler != NULL), 0);
764
765   klass = ATK_OBJECT_GET_CLASS (accessible);
766   if (klass->connect_property_change_handler)
767     return (klass->connect_property_change_handler) (accessible, handler);
768   else
769     return 0;
770 }
771
772 /**
773  * atk_object_remove_property_change_handler:
774  * @accessible: an #AtkObject
775  * @handler_id : a guint which identifies the handler to be removed.
776  * 
777  * Removes a property change handler.
778  **/
779 void
780 atk_object_remove_property_change_handler  (AtkObject *accessible,
781                                             guint      handler_id)
782 {
783   AtkObjectClass *klass;
784
785   g_return_if_fail (ATK_IS_OBJECT (accessible));
786
787   klass = ATK_OBJECT_GET_CLASS (accessible);
788   if (klass->remove_property_change_handler)
789     (klass->remove_property_change_handler) (accessible, handler_id);
790 }
791
792 /**
793  * atk_object_notify_state_change:
794  * @accessible: an #AtkObject
795  * @state: an #AtkState whose state is changed
796  * @value : a gboolean which indicates whether the state is being set on or off
797  * 
798  * Emits a state-change signal for the specified state. 
799  **/
800 void
801 atk_object_notify_state_change (AtkObject *accessible,
802                                 AtkState  state,
803                                 gboolean  value)
804 {
805   G_CONST_RETURN gchar* name;
806
807   name = atk_state_type_get_name (state);
808   g_signal_emit (accessible, atk_object_signals[STATE_CHANGE],
809                  g_quark_from_string (name),
810                  name, value, NULL);
811 }
812
813 /**
814  * atk_implementor_ref_accessible:
815  * @implementor: The #GObject instance which should implement #AtkImplementorIface
816  * if a non-null return value is required.
817  * 
818  * Gets a reference to an object's #AtkObject implementation, if
819  * the object implements #AtkObjectIface
820  *
821  * Returns: a reference to an object's #AtkObject implementation
822  */
823 AtkObject *
824 atk_implementor_ref_accessible (AtkImplementor *object)
825 {
826   AtkImplementorIface *iface;
827   AtkObject           *accessible = NULL;
828
829   g_return_val_if_fail (ATK_IS_IMPLEMENTOR (object), NULL);
830
831   iface = ATK_IMPLEMENTOR_GET_IFACE (object);
832
833   if (iface != NULL) 
834     accessible =  iface->ref_accessible (object);
835
836   g_return_val_if_fail ((accessible != NULL), NULL);
837
838   return accessible;
839 }
840
841 static AtkRelationSet*
842 atk_object_real_ref_relation_set (AtkObject *accessible)
843 {
844   g_return_val_if_fail (accessible->relation_set, NULL);
845   g_object_ref (accessible->relation_set); 
846
847   return accessible->relation_set;
848 }
849
850 static void
851 atk_object_real_set_property (GObject      *object,
852                               guint         prop_id,
853                               const GValue *value,
854                               GParamSpec   *pspec)
855 {
856   AtkObject *accessible;
857
858   accessible = ATK_OBJECT (object);
859
860   switch (prop_id)
861     {
862     case PROP_NAME:
863       atk_object_set_name (accessible, g_value_get_string (value));
864       break;
865     case PROP_DESCRIPTION:
866       atk_object_set_description (accessible, g_value_get_string (value));
867       break;
868     case PROP_ROLE:
869       atk_object_set_role (accessible, g_value_get_int (value));
870       break;
871     case PROP_PARENT:
872       atk_object_set_parent (accessible, g_value_get_object (value));
873       break;
874     case PROP_VALUE:
875       if (ATK_IS_VALUE (accessible))
876         atk_value_set_current_value (ATK_VALUE (accessible), value);
877       break;
878     default:
879       break;
880     }
881 }
882
883 static void
884 atk_object_real_get_property (GObject      *object,
885                               guint         prop_id,
886                               GValue       *value,
887                               GParamSpec   *pspec)
888 {
889   AtkObject *accessible;
890
891   accessible = ATK_OBJECT (object);
892
893   switch (prop_id)
894     {
895     case PROP_NAME:
896       g_value_set_string (value, atk_object_get_name (accessible));
897       break;
898     case PROP_DESCRIPTION:
899       g_value_set_string (value, atk_object_get_description (accessible));
900       break;
901     case PROP_ROLE:
902       g_value_set_int (value, atk_object_get_role (accessible));
903       break;
904     case PROP_LAYER:
905       if (ATK_IS_COMPONENT (accessible))
906         g_value_set_int (value, atk_component_get_layer (ATK_COMPONENT (accessible)));
907       break;
908     case PROP_MDI_ZORDER:
909       if (ATK_IS_COMPONENT (accessible))
910         g_value_set_int (value, atk_component_get_mdi_zorder (ATK_COMPONENT (accessible)));
911       break;
912     case PROP_PARENT:
913       g_value_set_object (value, atk_object_get_parent (accessible));
914       break;
915     case PROP_VALUE:
916       if (ATK_IS_VALUE (accessible))
917         atk_value_get_current_value (ATK_VALUE (accessible), value);
918       break;
919     default:
920       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
921       break;
922     }
923 }
924
925 static void
926 atk_object_finalize (GObject *object)
927 {
928   AtkObject        *accessible;
929
930   g_return_if_fail (ATK_IS_OBJECT (object));
931
932   accessible = ATK_OBJECT (object);
933
934   g_free (accessible->name);
935   g_free (accessible->description);
936
937   /*
938    * Free memory allocated for relation set if it have been allocated.
939    */
940   if (accessible->relation_set)
941     g_object_unref (accessible->relation_set);
942
943   if (accessible->accessible_parent)
944     g_object_unref (accessible->accessible_parent);
945
946   G_OBJECT_CLASS (parent_class)->finalize (object);
947 }
948
949 static G_CONST_RETURN gchar*
950 atk_object_real_get_name (AtkObject *object)
951 {
952   return object->name;
953 }
954
955 static G_CONST_RETURN gchar*
956 atk_object_real_get_description (AtkObject *object)
957 {
958   return object->description;
959 }
960
961 static AtkObject*
962 atk_object_real_get_parent (AtkObject       *object)
963 {
964   return object->accessible_parent;
965 }
966
967 static AtkRole
968 atk_object_real_get_role (AtkObject       *object)
969 {
970   return object->role;
971 }
972
973 static AtkLayer
974 atk_object_real_get_layer (AtkObject       *object)
975 {
976   return object->layer;
977 }
978
979 static AtkStateSet*
980 atk_object_real_ref_state_set (AtkObject *accessible) 
981 {
982   AtkStateSet *state_set;
983   AtkObject *ap;
984
985   state_set = atk_state_set_new ();
986
987   ap = atk_object_get_parent (accessible);
988   if (ap)
989     if (ATK_IS_SELECTION (ap))
990       {
991         int i;
992
993         atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE);
994
995         i = atk_object_get_index_in_parent (accessible);
996         if (i >= 0)
997           if (atk_selection_is_child_selected(ATK_SELECTION (ap), i))
998             atk_state_set_add_state (state_set, ATK_STATE_SELECTED);
999       } 
1000
1001   return state_set; 
1002 }
1003
1004 static void
1005 atk_object_real_set_name (AtkObject       *object,
1006                           const gchar     *name)
1007 {
1008   g_free (object->name);
1009   object->name = g_strdup (name);
1010 }
1011
1012 static void
1013 atk_object_real_set_description (AtkObject       *object,
1014                                  const gchar     *description)
1015 {
1016   g_free (object->description);
1017   object->description = g_strdup (description);
1018 }
1019
1020 static void
1021 atk_object_real_set_parent (AtkObject       *object,
1022                             AtkObject       *parent)
1023 {
1024   if (object->accessible_parent)
1025     g_object_unref (object->accessible_parent);
1026
1027   object->accessible_parent = parent;
1028   if (object->accessible_parent)
1029     g_object_ref (object->accessible_parent);
1030 }
1031
1032 static void
1033 atk_object_real_set_role (AtkObject *object,
1034                           AtkRole   role)
1035 {
1036   object->role = role;
1037 }
1038
1039 static guint
1040 atk_object_real_connect_property_change_handler (AtkObject                *obj,
1041                                                  AtkPropertyChangeHandler *handler)
1042 {
1043   return g_signal_connect_closure_by_id (obj,
1044                                          atk_object_signals[PROPERTY_CHANGE],
1045                                          0,
1046                                          g_cclosure_new (
1047                                          G_CALLBACK (handler), NULL,
1048                                          (GClosureNotify) NULL),
1049                                          FALSE);
1050 }
1051
1052 static void
1053 atk_object_real_remove_property_change_handler (AtkObject           *obj,
1054                                           guint               handler_id)
1055 {
1056   g_signal_handler_disconnect (obj, handler_id);
1057 }
1058
1059 /**
1060  * atk_object_initialize:
1061  * @accessible: a #AtkObject
1062  * @data: a #gpointer which identifies the object for which the AtkObject was created.
1063  *
1064  * This function is called when implementing subclasses of #AtkObject.
1065  * It does initialization required for the new object. It is intended
1066  * that this function should called only in the ..._new() functions used
1067  * to create an instance of a subclass of #AtkObject
1068  **/
1069 void
1070 atk_object_initialize (AtkObject  *accessible,
1071                        gpointer   data)
1072 {
1073   AtkObjectClass *klass;
1074
1075   g_return_if_fail (ATK_IS_OBJECT (accessible));
1076
1077   klass = ATK_OBJECT_GET_CLASS (accessible);
1078   if (klass->initialize)
1079     klass->initialize (accessible, data);
1080 }
1081
1082 /*
1083  * This function is a signal handler for notify signal which gets emitted
1084  * when a property changes value.
1085  *
1086  * It constructs an AtkPropertyValues structure and emits a "property_changed"
1087  * signal which causes the user specified AtkPropertyChangeHandler
1088  * to be called.
1089  */
1090 static void
1091 atk_object_notify (GObject     *obj,
1092                    GParamSpec  *pspec)
1093 {
1094   AtkPropertyValues values = { 0, };
1095
1096   g_value_init (&values.new_value, pspec->value_type);
1097   g_object_get_property (obj, pspec->name, &values.new_value);
1098   values.property_name = pspec->name;
1099   g_signal_emit (obj, atk_object_signals[PROPERTY_CHANGE],
1100                  g_quark_from_string (pspec->name),
1101                  &values, NULL);
1102   g_value_unset (&values.new_value);
1103 }
1104
1105 /**
1106  * atk_role_get_name:
1107  * @role: The #AtkRole whose name is required
1108  *
1109  * Gets the description string describing the #AtkRole @role.
1110  *
1111  * Returns: the string describing the AtkRole
1112  */
1113 G_CONST_RETURN gchar*
1114 atk_role_get_name (AtkRole role)
1115 {
1116   GTypeClass *type_class;
1117   GEnumValue *value;
1118   gchar *name = NULL;
1119
1120   type_class = g_type_class_ref (ATK_TYPE_ROLE);
1121   g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), NULL);
1122
1123   value = g_enum_get_value (G_ENUM_CLASS (type_class), role);
1124
1125   if (value)
1126     {
1127       name = value->value_nick;
1128     }
1129   else
1130     {
1131       if (extra_roles)
1132         {
1133           gint n = role;
1134
1135           n -= ATK_ROLE_LAST_DEFINED + 1;
1136
1137           if (n < extra_roles->len)
1138             name = g_ptr_array_index (extra_roles, n);
1139         }
1140     }
1141   g_type_class_unref (type_class);
1142   return name;
1143 }
1144
1145 /**
1146  * atk_role_get_localized_name:
1147  * @role: The #AtkRole whose localized name is required
1148  *
1149  * Gets the localized description string describing the #AtkRole @role.
1150  *
1151  * Returns: the localized string describing the AtkRole
1152  **/
1153 G_CONST_RETURN gchar*
1154 atk_role_get_localized_name (AtkRole role)
1155 {
1156   G_CONST_RETURN gchar *name;
1157
1158   switch (role)
1159     {
1160       case ATK_ROLE_INVALID:
1161         name = _("invalid");
1162         break;
1163       case ATK_ROLE_ACCEL_LABEL:
1164         name = _("accel-label");
1165         break;
1166       case ATK_ROLE_ALERT:
1167         name = _("alert");
1168         break;
1169       case ATK_ROLE_ANIMATION:
1170         name = _("animation");
1171         break;
1172       case ATK_ROLE_ARROW:
1173         name = _("arrow");
1174         break;
1175       case ATK_ROLE_CALENDAR:
1176         name = _("calendar");
1177         break;
1178       case ATK_ROLE_CANVAS:
1179         name = _("canvas");
1180         break;
1181       case ATK_ROLE_CHECK_BOX:
1182         name = _("check-box");
1183         break;
1184       case ATK_ROLE_CHECK_MENU_ITEM:
1185         name = _("check-menu-item");
1186         break;
1187       case ATK_ROLE_COLOR_CHOOSER:
1188         name = _("color-chooser");
1189         break;
1190       case ATK_ROLE_COLUMN_HEADER:
1191         name = _("column-header");
1192         break;
1193       case ATK_ROLE_COMBO_BOX:
1194         name = _("combo-box");
1195         break;
1196       case ATK_ROLE_DATE_EDITOR:
1197         name = _("date-editor");
1198         break;
1199       case ATK_ROLE_DESKTOP_ICON:
1200         name = _("desktop-icon");
1201         break;
1202       case ATK_ROLE_DESKTOP_FRAME:
1203         name = _("desktop-frame");
1204         break;
1205       case ATK_ROLE_DIAL:
1206         name = _("dial");
1207         break;
1208       case ATK_ROLE_DIALOG:
1209         name = _("dialog");
1210         break;
1211       case ATK_ROLE_DIRECTORY_PANE:
1212         name = _("directory-pane");
1213         break;
1214       case ATK_ROLE_DRAWING_AREA:
1215         name = _("drawing-area");
1216         break;
1217       case ATK_ROLE_FILE_CHOOSER:
1218         name = _("file-chooser");
1219         break;
1220       case ATK_ROLE_FILLER:
1221         name = _("filler");
1222         break;
1223       case ATK_ROLE_FONT_CHOOSER:
1224         name = _("font-chooser");
1225         break;
1226       case ATK_ROLE_FRAME:
1227         name = _("frame");
1228         break;
1229       case ATK_ROLE_GLASS_PANE:
1230         name = _("glass-pane");
1231         break;
1232       case ATK_ROLE_HTML_CONTAINER:
1233         name = _("html-container");
1234         break;
1235       case ATK_ROLE_ICON:
1236         name = _("icon");
1237         break;
1238       case ATK_ROLE_IMAGE:
1239         name = _("image");
1240         break;
1241       case ATK_ROLE_INTERNAL_FRAME:
1242         name = _("internal-frame");
1243         break;
1244       case ATK_ROLE_LABEL:
1245         name = _("label");
1246         break;
1247       case ATK_ROLE_LAYERED_PANE:
1248         name = _("layered-pane");
1249         break;
1250       case ATK_ROLE_LIST:
1251         name = _("list");
1252         break;
1253       case ATK_ROLE_LIST_ITEM:
1254         name = _("list-item");
1255         break;
1256       case ATK_ROLE_MENU:
1257         name = _("menu");
1258         break;
1259       case ATK_ROLE_MENU_BAR:
1260         name = _("menu-bar");
1261         break;
1262       case ATK_ROLE_MENU_ITEM:
1263         name = _("menu-item");
1264         break;
1265       case ATK_ROLE_OPTION_PANE:
1266         name = _("option-pane");
1267         break;
1268       case ATK_ROLE_PAGE_TAB:
1269         name = _("page-tab");
1270         break;
1271       case ATK_ROLE_PAGE_TAB_LIST:
1272         name = _("page-tab-list");
1273         break;
1274       case ATK_ROLE_PANEL:
1275         name = _("panel");
1276         break;
1277       case ATK_ROLE_PASSWORD_TEXT:
1278         name = _("password-text");
1279         break;
1280       case ATK_ROLE_POPUP_MENU:
1281         name = _("popup-menu");
1282         break;
1283       case ATK_ROLE_PROGRESS_BAR:
1284         name = _("progress-bar");
1285         break;
1286       case ATK_ROLE_PUSH_BUTTON:
1287         name = _("push-button");
1288         break;
1289       case ATK_ROLE_RADIO_BUTTON:
1290         name = _("radio-button");
1291         break;
1292       case ATK_ROLE_RADIO_MENU_ITEM:
1293         name = _("radio-menu-item");
1294         break;
1295       case ATK_ROLE_ROOT_PANE:
1296         name = _("root-pane");
1297         break;
1298       case ATK_ROLE_ROW_HEADER:
1299         name = _("row-header");
1300         break;
1301       case ATK_ROLE_SCROLL_BAR:
1302         name = _("scroll-bar");
1303         break;
1304       case ATK_ROLE_SCROLL_PANE:
1305         name = _("scroll-pane");
1306         break;
1307       case ATK_ROLE_SEPARATOR:
1308         name = _("separator");
1309         break;
1310       case ATK_ROLE_SLIDER:
1311         name = _("slider");
1312         break;
1313       case ATK_ROLE_SPLIT_PANE:
1314         name = _("split-pane");
1315         break;
1316       case ATK_ROLE_SPIN_BUTTON:
1317         name = _("spin-button");
1318         break;
1319       case ATK_ROLE_STATUSBAR:
1320         name = _("statusbar");
1321         break;
1322       case ATK_ROLE_TABLE:
1323         name = _("table");
1324         break;
1325       case ATK_ROLE_TABLE_CELL:
1326         name = _("table-cell");
1327         break;
1328       case ATK_ROLE_TABLE_COLUMN_HEADER:
1329         name = _("table-column-header");
1330         break;
1331       case ATK_ROLE_TABLE_ROW_HEADER:
1332         name = _("table-row-header");
1333         break;
1334       case ATK_ROLE_TEAR_OFF_MENU_ITEM:
1335         name = _("tear-off-menu-item");
1336         break;
1337       case ATK_ROLE_TERMINAL:
1338         name = _("terminal");
1339         break;
1340       case ATK_ROLE_TEXT:
1341         name = _("text");
1342         break;
1343       case ATK_ROLE_TOGGLE_BUTTON:
1344         name = _("toggle-button");
1345         break;
1346       case ATK_ROLE_TOOL_BAR:
1347         name = _("tool-bar");
1348         break;
1349       case ATK_ROLE_TOOL_TIP:
1350         name = _("tool-tip");
1351         break;
1352       case ATK_ROLE_TREE:
1353         name = _("tree");
1354         break;
1355       case ATK_ROLE_TREE_TABLE:
1356         name = _("tree-table");
1357         break;
1358       case ATK_ROLE_UNKNOWN:
1359         name = _("unknown");
1360         break;
1361       case ATK_ROLE_VIEWPORT:
1362         name = _("viewport");
1363         break;
1364       case ATK_ROLE_WINDOW:
1365         name = _("window");
1366         break;
1367       case ATK_ROLE_HEADER:
1368         name = _("header");
1369         break;
1370       case ATK_ROLE_FOOTER:
1371         name = _("footer");
1372         break;
1373       case ATK_ROLE_PARAGRAPH:
1374         name = _("paragraph");
1375         break;
1376       case ATK_ROLE_RULER:
1377         name = _("ruler");
1378         break;
1379       default:
1380         name = atk_role_get_name (role);
1381         break;
1382     }
1383   return name;
1384 }
1385
1386 /**
1387  * atk_role_for_name:
1388  * @name: a string which is the (non-localized) name of an ATK role.
1389  *
1390  * Get the #AtkRole type corresponding to a rolew name.
1391  *
1392  * Returns: the #AtkRole enumerated type corresponding to the specified
1393 name,
1394  *          or #ATK_ROLE_INVALID if no matching role is found.
1395  **/
1396 AtkRole
1397 atk_role_for_name (const gchar *name)
1398 {
1399   GTypeClass *type_class;
1400   GEnumValue *value;
1401   AtkRole role = ATK_ROLE_INVALID;
1402
1403   g_return_val_if_fail (name, ATK_ROLE_INVALID);
1404
1405   type_class = g_type_class_ref (ATK_TYPE_ROLE);
1406   g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), ATK_ROLE_INVALID);
1407
1408   value = g_enum_get_value_by_nick (G_ENUM_CLASS (type_class), name);
1409
1410   if (value)
1411     {
1412       role = value->value;
1413     }
1414   else
1415     {
1416      gint i;
1417
1418       if (extra_roles)
1419         {
1420           for (i = 0; i < extra_roles->len; i++)
1421             {
1422               gchar *extra_role = (gchar *)g_ptr_array_index (extra_roles, i);
1423
1424               g_return_val_if_fail (extra_role, ATK_ROLE_INVALID);
1425
1426               if (strcmp (name, extra_role) == 0)
1427                 {
1428                   role = i + 1 + ATK_ROLE_LAST_DEFINED;
1429                   break;
1430                 }
1431             }
1432         }
1433     }
1434   g_type_class_unref (type_class);
1435   
1436   return role;
1437 }
1438
1439 /**
1440  * atk_object_add_relationship:
1441  * @object: The #AtkObject to which an AtkRelation is to be added. 
1442  * @relationship: The #AtkRelationType of the relation
1443  * @target: The #AtkObject which is to be the target of the relation.
1444  *
1445  * Adds a relationship of the specified type with the specified target.
1446  *
1447  * Returns TRUE if the relationship is added.
1448  **/
1449 gboolean
1450 atk_object_add_relationship (AtkObject       *object,
1451                              AtkRelationType relationship,
1452                              AtkObject       *target)
1453 {
1454   AtkObject *array[1];
1455   AtkRelation *relation;
1456
1457   g_return_val_if_fail (ATK_IS_OBJECT (object), FALSE);
1458   g_return_val_if_fail (ATK_IS_OBJECT (target), FALSE);
1459
1460   array[0] = target;
1461   relation = atk_relation_new (array, 1, relationship);
1462   atk_relation_set_add (object->relation_set, relation);
1463   g_object_unref (relation);
1464
1465   return TRUE;
1466 }
1467
1468 /**
1469  * atk_object_remove_relationship:
1470  * @object: The #AtkObject from which an AtkRelation is to be removed. 
1471  * @relationship: The #AtkRelationType of the relation
1472  * @target: The #AtkObject which is the target of the relation to be removed.
1473  *
1474  * Removes a relationship of the specified type with the specified target.
1475  *
1476  * Returns TRUE if the relationship is removed.
1477  **/
1478 gboolean
1479 atk_object_remove_relationship (AtkObject       *object,
1480                                 AtkRelationType relationship,
1481                                 AtkObject       *target)
1482 {
1483   gint n_relations, i;
1484   gboolean ret = FALSE;
1485   AtkRelation *relation;
1486
1487   g_return_val_if_fail (ATK_IS_OBJECT (object), FALSE);
1488   g_return_val_if_fail (ATK_IS_OBJECT (target), FALSE);
1489
1490   n_relations = atk_relation_set_get_n_relations (object->relation_set);
1491   for (i = 0; i < n_relations; i++)
1492     {
1493       relation = atk_relation_set_get_relation (object->relation_set, i);
1494       if (atk_relation_get_relation_type (relation) == relationship)
1495         {
1496           GPtrArray *array;
1497           gint j;
1498
1499           array = atk_relation_get_target (relation);
1500         
1501           if (g_ptr_array_index (array, 0) == target)
1502             {
1503               atk_relation_set_remove (object->relation_set, relation); 
1504               ret = TRUE;
1505               break;
1506             }
1507         }
1508     }
1509
1510   return ret;
1511 }