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.
21 #include <glib-object.h>
26 * @Short_description: An object used to describe a relation between a
27 * object and one or more other objects.
30 * An AtkRelation describes a relation between an object and one or
31 * more other objects. The actual relations that an object has with
32 * other objects are defined as an AtkRelationSet, which is a set of
43 static GPtrArray *extra_names = NULL;
45 static gpointer parent_class = NULL;
47 static void atk_relation_class_init (AtkRelationClass *klass);
48 static void atk_relation_finalize (GObject *object);
49 static void atk_relation_set_property (GObject *object,
53 static void atk_relation_get_property (GObject *object,
58 static GPtrArray* atk_relation_get_ptr_array_from_value_array (GValueArray *array);
59 static GValueArray* atk_relation_get_value_array_from_ptr_array (GPtrArray *array);
62 atk_relation_get_type (void)
64 static GType type = 0;
68 static const GTypeInfo typeInfo =
70 sizeof (AtkRelationClass),
72 (GBaseFinalizeFunc) NULL,
73 (GClassInitFunc) atk_relation_class_init,
74 (GClassFinalizeFunc) NULL,
78 (GInstanceInitFunc) NULL,
80 type = g_type_register_static (G_TYPE_OBJECT, "AtkRelation", &typeInfo, 0) ;
86 atk_relation_class_init (AtkRelationClass *klass)
88 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
90 parent_class = g_type_class_peek_parent (klass);
92 gobject_class->finalize = atk_relation_finalize;
93 gobject_class->set_property = atk_relation_set_property;
94 gobject_class->get_property = atk_relation_get_property;
96 g_object_class_install_property (gobject_class,
98 g_param_spec_enum ("relation_type",
100 "The type of the relation",
101 ATK_TYPE_RELATION_TYPE,
104 g_object_class_install_property (gobject_class,
106 g_param_spec_value_array ("target",
108 "An array of the targets for the relation",
115 * atk_relation_type_register:
116 * @name: a name string
118 * Associate @name with a new #AtkRelationType
120 * Returns: an #AtkRelationType associated with @name
123 atk_relation_type_register (const gchar *name)
125 g_return_val_if_fail (name, ATK_RELATION_NULL);
128 extra_names = g_ptr_array_new ();
130 g_ptr_array_add (extra_names, g_strdup (name));
131 return extra_names->len + ATK_RELATION_LAST_DEFINED;
135 * atk_relation_type_get_name:
136 * @type: The #AtkRelationType whose name is required
138 * Gets the description string describing the #AtkRelationType @type.
140 * Returns: the string describing the AtkRelationType
143 atk_relation_type_get_name (AtkRelationType type)
145 GTypeClass *type_class;
147 const gchar *name = NULL;
149 type_class = g_type_class_ref (ATK_TYPE_RELATION_TYPE);
150 g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), NULL);
152 value = g_enum_get_value (G_ENUM_CLASS (type_class), type);
156 name = value->value_nick;
164 n -= ATK_RELATION_LAST_DEFINED + 1;
166 if (n < extra_names->len)
167 name = g_ptr_array_index (extra_names, n);
170 g_type_class_unref (type_class);
175 * atk_relation_type_for_name:
176 * @name: a string which is the (non-localized) name of an ATK relation type.
178 * Get the #AtkRelationType type corresponding to a relation name.
180 * Returns: the #AtkRelationType enumerated type corresponding to the specified name,
181 * or #ATK_RELATION_NULL if no matching relation type is found.
184 atk_relation_type_for_name (const gchar *name)
186 GTypeClass *type_class;
188 AtkRelationType type = ATK_RELATION_NULL;
190 g_return_val_if_fail (name, ATK_RELATION_NULL);
192 type_class = g_type_class_ref (ATK_TYPE_RELATION_TYPE);
193 g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), ATK_RELATION_NULL);
195 value = g_enum_get_value_by_nick (G_ENUM_CLASS (type_class), name);
207 for (i = 0; i < extra_names->len; i++)
209 gchar *extra_name = (gchar *)g_ptr_array_index (extra_names, i);
211 g_return_val_if_fail (extra_name, ATK_RELATION_NULL);
213 if (strcmp (name, extra_name) == 0)
215 type = i + 1 + ATK_RELATION_LAST_DEFINED;
221 g_type_class_unref (type_class);
229 * @targets: (array length=n_targets): an array of pointers to
231 * @n_targets: number of #AtkObjects pointed to by @targets
232 * @relationship: an #AtkRelationType with which to create the new
235 * Create a new relation for the specified key and the specified list
236 * of targets. See also atk_object_add_relationship().
238 * Returns: a pointer to a new #AtkRelation
241 atk_relation_new (AtkObject **targets,
243 AtkRelationType relationship)
245 AtkRelation *relation;
250 g_return_val_if_fail (targets != NULL, NULL);
252 array = g_value_array_new (n_targets);
253 for (i = 0; i < n_targets; i++)
255 value = g_new0 (GValue, 1);
256 g_value_init (value, ATK_TYPE_OBJECT);
257 g_value_set_object (value, targets[i]);
258 array = g_value_array_append (array, value);
259 g_value_unset (value);
263 relation = g_object_new (ATK_TYPE_RELATION,
264 "relation_type", relationship,
268 g_value_array_free (array);
274 * atk_relation_get_relation_type:
275 * @relation: an #AtkRelation
277 * Gets the type of @relation
279 * Returns: the type of @relation
282 atk_relation_get_relation_type (AtkRelation *relation)
284 g_return_val_if_fail (ATK_IS_RELATION (relation), 0);
286 return relation->relationship;
290 * atk_relation_get_target:
291 * @relation: an #AtkRelation
293 * Gets the target list of @relation
295 * Returns: (transfer none) (element-type Atk.Object): the target list of @relation
298 atk_relation_get_target (AtkRelation *relation)
300 g_return_val_if_fail (ATK_IS_RELATION (relation), NULL);
302 return relation->target;
306 delete_object_while_in_relation (gpointer callback_data,
307 GObject *where_the_object_was)
311 g_assert (callback_data != NULL);
313 array = callback_data;
314 g_ptr_array_remove (array, where_the_object_was);
318 * atk_relation_add_target:
319 * @relation: an #AtkRelation
320 * @target: an #AtkObject
322 * Adds the specified AtkObject to the target for the relation, if it is
323 * not already present. See also atk_object_add_relationship().
329 atk_relation_add_target (AtkRelation *relation,
334 g_return_if_fail (ATK_IS_RELATION (relation));
335 g_return_if_fail (ATK_IS_OBJECT (target));
337 /* first check if target occurs in array ... */
338 for (i = 0; i < relation->target->len; i++)
339 if (g_ptr_array_index(relation->target, i) == target)
342 g_ptr_array_add (relation->target, target);
343 g_object_weak_ref (G_OBJECT (target), (GWeakNotify) delete_object_while_in_relation, relation->target);
347 * atk_relation_remove_target:
348 * @relation: an #AtkRelation
349 * @target: an #AtkObject
351 * Remove the specified AtkObject from the target for the relation.
353 * Returns: TRUE if the removal is successful.
357 atk_relation_remove_target (AtkRelation *relation,
360 gboolean ret = FALSE;
363 array = atk_relation_get_target (relation);
365 if (array && g_ptr_array_remove (array, target))
367 g_object_weak_unref (G_OBJECT (target),
368 (GWeakNotify) delete_object_while_in_relation,
376 atk_relation_finalize (GObject *object)
378 AtkRelation *relation;
380 g_return_if_fail (ATK_IS_RELATION (object));
382 relation = ATK_RELATION (object);
384 if (relation->target)
388 for (i = 0; i < relation->target->len; i++)
390 g_object_weak_unref (G_OBJECT (g_ptr_array_index (relation->target, i)),
391 (GWeakNotify) delete_object_while_in_relation,
394 g_ptr_array_free (relation->target, TRUE);
397 G_OBJECT_CLASS (parent_class)->finalize (object);
401 atk_relation_set_property (GObject *object,
406 AtkRelation *relation;
409 relation = ATK_RELATION (object);
413 case PROP_RELATION_TYPE:
414 relation->relationship = g_value_get_enum (value);
417 if (relation->target)
421 for (i = 0; i < relation->target->len; i++)
423 g_object_weak_unref (G_OBJECT (g_ptr_array_index (relation->target, i)),
424 (GWeakNotify) delete_object_while_in_relation,
427 g_ptr_array_free (relation->target, TRUE);
429 boxed = g_value_get_boxed (value);
430 relation->target = atk_relation_get_ptr_array_from_value_array ( (GValueArray *) boxed);
438 atk_relation_get_property (GObject *object,
443 AtkRelation *relation;
446 relation = ATK_RELATION (object);
450 case PROP_RELATION_TYPE:
451 g_value_set_enum (value, relation->relationship);
454 array = atk_relation_get_value_array_from_ptr_array (relation->target);
455 g_value_set_boxed (value, array);
458 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
464 atk_relation_get_ptr_array_from_value_array (GValueArray *array)
467 GPtrArray *return_array;
471 return_array = g_ptr_array_sized_new (array->n_values);
472 for (i = 0; i < array->n_values; i++)
474 value = g_value_array_get_nth (array, i);
475 obj = g_value_get_object (value);
476 g_ptr_array_add (return_array, obj);
477 g_object_weak_ref (obj, (GWeakNotify) delete_object_while_in_relation, return_array);
484 atk_relation_get_value_array_from_ptr_array (GPtrArray *array)
487 GValueArray *return_array;
490 return_array = g_value_array_new (array->len);
491 for (i = 0; i < array->len; i++)
493 value = g_new0 (GValue, 1);
494 g_value_init (value, ATK_TYPE_OBJECT);
495 g_value_set_object (value, g_ptr_array_index (array, i));
496 return_array = g_value_array_append (return_array, value);