direct text input for UML-message



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]