/* Dia -- an diagram creation/manipulation program * Copyright(C) 1998 Alexander Larsson * * selection.c: container object to represent the current selection * Copyright(C) 2008 Sameer D. Sahasrabuddhe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or *(at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "selection.h" #include "object.h" typedef struct _SelectionPropChange SelectionPropChange; struct _Selection { DiaObject object; /* parent class */ GList *objects; /* we don't own these */ }; static Selection* selection_create(); static void selection_destroy(Selection * sel); static DiaObject *selection_copy(Selection * sel); static void selection_select(Selection * sel, Point * clicked_point, DiaRenderer * interactive_renderer); static SelectionPropChange *selection_move(Selection * sel, Point * delta); static SelectionPropChange *selection_move_handle(Selection * sel, Handle * handle, Point * pos, ConnectionPoint * cp, HandleMoveReason reason, ModifierKeys modifiers); static SelectionPropChange *selection_apply_properties_list(Selection * sel, GPtrArray * props); static void selection_draw(Selection * sel, DiaRenderer * ddisp); static real selection_distance_from(Selection * sel, Point * point); static const PropDescription *selection_describe_props(Selection * sel); static void selection_get_props(Selection * sel, GPtrArray * props); static void selection_set_props(Selection * sel, GPtrArray * props); static ObjectOps selection_ops = { (DestroyFunc) selection_destroy, (DrawFunc) selection_draw, (DistanceFunc) selection_distance_from, (SelectFunc) NULL, (CopyFunc) selection_copy, (MoveFunc) selection_move, (MoveHandleFunc) selection_move_handle, (GetPropertiesFunc) object_create_props_dialog, (ApplyPropertiesDialogFunc) object_apply_props_from_dialog, (ObjectMenuFunc) NULL, (DescribePropsFunc) selection_describe_props, (GetPropsFunc) selection_get_props, (SetPropsFunc) selection_set_props, (TextEditFunc) 0, (ApplyPropertiesListFunc) selection_apply_properties_list, }; DiaObjectType selection_type = { "Selection", 0, NULL }; Selection * selection_create() { Selection *sel; DiaObject *obj; sel = g_new0(Selection, 1); obj = &sel->object; obj->type = &selection_type; obj->ops = &selection_ops; /* Note that the selection is always at the origin. */ obj->position.x = 0.0; obj->position.y = 0.0; return sel; } static void selection_destroy(Selection * sel) { /* Don't actually destroy the objects. We don't own them. */ g_list_free(sel->objects); sel->objects = NULL; } static DiaObject * selection_copy(Selection * sel) { DiaObject *obj, *newobj; Selection *newsel; newsel = g_new0(Selection, 1); obj = &sel->object; newobj = &newsel->object; object_copy(obj, newobj); /* Shallow copy. We don't own them, remember? */ newsel->objects = g_list_copy(sel->objects); return(DiaObject *) newsel; } static void selection_select(Selection * sel, Point * clicked_point, DiaRenderer * interactive_renderer) { /* Since the selection is not a real object, it cannot be selected. */ g_return_if_reached(); } static SelectionPropChange * selection_move(Selection * sel, Point * to) { GList *i; DiaObject *selobj = (DiaObject*)sel; g_warn_if_fail(selobj->position.x == 0.0 && selobj->position.y == 0.0); /* In any code that ends up moving the selection, the call to "move" for each selected object first computes the destination using the current position of that object. That code now moves only the Selection object, which is at the origin. Hence the destination computed is actually the delta. We recalculate the destination of each selected object before calling "move" on that object. Ugly, but effective. */ for (i = sel->objects; i != NULL; i = g_list_next(i)) { DiaObject *object = (DiaObject*)i->data; Point pos = object->position; point_add(&pos, to); object->ops->move(object, &pos); } } static SelectionPropChange* selection_move_handle(Selection * sel, Handle * handle, Point * pos, ConnectionPoint * cp, HandleMoveReason reason, ModifierKeys modifiers) { /* Selections don't have handles. Not yet. */ g_return_if_reached(); } static void selection_draw(Selection * sel, DiaRenderer * ddisp) { /* Selections are not real objects in the diagram, and hence this function will be never called. */ g_return_if_reached(); } static real selection_distance_from(Selection * sel, Point * point) { /* This should not get called. If it does, then the selection is also wherever you are, not just the origin. */ g_return_val_if_reached((real)0.0); } static const PropDescription* selection_describe_props(Selection * sel) { /* The code here is identical to group_describe_props. The body of that function should be extracted into a function called object_list_describe_props. It should take an additional argument that determines whether a union or intersection is desired. */ } static void selection_get_props(Selection * sel, GPtrArray * props) { /* Again, the same as group_get_props, to be extracted into object_list_get_props. */ } static void selection_set_props(Selection * sel, GPtrArray * props) { /* Same as above. */ }