[dia] Align Connected: aligning at connected points
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] Align Connected: aligning at connected points
- Date: Sun, 15 Aug 2010 19:07:03 +0000 (UTC)
commit f705f2d7fb6e65b1b053a72714bc0450d020fcfc
Author: Hans Breuer <hans breuer org>
Date: Sun Aug 15 20:38:33 2010 +0200
Align Connected: aligning at connected points
Aligning objects usually works on the objects bounding boxes.
To get straight lines connecting multiple objects in the same
direction it might be useful to align the connected points
instead. This will (slightly) move the objects - while staying
connected - to have the connection points on a straight line.
Currently implemented are horizontal and vertical alignment
based on the information given by the used connection points.
(Following commits will fix some of this info.)
move the objects
app/commands.c | 20 +++++++++
app/commands.h | 1 +
app/menus.c | 1 +
app/object_ops.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++-
app/object_ops.h | 1 +
data/display-ui.xml | 1 +
data/popup-ui.xml | 1 +
7 files changed, 139 insertions(+), 2 deletions(-)
---
diff --git a/app/commands.c b/app/commands.c
index 17b20e9..04e5e34 100644
--- a/app/commands.c
+++ b/app/commands.c
@@ -1241,6 +1241,26 @@ objects_align_v_callback (GtkAction *action)
undo_set_transactionpoint(dia->undo);
}
+void
+objects_align_connected_callback (GtkAction *action)
+{
+ Diagram *dia;
+ GList *objects;
+
+ dia = ddisplay_active_diagram();
+ if (!dia) return;
+ objects = dia->data->selected;
+
+ object_add_updates_list(objects, dia);
+ object_list_align_connected(objects, dia, 0);
+ diagram_update_connections_selection(dia);
+ object_add_updates_list(objects, dia);
+ diagram_modified(dia);
+ diagram_flush(dia);
+
+ undo_set_transactionpoint(dia->undo);
+}
+
/*! Open a file and show it in a new display */
void
dia_file_open (const gchar *filename,
diff --git a/app/commands.h b/app/commands.h
index a770e1a..c72dded 100644
--- a/app/commands.h
+++ b/app/commands.h
@@ -87,6 +87,7 @@ void objects_group_callback (GtkAction *action);
void objects_ungroup_callback (GtkAction *action);
void objects_align_h_callback (GtkAction *action);
void objects_align_v_callback (GtkAction *action);
+void objects_align_connected_callback (GtkAction *action);
void dialogs_properties_callback (GtkAction *action);
void dialogs_layers_callback (GtkAction *action);
diff --git a/app/menus.c b/app/menus.c
index f89de77..21fc418 100644
--- a/app/menus.c
+++ b/app/menus.c
@@ -191,6 +191,7 @@ static const GtkActionEntry display_entries[] =
{ "ObjectsAlignSpreadoutvertically", NULL, N_("Spread Out Vertically"), "<alt><shift>V", NULL, G_CALLBACK (objects_align_v_callback) },
{ "ObjectsAlignAdjacent", NULL, N_("Adjacent"), "<alt><shift>A", NULL, G_CALLBACK (objects_align_h_callback) },
{ "ObjectsAlignStacked", NULL, N_("Stacked"), "<alt><shift>S", NULL, G_CALLBACK (objects_align_v_callback) },
+ { "ObjectsAlignConnected", NULL, N_("Connected"), "<alt><shift>O", NULL, G_CALLBACK (objects_align_connected_callback) },
{ "ObjectsProperties", GTK_STOCK_PROPERTIES, NULL, "<alt>Return", NULL, G_CALLBACK (dialogs_properties_callback) },
diff --git a/app/object_ops.c b/app/object_ops.c
index 0096408..47fb76f 100644
--- a/app/object_ops.c
+++ b/app/object_ops.c
@@ -168,7 +168,8 @@ object_list_corner(GList *list)
}
static int
-object_list_sort_vertical(const void *o1, const void *o2) {
+object_list_sort_vertical(const void *o1, const void *o2)
+{
DiaObject *obj1 = *(DiaObject **)o1;
DiaObject *obj2 = *(DiaObject **)o2;
@@ -318,7 +319,8 @@ object_list_align_v(GList *objects, Diagram *dia, int align)
static int
-object_list_sort_horizontal(const void *o1, const void *o2) {
+object_list_sort_horizontal(const void *o1, const void *o2)
+{
DiaObject *obj1 = *(DiaObject **)o1;
DiaObject *obj2 = *(DiaObject **)o2;
@@ -464,6 +466,116 @@ object_list_align_h(GList *objects, Diagram *dia, int align)
g_list_free(objects);
}
+/*! Align objects at their connected points */
+void
+object_list_align_connected (GList *objects, Diagram *dia, int align)
+{
+ GList *list;
+ GList *connected;
+ Point *orig_pos;
+ Point *dest_pos;
+ DiaObject *obj, *o2;
+ int i, nobjs;
+ GList *to_be_moved = NULL;
+ GList *movelist = NULL;
+ GList *connections = NULL;
+
+ /* find all elements to be moved directly */
+ list = objects;
+ while (list != NULL) {
+ obj = list->data;
+ for (i = 0; i < obj->num_connections; ++i) {
+ ConnectionPoint *cp = obj->connections[i];
+ connected = cp->connected;
+ /* first of all remember the objects connected to anything */
+ if (connected && !g_list_find (to_be_moved, obj))
+ to_be_moved = g_list_append (to_be_moved, obj);
+ /* also list all the connection objects - our todo list */
+ while (connected != NULL) {
+ o2 = connected->data;
+ if (!g_list_find (connections, o2))
+ connections = g_list_append (connections, o2);
+ connected = g_list_next (connected);
+ }
+ }
+ list = g_list_next (list);
+ }
+ dia_log_message ("Moves %d - Connections %d\n", g_list_length (to_be_moved), g_list_length (connections));
+ /* for every connection check:
+ * - "matching" directions of both object connection points (this also gives
+ * the direction of the move of the second object)
+ * -
+ * - move every object only once
+ */
+ nobjs = g_list_length (to_be_moved);
+ orig_pos = g_new (Point, nobjs);
+ dest_pos = g_new (Point, nobjs);
+
+ list = connections;
+ while (list != NULL) {
+ DiaObject *con = list->data;
+ Handle *h1 = NULL, *h2 = NULL;
+
+ g_assert (con->num_handles >= 2);
+ for (i = 0; i < con->num_handles; ++i) {
+ if (con->handles[i]->id == HANDLE_MOVE_STARTPOINT)
+ h1 = con->handles[i];
+ else if (con->handles[i]->id == HANDLE_MOVE_ENDPOINT)
+ h2 = con->handles[i];
+ }
+ /* should this be an assert? */
+ if (h1 && h2 && h1->connected_to && h2->connected_to) {
+ ConnectionPoint *cps = h1->connected_to;
+ ConnectionPoint *cpe = h2->connected_to;
+
+ obj = cps->object;
+ o2 = cpe->object;
+ if (g_list_find(to_be_moved, o2) && !g_list_find (movelist, o2)) {
+ Point delta = {0, 0};
+ /* if we haven't moved it yet, check if we want to */
+ if ( (cps->directions == DIR_NORTH && cpe->directions == DIR_SOUTH)
+ || (cps->directions == DIR_SOUTH && cpe->directions == DIR_NORTH)) {
+ /* horizontal move */
+ delta.x = cps->pos.x - cpe->pos.x;
+ } else if ( (cps->directions == DIR_EAST && cpe->directions == DIR_WEST)
+ || (cps->directions == DIR_WEST && cpe->directions == DIR_EAST)) {
+ /* vertical move */
+ delta.y = cps->pos.y - cpe->pos.y;
+ } else {
+ /* would need more context */
+ char dirs[] = "NESW";
+ int j;
+ for (j = 0; j < 4; ++j) if (cps->directions & (1<<j)) g_print ("%c", dirs[j]);
+ g_print ("(%s) -> ", obj->type->name);
+ for (j = 0; j < 4; ++j) if (cpe->directions & (1<<j)) g_print ("%c", dirs[j]);
+ g_print ("(%s)\n", o2->type->name);
+ }
+ if (delta.x != 0.0 || delta.y != 0) {
+ Point pos = o2->position;
+
+ point_add (&pos, &delta);
+
+ i = g_list_length (movelist);
+ orig_pos[i] = o2->position;
+ dest_pos[i] = pos;
+
+ dia_log_message ("Move '%s' by %g,%g\n", o2->type->name, delta.x, delta.y);
+ o2->ops->move (o2, &pos);
+ diagram_update_connections_object (dia, o2, FALSE);
+ movelist = g_list_append (movelist, o2);
+ }
+ }
+ }
+
+ list = g_list_next (list);
+ }
+
+ /* eating all the passed in parameters */
+ undo_move_objects (dia, orig_pos, dest_pos, movelist);
+ g_list_free (to_be_moved);
+ g_list_free (connections);
+}
+
/** Move the list in the given direction.
*
* @param objects The objects to move
diff --git a/app/object_ops.h b/app/object_ops.h
index d89fe23..93c7d6b 100644
--- a/app/object_ops.h
+++ b/app/object_ops.h
@@ -46,6 +46,7 @@ void object_connect_display(DDisplay *ddisp, DiaObject *obj,
Point object_list_corner(GList *list);
void object_list_align_h(GList *objects, Diagram *dia, int align);
void object_list_align_v(GList *objects, Diagram *dia, int align);
+void object_list_align_connected (GList *objects, Diagram *dia, int align);
typedef enum {
DIR_UP = 1,
diff --git a/data/display-ui.xml b/data/display-ui.xml
index 79439e6..2cd44aa 100644
--- a/data/display-ui.xml
+++ b/data/display-ui.xml
@@ -107,6 +107,7 @@
<menuitem name="ObjectsAlignSpreadoutvertically" action="ObjectsAlignSpreadoutvertically" />
<menuitem name="ObjectsAlignAdjacent" action="ObjectsAlignAdjacent" />
<menuitem name="ObjectsAlignStacked" action="ObjectsAlignStacked" />
+ <menuitem name="ObjectsAlignConnected" action="ObjectsAlignConnected" />
</menu>
<separator name="ObjectsSep4" />
<menuitem name="ObjectsProperties" action="ObjectsProperties" />
diff --git a/data/popup-ui.xml b/data/popup-ui.xml
index 7e478f5..263e08d 100644
--- a/data/popup-ui.xml
+++ b/data/popup-ui.xml
@@ -104,6 +104,7 @@
<menuitem name="ObjectsAlignSpreadoutvertically" action="ObjectsAlignSpreadoutvertically" />
<menuitem name="ObjectsAlignAdjacent" action="ObjectsAlignAdjacent" />
<menuitem name="ObjectsAlignStacked" action="ObjectsAlignStacked" />
+ <menuitem name="ObjectsAlignConnected" action="ObjectsAlignConnected" />
</menu>
<separator name="ObjectsSep4" />
<menuitem name="ObjectsProperties" action="ObjectsProperties" />
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]