Release 2.15.1
[atk.git] / atk / atkrelation.c
blob6dcb1c477e55bf1a104bd8cd5bdaee3f8ee51001
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 "config.h"
22 #include <string.h>
23 #include <glib-object.h>
24 #include "atk.h"
26 /**
27 * SECTION:atkrelation
28 * @Short_description: An object used to describe a relation between a
29 * object and one or more other objects.
30 * @Title:AtkRelation
32 * An AtkRelation describes a relation between an object and one or
33 * more other objects. The actual relations that an object has with
34 * other objects are defined as an AtkRelationSet, which is a set of
35 * AtkRelations.
37 enum {
38 PROP_0,
40 PROP_RELATION_TYPE,
41 PROP_TARGET,
42 PROP_LAST
45 static GPtrArray *extra_names = NULL;
47 static gpointer parent_class = NULL;
49 static void atk_relation_class_init (AtkRelationClass *klass);
50 static void atk_relation_finalize (GObject *object);
51 static void atk_relation_set_property (GObject *object,
52 guint prop_id,
53 const GValue *value,
54 GParamSpec *pspec);
55 static void atk_relation_get_property (GObject *object,
56 guint prop_id,
57 GValue *value,
58 GParamSpec *pspec);
60 static GPtrArray* atk_relation_get_ptr_array_from_value_array (GValueArray *array);
61 static GValueArray* atk_relation_get_value_array_from_ptr_array (GPtrArray *array);
63 GType
64 atk_relation_get_type (void)
66 static GType type = 0;
68 if (!type)
70 static const GTypeInfo typeInfo =
72 sizeof (AtkRelationClass),
73 (GBaseInitFunc) NULL,
74 (GBaseFinalizeFunc) NULL,
75 (GClassInitFunc) atk_relation_class_init,
76 (GClassFinalizeFunc) NULL,
77 NULL,
78 sizeof (AtkRelation),
80 (GInstanceInitFunc) NULL,
81 } ;
82 type = g_type_register_static (G_TYPE_OBJECT, "AtkRelation", &typeInfo, 0) ;
84 return type;
87 static void
88 atk_relation_class_init (AtkRelationClass *klass)
90 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
92 parent_class = g_type_class_peek_parent (klass);
94 gobject_class->finalize = atk_relation_finalize;
95 gobject_class->set_property = atk_relation_set_property;
96 gobject_class->get_property = atk_relation_get_property;
98 g_object_class_install_property (gobject_class,
99 PROP_RELATION_TYPE,
100 g_param_spec_enum ("relation_type",
101 "Relation Type",
102 "The type of the relation",
103 ATK_TYPE_RELATION_TYPE,
104 ATK_RELATION_NULL,
105 G_PARAM_READWRITE));
106 g_object_class_install_property (gobject_class,
107 PROP_TARGET,
108 g_param_spec_value_array ("target",
109 "Target",
110 "An array of the targets for the relation",
111 NULL,
113 G_PARAM_READWRITE));
117 * atk_relation_type_register:
118 * @name: a name string
120 * Associate @name with a new #AtkRelationType
122 * Returns: an #AtkRelationType associated with @name
124 AtkRelationType
125 atk_relation_type_register (const gchar *name)
127 g_return_val_if_fail (name, ATK_RELATION_NULL);
129 if (!extra_names)
130 extra_names = g_ptr_array_new ();
132 g_ptr_array_add (extra_names, g_strdup (name));
133 return extra_names->len + ATK_RELATION_LAST_DEFINED;
137 * atk_relation_type_get_name:
138 * @type: The #AtkRelationType whose name is required
140 * Gets the description string describing the #AtkRelationType @type.
142 * Returns: the string describing the AtkRelationType
144 const gchar*
145 atk_relation_type_get_name (AtkRelationType type)
147 GTypeClass *type_class;
148 GEnumValue *value;
149 const gchar *name = NULL;
151 type_class = g_type_class_ref (ATK_TYPE_RELATION_TYPE);
152 g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), NULL);
154 value = g_enum_get_value (G_ENUM_CLASS (type_class), type);
156 if (value)
158 name = value->value_nick;
160 else
162 if (extra_names)
164 gint n = type;
166 n -= ATK_RELATION_LAST_DEFINED + 1;
168 if (n < extra_names->len)
169 name = g_ptr_array_index (extra_names, n);
172 g_type_class_unref (type_class);
173 return name;
177 * atk_relation_type_for_name:
178 * @name: a string which is the (non-localized) name of an ATK relation type.
180 * Get the #AtkRelationType type corresponding to a relation name.
182 * Returns: the #AtkRelationType enumerated type corresponding to the specified name,
183 * or #ATK_RELATION_NULL if no matching relation type is found.
185 AtkRelationType
186 atk_relation_type_for_name (const gchar *name)
188 GTypeClass *type_class;
189 GEnumValue *value;
190 AtkRelationType type = ATK_RELATION_NULL;
192 g_return_val_if_fail (name, ATK_RELATION_NULL);
194 type_class = g_type_class_ref (ATK_TYPE_RELATION_TYPE);
195 g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), ATK_RELATION_NULL);
197 value = g_enum_get_value_by_nick (G_ENUM_CLASS (type_class), name);
199 if (value)
201 type = value->value;
203 else
205 gint i;
207 if (extra_names)
209 for (i = 0; i < extra_names->len; i++)
211 gchar *extra_name = (gchar *)g_ptr_array_index (extra_names, i);
213 g_return_val_if_fail (extra_name, ATK_RELATION_NULL);
215 if (strcmp (name, extra_name) == 0)
217 type = i + 1 + ATK_RELATION_LAST_DEFINED;
218 break;
223 g_type_class_unref (type_class);
225 return type;
230 * atk_relation_new:
231 * @targets: (array length=n_targets): an array of pointers to
232 * #AtkObjects
233 * @n_targets: number of #AtkObjects pointed to by @targets
234 * @relationship: an #AtkRelationType with which to create the new
235 * #AtkRelation
237 * Create a new relation for the specified key and the specified list
238 * of targets. See also atk_object_add_relationship().
240 * Returns: a pointer to a new #AtkRelation
242 AtkRelation*
243 atk_relation_new (AtkObject **targets,
244 gint n_targets,
245 AtkRelationType relationship)
247 AtkRelation *relation;
248 int i;
249 GValueArray *array;
250 GValue *value;
252 g_return_val_if_fail (targets != NULL, NULL);
254 array = g_value_array_new (n_targets);
255 for (i = 0; i < n_targets; i++)
257 value = g_new0 (GValue, 1);
258 g_value_init (value, ATK_TYPE_OBJECT);
259 g_value_set_object (value, targets[i]);
260 array = g_value_array_append (array, value);
261 g_value_unset (value);
262 g_free (value);
265 relation = g_object_new (ATK_TYPE_RELATION,
266 "relation_type", relationship,
267 "target", array,
268 NULL);
270 g_value_array_free (array);
272 return relation;
276 * atk_relation_get_relation_type:
277 * @relation: an #AtkRelation
279 * Gets the type of @relation
281 * Returns: the type of @relation
283 AtkRelationType
284 atk_relation_get_relation_type (AtkRelation *relation)
286 g_return_val_if_fail (ATK_IS_RELATION (relation), 0);
288 return relation->relationship;
292 * atk_relation_get_target:
293 * @relation: an #AtkRelation
295 * Gets the target list of @relation
297 * Returns: (transfer none) (element-type Atk.Object): the target list of @relation
299 GPtrArray*
300 atk_relation_get_target (AtkRelation *relation)
302 g_return_val_if_fail (ATK_IS_RELATION (relation), NULL);
304 return relation->target;
307 static void
308 delete_object_while_in_relation (gpointer callback_data,
309 GObject *where_the_object_was)
311 GPtrArray *array;
313 g_assert (callback_data != NULL);
315 array = callback_data;
316 g_ptr_array_remove (array, where_the_object_was);
320 * atk_relation_add_target:
321 * @relation: an #AtkRelation
322 * @target: an #AtkObject
324 * Adds the specified AtkObject to the target for the relation, if it is
325 * not already present. See also atk_object_add_relationship().
328 * Since: 1.9
330 void
331 atk_relation_add_target (AtkRelation *relation,
332 AtkObject *target)
334 guint i;
336 g_return_if_fail (ATK_IS_RELATION (relation));
337 g_return_if_fail (ATK_IS_OBJECT (target));
339 /* first check if target occurs in array ... */
340 for (i = 0; i < relation->target->len; i++)
341 if (g_ptr_array_index(relation->target, i) == target)
342 return;
344 g_ptr_array_add (relation->target, target);
345 g_object_weak_ref (G_OBJECT (target), (GWeakNotify) delete_object_while_in_relation, relation->target);
349 * atk_relation_remove_target:
350 * @relation: an #AtkRelation
351 * @target: an #AtkObject
353 * Remove the specified AtkObject from the target for the relation.
355 * Returns: TRUE if the removal is successful.
358 gboolean
359 atk_relation_remove_target (AtkRelation *relation,
360 AtkObject *target)
362 gboolean ret = FALSE;
363 GPtrArray *array;
365 array = atk_relation_get_target (relation);
367 if (array && g_ptr_array_remove (array, target))
369 g_object_weak_unref (G_OBJECT (target),
370 (GWeakNotify) delete_object_while_in_relation,
371 relation->target);
372 ret = TRUE;
374 return ret;
377 static void
378 atk_relation_finalize (GObject *object)
380 AtkRelation *relation;
382 g_return_if_fail (ATK_IS_RELATION (object));
384 relation = ATK_RELATION (object);
386 if (relation->target)
388 gint i;
390 for (i = 0; i < relation->target->len; i++)
392 g_object_weak_unref (G_OBJECT (g_ptr_array_index (relation->target, i)),
393 (GWeakNotify) delete_object_while_in_relation,
394 relation->target);
396 g_ptr_array_free (relation->target, TRUE);
399 G_OBJECT_CLASS (parent_class)->finalize (object);
402 static void
403 atk_relation_set_property (GObject *object,
404 guint prop_id,
405 const GValue *value,
406 GParamSpec *pspec)
408 AtkRelation *relation;
409 gpointer boxed;
411 relation = ATK_RELATION (object);
413 switch (prop_id)
415 case PROP_RELATION_TYPE:
416 relation->relationship = g_value_get_enum (value);
417 break;
418 case PROP_TARGET:
419 if (relation->target)
421 gint i;
423 for (i = 0; i < relation->target->len; i++)
425 g_object_weak_unref (G_OBJECT (g_ptr_array_index (relation->target, i)),
426 (GWeakNotify) delete_object_while_in_relation,
427 relation->target);
429 g_ptr_array_free (relation->target, TRUE);
431 boxed = g_value_get_boxed (value);
432 relation->target = atk_relation_get_ptr_array_from_value_array ( (GValueArray *) boxed);
433 break;
434 default:
435 break;
439 static void
440 atk_relation_get_property (GObject *object,
441 guint prop_id,
442 GValue *value,
443 GParamSpec *pspec)
445 AtkRelation *relation;
446 GValueArray *array;
448 relation = ATK_RELATION (object);
450 switch (prop_id)
452 case PROP_RELATION_TYPE:
453 g_value_set_enum (value, relation->relationship);
454 break;
455 case PROP_TARGET:
456 array = atk_relation_get_value_array_from_ptr_array (relation->target);
457 g_value_set_boxed (value, array);
458 break;
459 default:
460 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
461 break;
465 static GPtrArray*
466 atk_relation_get_ptr_array_from_value_array (GValueArray *array)
468 gint i;
469 GPtrArray *return_array;
470 GValue *value;
471 GObject *obj;
473 return_array = g_ptr_array_sized_new (array->n_values);
474 for (i = 0; i < array->n_values; i++)
476 value = g_value_array_get_nth (array, i);
477 obj = g_value_get_object (value);
478 g_ptr_array_add (return_array, obj);
479 g_object_weak_ref (obj, (GWeakNotify) delete_object_while_in_relation, return_array);
482 return return_array;
485 static GValueArray*
486 atk_relation_get_value_array_from_ptr_array (GPtrArray *array)
488 int i;
489 GValueArray *return_array;
490 GValue *value;
492 return_array = g_value_array_new (array->len);
493 for (i = 0; i < array->len; i++)
495 value = g_new0 (GValue, 1);
496 g_value_init (value, ATK_TYPE_OBJECT);
497 g_value_set_object (value, g_ptr_array_index (array, i));
498 return_array = g_value_array_append (return_array, value);
500 return return_array;