From e5f0f5ff6e90af7a05e6069bdf0726c46d63778f Mon Sep 17 00:00:00 2001 From: lclausen Date: Mon, 7 Aug 2006 20:08:37 +0000 Subject: [PATCH] New group work, and utility funcs. --- ChangeLog | 10 ++++++++++ app/diagram.c | 17 +++++++++++++---- app/modify_tool.c | 12 ++++-------- app/select.c | 36 ++++++++++++++++-------------------- lib/diagramdata.c | 18 ++++++++++++++++-- lib/object.c | 42 ++++++++++++++++++++++++++++++++++++++++++ lib/object.h | 2 ++ objects/Misc/newgroup.c | 13 +++++++++++-- 8 files changed, 114 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index 659b74b6..c91da7c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2006-08-06 Lars Clausen + + * objects/Misc/newgroup.c: + * lib/diagramdata.c: + * app/diagram.[ch]: + * app/select.c: + * app/modify_tool.c: + * lib/object.[ch]: Work towards a more reasonable definition of + Groups. + 2006-08-06 Steffen Macke * installer/win32/dia.nsi: Save diagrams by default in "My Pictures"; diff --git a/app/diagram.c b/app/diagram.c index f3c9ff3c..a65641f9 100644 --- a/app/diagram.c +++ b/app/diagram.c @@ -651,13 +651,22 @@ diagram_unselect_objects(Diagram *dia, GList *obj_list) g_signal_emit (dia, diagram_signals[SELECTION_CHANGED], 0, g_list_length (dia->data->selected)); } +/** Make a single object selected. + * Note that an object inside a closed group cannot be made selected, nor + * can an object in a non-active layer. + * @param diagram The diagram that the object belongs to (sorta redundant now) + * @param obj The object that should be made selected. + */ void diagram_select(Diagram *diagram, DiaObject *obj) { - data_select(diagram->data, obj); - obj->ops->selectf(obj, NULL, NULL); - object_add_updates(obj, diagram); - g_signal_emit (diagram, diagram_signals[SELECTION_CHANGED], 0, g_list_length (diagram->data->selected)); + if (dia_object_is_selectable(obj)) { + data_select(diagram->data, obj); + obj->ops->selectf(obj, NULL, NULL); + object_add_updates(obj, diagram); + g_signal_emit (diagram, diagram_signals[SELECTION_CHANGED], 0, + g_list_length (diagram->data->selected)); + } } void diff --git a/app/modify_tool.c b/app/modify_tool.c index 24c4e1f4..711387bd 100644 --- a/app/modify_tool.c +++ b/app/modify_tool.c @@ -598,14 +598,10 @@ find_selected_objects(DDisplay *ddisp, ModifyTool *tool) r.top = MIN(tool->start_box.y, tool->end_box.y); r.bottom = MAX(tool->start_box.y, tool->end_box.y); - if (prefs.reverse_rubberbanding_intersects) { - if (tool->start_box.x > tool->end_box.x) { - return - layer_find_objects_intersecting_rectangle(ddisp->diagram->data->active_layer, &r); - } else { - return - layer_find_objects_in_rectangle(ddisp->diagram->data->active_layer, &r); - } + if (prefs.reverse_rubberbanding_intersects && + tool->start_box.x > tool->end_box.x) { + return + layer_find_objects_intersecting_rectangle(ddisp->diagram->data->active_layer, &r); } else { return layer_find_objects_in_rectangle(ddisp->diagram->data->active_layer, &r); diff --git a/app/select.c b/app/select.c index 0da89fd1..428a8f24 100644 --- a/app/select.c +++ b/app/select.c @@ -43,8 +43,9 @@ select_all_callback(gpointer data, guint action, GtkWidget *widget) while (objects != NULL) { DiaObject *obj = (DiaObject *)objects->data; - if (!diagram_is_selected(dia, obj)) + if (!diagram_is_selected(dia, obj)) { diagram_select(dia, obj); + } objects = g_list_next(objects); } @@ -85,10 +86,11 @@ select_invert_callback(gpointer data, guint action, GtkWidget *widget) for (; tmp != NULL; tmp = g_list_next(tmp)) { DiaObject *obj = (DiaObject *)tmp->data; - if (!diagram_is_selected(dia, obj)) + if (!diagram_is_selected(dia, obj)) { diagram_select(dia, obj); - else + } else { diagram_unselect_object(dia, obj); + } } ddisplay_do_update_menu_sensitivity(ddisp); @@ -119,11 +121,10 @@ select_connected_callback(gpointer data, guint action, GtkWidget *widget) for (i = 0; i < obj->num_handles; i++) { Handle *handle = obj->handles[i]; - if (handle->connected_to != NULL && - handle->connected_to->object->parent_layer == dia->data->active_layer) { - if (!diagram_is_selected(dia, handle->connected_to->object)) { - diagram_select(dia, handle->connected_to->object); - } + if (handle->connected_to != NULL + && dia_object_is_selectable(handle->connected_to->object) + && !diagram_is_selected(dia, handle->connected_to->object)) { + diagram_select(dia, handle->connected_to->object); } } } @@ -139,7 +140,7 @@ select_connected_callback(gpointer data, guint action, GtkWidget *widget) for (; conns != NULL; conns = g_list_next(conns)) { DiaObject *obj2 = (DiaObject *)conns->data; - if (obj2->parent_layer == dia->data->active_layer + if (dia_object_is_selectable(obj2) && !diagram_is_selected(dia, obj2)) { diagram_select(dia, obj2); } @@ -163,10 +164,11 @@ select_transitively(Diagram *dia, DiaObject *obj) Handle *handle = obj->handles[i]; if (handle->connected_to != NULL && - handle->connected_to->object->parent_layer == dia->data->active_layer) { - if (!diagram_is_selected(dia, handle->connected_to->object)) { - diagram_select(dia, handle->connected_to->object); - newly_selected = g_list_prepend(newly_selected, handle->connected_to->object); + dia_object_is_selectable(handle->connected_to->object)) { + DiaObject *connected_object = handle->connected_to->object; + if (!diagram_is_selected(dia, connected_object)) { + diagram_select(dia, connected_object); + newly_selected = g_list_prepend(newly_selected, connected_object); } } } @@ -178,8 +180,7 @@ select_transitively(Diagram *dia, DiaObject *obj) for (; conns != NULL; conns = g_list_next(conns)) { DiaObject *obj2 = (DiaObject *)conns->data; - if (obj2->parent_layer == dia->data->active_layer - && !diagram_is_selected(dia, obj2)) { + if (dia_object_is_selectable(obj2) && !diagram_is_selected(dia, obj2)) { diagram_select(dia, obj2); newly_selected = g_list_prepend(newly_selected, obj2); } @@ -260,8 +261,3 @@ select_style_callback(gpointer data, guint action, GtkWidget *widget) /* simply set the selection style to the value of `action' */ selection_style = action; } - - - - - diff --git a/lib/diagramdata.c b/lib/diagramdata.c index 763a8916..00f72e15 100644 --- a/lib/diagramdata.c +++ b/lib/diagramdata.c @@ -867,7 +867,12 @@ layer_find_objects_intersecting_rectangle(Layer *layer, Rectangle *rect) obj = (DiaObject *)list->data; if (rectangle_intersects(rect, &obj->bounding_box)) { - selected_list = g_list_prepend(selected_list, obj); + if (dia_object_is_selectable(obj)) { + selected_list = g_list_prepend(selected_list, obj); + } + /* Objects in closed groups do not get selected, but their parents do. + * Since the parents bbox is outside the objects, they will be found + * anyway and the inner object can just be skipped. */ } list = g_list_next(list); @@ -892,10 +897,13 @@ layer_find_objects_in_rectangle(Layer *layer, Rectangle *rect) selected_list = NULL; list = layer->objects; while (list != NULL) { + DiaObject *parent; obj = (DiaObject *)list->data; if (rectangle_in_rectangle(rect, &obj->bounding_box)) { - selected_list = g_list_prepend(selected_list, obj); + if (dia_object_is_selectable(obj)) { + selected_list = g_list_prepend(selected_list, obj); + } } list = g_list_next(list); @@ -944,6 +952,10 @@ layer_find_closest_object_except(Layer *layer, Point *pos, ; } + /* If the object is within a closed group, find the group. */ + closest = dia_object_get_parent_with_flags(closest, + DIA_OBJECT_GRABS_CHILD_INPUT); + return closest; } @@ -989,6 +1001,8 @@ layer_find_closest_connectionpoint(Layer *layer, obj = (DiaObject *) l->data; if (obj == notthis) continue; + if (obj != dia_object_get_parent_with_flags(obj, DIA_OBJECT_GRABS_CHILD_INPUT)) + continue; for (i=0;inum_connections;i++) { cp = obj->connections[i]; /* Note: Uses manhattan metric for speed... */ diff --git a/lib/object.c b/lib/object.c index d55cd5dc..28dc9b31 100644 --- a/lib/object.c +++ b/lib/object.c @@ -639,6 +639,48 @@ dia_object_is_selected (const DiaObject *obj) return FALSE; } +/** Return the top-most object in the parent chain that has the given + * flags set. + * @param obj An object to start at. If this is NULL, NULL is returned. + * @param flags The flags to check. If 0, the top-most parent is returned. + * If more than one flag is given, the top-most parent that has all the given + * flags set is returned. + * @returns An object that either has all the flags set or + * is obj itself. It is guaranteed that no parent of this object has all the + * given flags set. + */ +DiaObject * +dia_object_get_parent_with_flags(DiaObject *obj, guint flags) +{ + DiaObject *top = obj; + if (obj == NULL) { + return NULL; + } + while (obj->parent != NULL) { + obj = obj->parent; + if ((obj->flags & flags) == flags) { + top = obj; + } + } + return top; +} + +/** Utility function: Checks if an objects can be selected. + * Reasons for not being selectable include: + * Being inside a closed group. + * Being in a non-active layer. + * + * @param obj An object to test. + * @returns TRUE if the object is not currently selected. + */ +gboolean +dia_object_is_selectable(DiaObject *obj) +{ + return obj->parent_layer == obj->parent_layer->parent_diagram->active_layer + && obj == dia_object_get_parent_with_flags(obj, DIA_OBJECT_GRABS_CHILD_INPUT); +} + + /****** DiaObject register: **********/ static guint hash(gpointer key) diff --git a/lib/object.h b/lib/object.h index cb0c058a..efdf6b70 100644 --- a/lib/object.h +++ b/lib/object.h @@ -559,6 +559,8 @@ Layer *dia_object_get_parent_layer(DiaObject *obj); gboolean dia_object_is_selected (const DiaObject *obj); Rectangle *dia_object_get_bounding_box(const DiaObject *obj); Rectangle *dia_object_get_enclosing_box(const DiaObject *obj); +DiaObject *dia_object_get_parent_with_flags(DiaObject *obj, guint flags); +gboolean dia_object_is_selectable(DiaObject *obj); /* The below are for debugging purposes only. */ gboolean dia_object_sanity_check(const DiaObject *obj, const gchar *msg); diff --git a/objects/Misc/newgroup.c b/objects/Misc/newgroup.c index df5ccd5f..359d0a41 100644 --- a/objects/Misc/newgroup.c +++ b/objects/Misc/newgroup.c @@ -45,6 +45,7 @@ typedef struct _Group NewGroup; struct _Group { Element element; + gboolean is_open; ConnectionPoint connections[NUM_CONNECTIONS]; }; @@ -110,6 +111,9 @@ static ObjectOps newgroup_ops = { static PropDescription newgroup_props[] = { ELEMENT_COMMON_PROPERTIES, + { "open", PROP_TYPE_BOOL, PROP_FLAG_VISIBLE, + N_("Open group"), NULL, NULL}, + PROP_DESC_END }; @@ -123,6 +127,7 @@ newgroup_describe_props(NewGroup *group) static PropOffset newgroup_offsets[] = { ELEMENT_COMMON_PROPERTIES_OFFSETS, + { "open", PROP_TYPE_BOOL, offsetof(NewGroup, is_open) }, { NULL, 0, 0 } }; @@ -158,8 +163,6 @@ static void newgroup_select(NewGroup *group, Point *clicked_point, DiaRenderer *interactive_renderer) { - real radius; - element_update_handles(&group->element); } @@ -258,6 +261,12 @@ newgroup_update_data(NewGroup *group) obj->position = elem->corner; element_update_handles(elem); + + if (group->is_open) { + obj->flags &= ~DIA_OBJECT_GRABS_CHILD_INPUT; + } else { + obj->flags |= DIA_OBJECT_GRABS_CHILD_INPUT; + } } static DiaObject * -- 2.11.4.GIT