proposed UML sequence diagram fixes
- From: Hans Busch <hans bu gmx net>
- To: dia-list gnome org
- Subject: proposed UML sequence diagram fixes
- Date: Thu, 20 Mar 2003 08:43:15 +0100 (MET)
The changes have been implemented to ease the creation of
UML sequence diagrams. The storage format and geometric extents
remain unchanged such that all changes are compatible to dia 0.90
and 0.91.
The changes to UML-Object and UML-Lifeline can be seen as bugfixes,
because the original versions could hardly be used together with grid
alignment. The changes to UML-Message add in place editing and object
menu to speed up drawing.
UML-Object
- object center is grid aligned instead of the upper left corner such
that the attached lifeline will be on the grid.
UML-lifeline
- top handle moves box instead of resizing it to allow easy moving
of the box.
- on move of bottom handle the number of connection points is set such
that they are located on the vertical grid. Due to the odd layout
actually twice as much connection points are assigned to keep
backwards compatibility and to allow odd vertical box sizes.
- the object menu has been kept, although there is not much use for it
anymore. Removing it would reduce the code by about 20%.
UML-Message
- inplace text editing has been added. Replacing lots of character
drawing code by lib/text methods actually reduced code size!
- added object menu to change arrow type
-------------
Code Changes:
diff -u objects/org-UML/lifeline.c objects/UML/lifeline.c
--- objects/org-UML/lifeline.c Sun Jan 26 07:44:52 2003
+++ objects/UML/lifeline.c Fri Mar 14 23:06:47 2003
@@ -205,7 +205,7 @@
lifeline_move_handle(Lifeline *lifeline, Handle *handle,
Point *to, HandleMoveReason reason, ModifierKeys modifiers)
{
- real s, t;
+ real t, height;
Connection *conn;
assert(lifeline!=NULL);
@@ -213,60 +213,59 @@
assert(to!=NULL);
conn = &lifeline->connection;
- if (handle->id == HANDLE_BOXBOT) {
- t = to->y - conn->endpoints[0].y;
- if (t > LIFELINE_BOXMINHEIGHT &&
- t < conn->endpoints[1].y - conn->endpoints[0].y) {
+ height = conn->endpoints[1].y - conn->endpoints[0].y;
+ t = to->y - conn->endpoints[0].y;
+ switch(handle->id) {
+ case HANDLE_BOXTOP:
+ if (t > 0 && t < height - (lifeline->rbot - lifeline->rtop)) {
+ lifeline->rbot += t - lifeline->rtop;
+ lifeline->rtop = t;
+ }
+ break;
+ case HANDLE_BOXBOT: {
+ Layer *layer = dia_object_get_parent_layer(&conn->object);
+ DiagramData *dia_data = layer_get_parent_diagram(layer);
+
+ if (t > lifeline->rtop + LIFELINE_BOXMINHEIGHT && t < height) {
lifeline->rbot = t;
- if (t < lifeline->rtop + LIFELINE_BOXMINHEIGHT)
- lifeline->rtop = t - LIFELINE_BOXMINHEIGHT;
}
- } else if (handle->id == HANDLE_BOXTOP) {
- t = to->y - conn->endpoints[0].y;
- if (t > 0 &&
- t < conn->endpoints[1].y-conn->endpoints[0].y-LIFELINE_BOXMINHEIGHT) {
- lifeline->rtop = t;
- if (t > lifeline->rbot - LIFELINE_BOXMINHEIGHT)
- lifeline->rbot = t + LIFELINE_BOXMINHEIGHT;
+ /* update number of connections */
+ if (dia_data && dia_data->grid.width_y > 0) {
+ int count = (lifeline->rbot - lifeline->rtop) /
+ (dia_data->grid.width_y) - 0.5;
+ if (count > 0) {
+ connpointline_adjust_count(lifeline->northwest, count, to);
+ connpointline_adjust_count(lifeline->northeast, count, to);
+ connpointline_adjust_count(lifeline->southwest, count, to);
+ connpointline_adjust_count(lifeline->southeast, count, to);
+ }
}
- } else {
- /* move horizontally only if startpoint is moved */
- if (handle->id==HANDLE_MOVE_STARTPOINT) {
- conn->endpoints[0].x = conn->endpoints[1].x = to->x;
- } else {
- to->x = conn->endpoints[0].x;
+ break;
}
- /* If connected don't change size */
- t = (reason==HANDLE_MOVE_CONNECTED) ?
- conn->endpoints[1].y - conn->endpoints[0].y:
- lifeline->rbot;
- connection_move_handle(conn, handle->id, to, reason);
- s = conn->endpoints[1].y - conn->endpoints[0].y;
- if (handle->id==HANDLE_MOVE_ENDPOINT && s < t && s > lifeline->rtop +
LIFELINE_BOXMINHEIGHT)
- lifeline->rbot = s;
- else if (reason==HANDLE_MOVE_CONNECTED || s < t)
- conn->endpoints[1].y = conn->endpoints[0].y + t;
+ case HANDLE_MOVE_STARTPOINT:
+ conn->endpoints[0] = conn->endpoints[1] = *to;
+ conn->endpoints[1].y = to->y + height;
+ break;
+ case HANDLE_MOVE_ENDPOINT:
+ if (t > lifeline->rbot)
+ conn->endpoints[1].y = to->y;
+ break;
+ default:
+ perror("illegal handle");
}
-
lifeline_update_data(lifeline);
}
static void
lifeline_move(Lifeline *lifeline, Point *to)
{
- Point start_to_end;
- Point delta;
+ Point delta = *to;
Point *endpoints = &lifeline->connection.endpoints[0];
- delta = *to;
- point_sub(&delta, &endpoints[0]);
-
- start_to_end = endpoints[1];
- point_sub(&start_to_end, &endpoints[0]);
+ point_sub(&delta, &lifeline->connection.object.position);
+ point_add(&endpoints[0], &delta);
+ point_add(&endpoints[1], &delta);
- endpoints[1] = endpoints[0] = *to;
- point_add(&endpoints[1], &start_to_end);
-
lifeline_update_data(lifeline);
}
@@ -513,8 +512,6 @@
LineBBExtras *extra = &conn->extra_spacing;
Point p1, p2, pnw, psw, pne, pse, pmw,pme;
- obj->position = conn->endpoints[0];
-
/* box handles: */
p1.x = conn->endpoints[0].x;
p1.y = conn->endpoints[0].y + lifeline->rtop;
@@ -523,6 +520,8 @@
p2.y = conn->endpoints[0].y + lifeline->rbot;
lifeline->boxbot_handle.pos = p2;
+ obj->position = p1; // this point should be on grid
+
connection_update_handles(conn);
/* Boundingbox: */
@@ -569,6 +568,7 @@
connpointline_putonaline(lifeline->northeast,&pne,&pme);
connpointline_update(lifeline->southeast);
connpointline_putonaline(lifeline->southeast,&pme,&pse);
+
}
static Object *
@@ -577,12 +577,3 @@
return object_load_using_properties(&lifeline_type,
obj_node,version,filename);
}
-
-
-
-
-
-
-
-
-
diff -u objects/org-UML/message.c objects/UML/message.c
--- objects/org-UML/message.c Sun Jan 26 07:44:52 2003
+++ objects/UML/message.c Wed Mar 12 07:55:20 2003
@@ -34,6 +34,7 @@
#include "handle.h"
#include "arrows.h"
#include "properties.h"
+#include "text.h"
#include "pixmaps/message.xpm"
@@ -51,16 +52,24 @@
MESSAGE_RECURSIVE
} MessageType;
+typedef enum {
+ MESSAGE_SELECT_LINE,
+ MESSAGE_SELECT_TEXT
+} MessageSelectMode;
+
+
struct _Message {
Connection connection;
Handle text_handle;
- gchar *text;
+ Text *ttext;
+ gchar *text; // used for backward compatible load/store only
Point text_pos;
real text_width;
MessageType type;
+ MessageSelectMode select_mode;
};
#define MESSAGE_WIDTH 0.1
@@ -92,6 +101,8 @@
static PropDescription *message_describe_props(Message *mes);
static void message_get_props(Message * message, GPtrArray *props);
static void message_set_props(Message *message, GPtrArray *props);
+static DiaMenu *message_get_object_menu(Message *message,
+ Point *clickedpoint);
static ObjectTypeOps message_type_ops =
{
@@ -120,7 +131,7 @@
(MoveHandleFunc) message_move_handle,
(GetPropertiesFunc) object_create_props_dialog,
(ApplyPropertiesFunc) object_apply_props_from_dialog,
- (ObjectMenuFunc) NULL,
+ (ObjectMenuFunc) message_get_object_menu,
(DescribePropsFunc) message_describe_props,
(GetPropsFunc) message_get_props,
(SetPropsFunc) message_set_props
@@ -168,6 +179,9 @@
static void
message_get_props(Message * message, GPtrArray *props)
{
+ g_free(message->text); // update string
+ message->text = text_get_string_copy(message->ttext);
+
object_get_props_from_offsets(&message->connection.object,
message_offsets, props);
}
@@ -177,6 +191,8 @@
{
object_set_props_from_offsets(&message->connection.object,
message_offsets, props);
+ text_set_string(message->ttext, message->text);
+
message_update_data(message);
}
@@ -185,12 +201,14 @@
message_distance_from(Message *message, Point *point)
{
Point *endpoints;
- real dist;
+ real dist, distText;
endpoints = &message->connection.endpoints[0];
dist = distance_line_point(&endpoints[0], &endpoints[1], MESSAGE_WIDTH,
point);
-
+ distText = text_distance_from(message->ttext, point);
+ if (distText < dist)
+ dist = distText;
return dist;
}
@@ -198,6 +216,16 @@
message_select(Message *message, Point *clicked_point,
DiaRenderer *interactive_renderer)
{
+ int no_text = text_is_empty(message->ttext);
+ Point *endpoints = &message->connection.endpoints[0];
+ message->select_mode = MESSAGE_SELECT_LINE;
+ if (no_text || text_distance_from(message->ttext, clicked_point) <
+ distance_line_point(&endpoints[0], &endpoints[1],
+ MESSAGE_WIDTH, clicked_point)) {
+ if (!no_text) message->select_mode = MESSAGE_SELECT_TEXT;
+ text_set_cursor(message->ttext, clicked_point, interactive_renderer);
+ text_grab_focus(message->ttext, &message->connection.object);
+ }
connection_update_handles(&message->connection);
}
@@ -235,18 +263,20 @@
Point *endpoints = &message->connection.endpoints[0];
Point delta;
- delta = *to;
- point_sub(&delta, &endpoints[0]);
+ if (message->select_mode != MESSAGE_SELECT_TEXT) {
+ delta = *to;
+ point_sub(&delta, &endpoints[0]);
- start_to_end = endpoints[1];
- point_sub(&start_to_end, &endpoints[0]);
+ start_to_end = endpoints[1];
+ point_sub(&start_to_end, &endpoints[0]);
- endpoints[1] = endpoints[0] = *to;
- point_add(&endpoints[1], &start_to_end);
+ endpoints[1] = endpoints[0] = *to;
+ point_add(&endpoints[1], &start_to_end);
- point_add(&message->text_pos, &delta);
+ point_add(&message->text_pos, &delta);
- message_update_data(message);
+ message_update_data(message);
+ }
}
static void
@@ -256,7 +286,6 @@
Point *endpoints, p1, p2, px;
Arrow arrow;
int n1 = 1, n2 = 0;
- gchar *mname = NULL;
assert(message != NULL);
assert(renderer != NULL);
@@ -313,24 +342,7 @@
renderer_ops->set_font(renderer, message_font,
MESSAGE_FONTHEIGHT);
-
- if (message->type==MESSAGE_CREATE)
- mname = g_strdup_printf ("%s%s%s", UML_STEREOTYPE_START, "create",
UML_STEREOTYPE_END);
- else if (message->type==MESSAGE_DESTROY)
- mname = g_strdup_printf ("%s%s%s", UML_STEREOTYPE_START, "destroy",
UML_STEREOTYPE_END);
- else
- mname = message->text;
-
- if (mname && strlen(mname) != 0)
- renderer_ops->draw_string(renderer,
- mname, /*message->text,*/
- &message->text_pos, ALIGN_CENTER,
- &color_black);
- if (message->type == MESSAGE_CREATE || message->type == MESSAGE_DESTROY)
- {
- g_free(mname);
- }
-
+ text_draw(message->ttext, renderer);
}
@@ -370,6 +382,9 @@
message->text_pos.x = 0.5*(conn->endpoints[0].x + conn->endpoints[1].x);
message->text_pos.y = 0.5*(conn->endpoints[0].y + conn->endpoints[1].y);
+ message->ttext = new_text("", message_font, 0.8, &message->text_pos,
+ &color_black, ALIGN_CENTER);
+
message->text_handle.id = HANDLE_MOVE_TEXT;
message->text_handle.type = HANDLE_MINOR_CONTROL;
message->text_handle.connect_type = HANDLE_NONCONNECTABLE;
@@ -393,6 +408,7 @@
{
connection_destroy(&message->connection);
+ text_destroy(message->ttext);
g_free(message->text);
}
@@ -404,21 +420,14 @@
Rectangle rect;
obj->position = conn->endpoints[0];
-
+
message->text_handle.pos = message->text_pos;
-
+ text_set_position(message->ttext, &message->text_pos);
+
connection_update_handles(conn);
connection_update_boundingbox(conn);
-
- message->text_width =
- dia_font_string_width(message->text, message_font, MESSAGE_FONTHEIGHT);
-
- /* Add boundingbox for text: */
- rect.left = message->text_pos.x-message->text_width/2;
- rect.right = rect.left + message->text_width;
- rect.top = message->text_pos.y -
- dia_font_ascent(message->text, message_font, MESSAGE_FONTHEIGHT);
- rect.bottom = rect.top + MESSAGE_FONTHEIGHT;
+
+ text_calc_boundingbox(message->ttext, &rect);
rectangle_union(&obj->bounding_box, &rect);
}
@@ -430,4 +439,76 @@
obj_node,version,filename);
}
+/* Object menu handling */
+
+typedef struct {
+ ObjectChange obj_change;
+ MessageType oldType;
+ MessageType newType;
+} MessageChange;
+
+static void message_change_apply(MessageChange *change, Object *obj)
+{
+ ((Message*)obj)->type = change->newType;
+}
+
+static void message_change_revert(MessageChange *change, Object *obj)
+{
+ ((Message*)obj)->type = change->oldType;
+}
+
+static void message_change_free(MessageChange *change)
+{
+}
+
+static ObjectChange *
+message_create_change(Message *message, int newType)
+{
+ MessageChange *vc;
+
+ vc = g_new0(MessageChange,1);
+ vc->obj_change.apply = (ObjectChangeApplyFunc)message_change_apply;
+ vc->obj_change.revert = (ObjectChangeRevertFunc)message_change_revert;
+ vc->obj_change.free = (ObjectChangeFreeFunc)message_change_free;
+ vc->oldType = message->type;
+ message->type = vc->newType = newType;
+ message_update_data(message);
+ return (ObjectChange *)vc;
+}
+
+static ObjectChange *
+message_object_menu_callback(Object *obj, Point *clicked, gpointer data)
+{
+// ((Message*)obj)->type = (int)data;
+ return message_create_change((Message *)obj, (MessageType)data);
+}
+
+static DiaMenuItem object_menu_items[] = {
+ { N_("Call"), message_object_menu_callback, (void*)MESSAGE_CALL, 1 },
+ { N_("Create"), message_object_menu_callback, (void*)MESSAGE_CREATE, 1 },
+ { N_("Destroy"), message_object_menu_callback, (void*)MESSAGE_DESTROY, 1
},
+ { N_("Simple"), message_object_menu_callback, (void*)MESSAGE_SIMPLE, 1 },
+ { N_("Return"), message_object_menu_callback, (void*)MESSAGE_RETURN, 1 },
+ { N_("Send"), message_object_menu_callback, (void*)MESSAGE_SEND, 1 },
+ { N_("Recursive"), message_object_menu_callback,
+ (void*)MESSAGE_RECURSIVE, 1 },
+ { NULL, 0}
+};
+
+static DiaMenu object_menu = {
+ N_("UML Message"),
+ sizeof(object_menu_items)/sizeof(DiaMenuItem),
+ object_menu_items,
+ NULL
+};
+
+static DiaMenu *
+message_get_object_menu(Message *message, Point *clickedpoint)
+{
+ int i;
+ for(i = MESSAGE_CALL; i <= MESSAGE_RECURSIVE; i++)
+ object_menu_items[i].active = message->type == i ? 0 : 1;
+
+ return &object_menu;
+}
diff -u objects/org-UML/object.c objects/UML/object.c
--- objects/org-UML/object.c Sun Jan 26 07:44:52 2003
+++ objects/UML/object.c Wed Mar 12 07:55:20 2003
@@ -226,7 +226,7 @@
static void
objet_move(Objet *ob, Point *to)
{
- ob->element.corner = *to;
+ ob->element.object.position = *to;
objet_update_data(ob);
}
@@ -345,7 +345,7 @@
}
font = ob->text->font;
- h = elem->corner.y + OBJET_MARGIN_Y;
+ h = OBJET_MARGIN_Y;
if (ob->is_multiple) {
h += OBJET_MARGIN_M;
@@ -373,20 +373,13 @@
if (ob->show_attributes) {
h += OBJET_MARGIN_Y + ob->attributes->ascent;
- p2.x = elem->corner.x + OBJET_MARGIN_X;
- p2.y = h;
- text_set_position(ob->attributes, &p2);
-
+ p2.y = h;
h += ob->attributes->height*ob->attributes->numlines;
-
w = MAX(w, ob->attributes->max_width);
}
w += 2*OBJET_MARGIN_X;
- p1.x = elem->corner.x + w/2.0;
- text_set_position(ob->text, &p1);
-
ob->ex_pos.x = ob->st_pos.x = p1.x;
@@ -394,8 +387,20 @@
w += OBJET_MARGIN_M;
}
+ elem->corner.x = obj->position.x - w / 2.0;
+ elem->corner.y = obj->position.y - h / 2.0;
elem->width = w;
- elem->height = h - elem->corner.y;
+ elem->height = h;
+
+ p1.x = obj->position.x;
+ p1.y += elem->corner.y;
+ text_set_position(ob->text, &p1);
+
+ if (ob->show_attributes) {
+ p2.x = elem->corner.x + OBJET_MARGIN_X;
+ p2.y += elem->corner.y;
+ text_set_position(ob->attributes, &p2);
+ }
/* Update connections: */
ob->connections[0].pos = elem->corner;
@@ -415,7 +420,6 @@
ob->connections[7].pos.y = elem->corner.y + elem->height;
element_update_boundingbox(elem);
- obj->position = elem->corner;
element_update_handles(elem);
}
@@ -440,7 +444,7 @@
obj->ops = &objet_ops;
- elem->corner = *startpoint;
+ elem->object.position = *startpoint;
font = dia_font_new_from_style(DIA_FONT_SANS, OBJET_FONTHEIGHT);
--
+++ GMX - Mail, Messaging & more http://www.gmx.net +++
Bitte lächeln! Fotogalerie online mit GMX ohne eigene Homepage!
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]