direct text input for UML-message
- From: Hans Busch <hans bu gmx net>
- To: dia-list gnome org
- Subject: direct text input for UML-message
- Date: Mon, 10 Feb 2003 08:25:41 +0100 (MET)
I tried dia for designing sequence diagrams. It produces nice
charts! Unfortunately the input mechanisms via popup menus is slow.
So I had a look at the code and although it's C and not C++ I was
surprised to find such well structured code that it took only
some hours to understand amd improve UML-message (congratulations
to the designers).
Beside direct text input I also added an object menu, but I am not
satisfied with the result which may be caused by my poor understanding
of the menu mechanism. For UML-message a set of radio buttons would be
ideal. Is there a simple way to define them?
Is there a reason, why the middle button doesn't select the object?
This would speed up usage by eliminating a left mouse click.
For those interested in the changes please find them below. They are
relative to dia-0.90.
Hans
--- objects/UML-backup/message.c Wed Feb 5 22:37:01 2003
+++ objects/UML/message.c Sun Feb 9 12:27:31 2003
@@ -34,6 +34,7 @@
#include "handle.h"
#include "arrows.h"
#include "properties.h"
+#include "text.h"
#include "pixmaps/message.xpm"
@@ -52,16 +53,23 @@
MESSAGE_RECURSIVE
} MessageType;
+typedef enum {
+ MESSAGE_SELECT_LINE,
+ MESSAGE_SELECT_TEXT
+} MessageSelectMode;
+
struct _Message {
Connection connection;
Handle text_handle;
- utfchar *text;
+ Text *ttext; // replacement
+ utfchar *text; // used for backward compatible load/store
Point text_pos;
real text_width;
MessageType type;
+ MessageSelectMode select_mode;
};
#define MESSAGE_WIDTH 0.1
@@ -93,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 =
{
@@ -121,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
@@ -169,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);
}
@@ -178,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);
}
@@ -186,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;
}
@@ -199,6 +216,13 @@
message_select(Message *message, Point *clicked_point,
Renderer *interactive_renderer)
{
+ int no_text = text_is_empty(message->ttext);
+ message->select_mode = MESSAGE_SELECT_LINE;
+ if (no_text || text_distance_from(message->ttext, clicked_point) == 0.0)
{
+ 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);
}
@@ -236,18 +260,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,10 +282,6 @@
Point *endpoints, p1, p2, px;
ArrowType arrow_type;
int n1 = 1, n2 = 0;
- utfchar *mname = NULL;
-#ifdef GTK_DOESNT_TALK_UTF8_WE_DO
- utfchar *utfstart, *utfend;
-#endif
assert(message != NULL);
assert(renderer != NULL);
@@ -318,37 +340,7 @@
renderer->ops->set_font(renderer, message_font,
MESSAGE_FONTHEIGHT);
-#ifdef GTK_DOESNT_TALK_UTF8_WE_DO
- utfstart = charconv_local8_to_utf8 (UML_STEREOTYPE_START);
- utfend = charconv_local8_to_utf8 (UML_STEREOTYPE_END);
- if (message->type==MESSAGE_CREATE)
- mname = g_strdup_printf ("%s%s%s", utfstart, "create", utfend);
- else if (message->type==MESSAGE_DESTROY)
- mname = g_strdup_printf ("%s%s%s", utfstart, "destroy", utfend);
-
- else
- mname = message->text;
- g_free (utfstart);
- g_free (utfend);
-#else
- 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;
-#endif
-
- 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);
}
@@ -363,6 +355,7 @@
LineBBExtras *extra;
Object *obj;
+ fprintf(stderr, "msgCreate\n");
if (message_font == NULL) {
/* choose default font name for your locale. see also font_data
structure
in lib/font.c. */
@@ -389,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;
@@ -412,6 +408,7 @@
{
connection_destroy(&message->connection);
+ text_destroy(message->ttext);
g_free(message->text);
}
@@ -425,22 +422,14 @@
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 =
- 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 - font_ascent(message_font,
MESSAGE_FONTHEIGHT);
- rect.bottom = rect.top + MESSAGE_FONTHEIGHT;
+ text_calc_boundingbox(message->ttext, &rect);
rectangle_union(&obj->bounding_box, &rect);
}
-
-
static Object *
message_load(ObjectNode obj_node, int version, const char *filename)
{
@@ -448,4 +437,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;
+}
--
+++ GMX - Mail, Messaging & more http://www.gmx.net +++
NEU: Mit GMX ins Internet. Rund um die Uhr für 1 ct/ Min. surfen!
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]