/* dia-canvas-groupable.c * Copyright (C) 2003 Arjan Molenaar * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "dia-canvas-groupable.h" #include "dia-canvas-i18n.h" #include "diamarshal.h" #include "../config.h" static void dia_canvas_groupable_base_init (gpointer klass); GType dia_canvas_groupable_get_type (void) { static GType groupable_type = 0; if (!groupable_type) { static const GTypeInfo groupable_info = { sizeof (DiaCanvasGroupableIface), /* class_size */ dia_canvas_groupable_base_init, /* base_init */ NULL, /* base_finalize */ NULL, NULL, /* class_finalize */ NULL, /* class_data */ 0, 0, /* n_preallocs */ NULL }; groupable_type = g_type_register_static (G_TYPE_INTERFACE, "DiaCanvasGroupable", &groupable_info, 0); g_type_interface_add_prerequisite (groupable_type, DIA_TYPE_CANVAS_ITEM); } return groupable_type; } static void dia_canvas_groupable_base_init (gpointer iface) { static gboolean initialized = FALSE; if (!initialized) { g_signal_new ("add", G_TYPE_FROM_INTERFACE (iface), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (DiaCanvasGroupableIface, add), NULL, NULL, dia_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); g_signal_new ("remove", G_TYPE_FROM_INTERFACE (iface), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (DiaCanvasGroupableIface, remove), NULL, NULL, dia_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); initialized = TRUE; } } /** * dia_canvas_groupable_add: * @group: * @item: * * Append an item to the groupable object. This is done by emiting the 'add' * signal. The @group should add the item (or not) and return %TRUE or %FALSE. * The group should not worry about any attributes that need to be set on the * @item, since this method takes care of that. * * This function also creates a weak reference from the item to its parent and * from the item to the canvas. If one of them is destroyed, their reference * is set to %NULL automatically. * * If you, in your callback function, could not add the @item, stop * signal emission with g_signal_stop_emission() or * g_signal_stop_emission_by_name(). **/ void dia_canvas_groupable_add (DiaCanvasGroupable *group, DiaCanvasItem *item) { g_return_if_fail (DIA_IS_CANVAS_GROUPABLE (group)); g_return_if_fail (DIA_IS_CANVAS_ITEM (item)); g_return_if_fail (item->parent == NULL); g_return_if_fail (item->parent != DIA_CANVAS_ITEM (group)); g_signal_emit_by_name (group, "add", item); } /** * dia_canvas_groupable_remove: * @group: * @item: * * Remove @item from the groupable object. This is done by emiting the 'remove' * signal. If the signal returns with %TRUE, the @item -> group relationship * is removed. The @group should only care about removing it's reference to the * @item. * * If you, in your callback function, could not remove the @item, stop * signal emission with g_signal_stop_emission() or * g_signal_stop_emission_by_name(). **/ void dia_canvas_groupable_remove (DiaCanvasGroupable *group, DiaCanvasItem *item) { g_return_if_fail (DIA_IS_CANVAS_ITEM (group)); g_return_if_fail (DIA_IS_CANVAS_ITEM (item)); g_return_if_fail (item->parent == DIA_CANVAS_ITEM (group)); g_object_ref (item); g_signal_emit_by_name (group, "remove", item); g_object_unref (item); } /** * dia_canvas_groupable_get_iter: * @group: * @iter: iterator, must already exist in memory. * * Get an iterator for the groupable object. This works the same as the * text iterator and the tree iterator in GTK+. You can get the actual item by * calling dia_canvas_groupable_value(). The iterator can be set to the next * item with dia_canvas_groupable_next(). * * Return value: FALSE if no iterator is set, TRUE otherwise. **/ gboolean dia_canvas_groupable_get_iter (DiaCanvasGroupable *group, DiaCanvasIter *iter) { gboolean retval; g_return_val_if_fail (DIA_IS_CANVAS_GROUPABLE (group), FALSE); g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (DIA_CANVAS_GROUPABLE_GET_IFACE (group)->get_iter != NULL, FALSE); dia_canvas_iter_init (iter); retval = (* DIA_CANVAS_GROUPABLE_GET_IFACE (group)->get_iter) (group, iter); if (!retval) dia_canvas_iter_destroy (iter); return retval; } /** * dia_canvas_groupable_next: * @group: * @iter: * * Make the iterator point to the next item. If no more items are left * (FALSE is returned) the iterator is automatically destroyed. * If you quit iterating before the last item is requested, make sure you * call dia_canvas_iter_destroy(). * * Return value: TRUE if the iterator points to a valid object, FALSE otherwise. **/ gboolean dia_canvas_groupable_next (DiaCanvasGroupable *group, DiaCanvasIter *iter) { gboolean retval; g_return_val_if_fail (DIA_IS_CANVAS_GROUPABLE (group), FALSE); g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (DIA_CANVAS_GROUPABLE_GET_IFACE (group)->next != NULL, FALSE); retval = (* DIA_CANVAS_GROUPABLE_GET_IFACE (group)->next) (group, iter); if (!retval) dia_canvas_iter_destroy (iter); return retval; } /** * dia_canvas_groupable_value: * @group: * @iter: * * Retrieve the value pointer to by the iterator. * * Return value: The #DiaCanvasItem pointed to by the iterator. **/ DiaCanvasItem* dia_canvas_groupable_value (DiaCanvasGroupable *group, DiaCanvasIter *iter) { DiaCanvasItem *value = NULL; g_return_val_if_fail (DIA_IS_CANVAS_GROUPABLE (group), NULL); g_return_val_if_fail (iter != NULL, NULL); g_return_val_if_fail (DIA_CANVAS_GROUPABLE_GET_IFACE (group)->value != NULL, NULL); value = (* DIA_CANVAS_GROUPABLE_GET_IFACE (group)->value) (group, iter); g_assert (value == NULL || DIA_IS_CANVAS_ITEM (value)); return value; } /** * dia_canvas_groupable_length: * @group: * * Get the amount of items the groupable object holds. * * Return value: number of child items, -1 on error. **/ gint dia_canvas_groupable_length (DiaCanvasGroupable *group) { DiaCanvasIter iter; gint count = 0; g_return_val_if_fail (DIA_IS_CANVAS_GROUPABLE (group), -1); if (dia_canvas_groupable_get_iter (group, &iter)) do { count++; } while (dia_canvas_groupable_next (group, &iter)); return count; } /** * dia_canvas_groupable_pos: * @group: * @item: * * Get the position of @item in the group. * * Return value: Position of @item, -1 on error. **/ gint dia_canvas_groupable_pos (DiaCanvasGroupable *group, DiaCanvasItem *item) { DiaCanvasIter iter; gint count = 0; g_return_val_if_fail (DIA_IS_CANVAS_GROUPABLE (group), -1); g_return_val_if_fail (DIA_IS_CANVAS_ITEM (item), -1); if (dia_canvas_groupable_get_iter (group, &iter)) do { if (item == dia_canvas_groupable_value (group, &iter)) { dia_canvas_iter_destroy (&iter); return count; } count++; } while (dia_canvas_groupable_next (group, &iter)); return -1; }