diff -urNbB dia-0.93_orig/objects/UML/class.c dia-0.93/objects/UML/class.c --- dia-0.93_orig/objects/UML/class.c 2004-02-29 21:53:44.000000000 +0100 +++ dia-0.93/objects/UML/class.c 2004-05-13 11:58:21.000000000 +0200 @@ -121,6 +121,10 @@ N_("Visible Operations"), NULL, NULL }, { "visible_comments", PROP_TYPE_INT, PROP_FLAG_VISIBLE, N_("Visible Comments"), NULL, NULL }, + { "wrap_operations", PROP_TYPE_INT, PROP_FLAG_VISIBLE, + N_("Wrap Operations"), NULL, NULL }, + { "wrap_after_char", PROP_TYPE_INT, PROP_FLAG_VISIBLE, + N_("Wrap after char"), NULL, NULL }, { "attributes", PROP_TYPE_STRINGLIST, PROP_FLAG_DONT_SAVE, N_("Attributes"), NULL, NULL }, @@ -157,6 +161,8 @@ { "suppress_operations", PROP_TYPE_INT, offsetof(UMLClass , suppress_operations) }, { "visible_operations", PROP_TYPE_INT, offsetof(UMLClass , visible_operations) }, { "visible_comments", PROP_TYPE_INT, offsetof(UMLClass , visible_comments) }, + { "wrap_operations", PROP_TYPE_INT, offsetof(UMLClass , wrap_operations) }, + { "wrap_after_char", PROP_TYPE_INT, offsetof(UMLClass , wrap_after_char) }, { "operations", PROP_TYPE_STRINGLIST, offsetof(UMLClass , operations_strings) }, { "attributes", PROP_TYPE_STRINGLIST, offsetof(UMLClass , attributes_strings) }, @@ -436,6 +441,10 @@ p.x = x + UMLCLASS_BORDER/2.0 + 0.1; p.y = p1.y + 0.1; + int wrap_pos, last_wrap_pos, ident, wrapping_needed; + GList *wrapsublist = NULL; + gchar part_opstr[umlclass->max_wrapped_line_width]; + i = 0; list = umlclass->operations; while (list != NULL) { @@ -454,16 +463,56 @@ font = umlclass->normal_font; font_height = umlclass->font_height; } + + wrapping_needed = 0; opstr = (gchar*) g_list_nth(umlclass->operations_strings, i)->data; - ascent = dia_font_ascent(opstr, - font,font_height); - p.y += ascent; + if( umlclass->wrap_operations == TRUE) { + wrapsublist = (GList*)g_list_nth( umlclass->operations_wrappos, i)->data; + wrapping_needed = GPOINTER_TO_INT( wrapsublist->data); + } + ascent = dia_font_ascent(opstr, font, font_height); renderer_ops->set_font(renderer, font, font_height); + + if( umlclass->wrap_operations == TRUE && wrapping_needed) { + + wrapsublist = g_list_next( wrapsublist); + ident = GPOINTER_TO_INT( wrapsublist->data); + wrapsublist = g_list_next( wrapsublist); + wrap_pos = last_wrap_pos = 0; + + while( wrapsublist != NULL) { + + wrap_pos = GPOINTER_TO_INT( wrapsublist->data); + + if( last_wrap_pos == 0) { + strncpy( part_opstr, opstr, wrap_pos); + memset( part_opstr+wrap_pos, '\0', 1); + } else { + memset( part_opstr, ' ', ident); + memset( part_opstr+ident, '\0', 1); + strncat( part_opstr, opstr+last_wrap_pos, wrap_pos-last_wrap_pos); + } + + p.y += ascent; + + renderer_ops->draw_string(renderer, + part_opstr, + &p, ALIGN_LEFT, + ¨class->text_color); + + last_wrap_pos = wrap_pos; + wrapsublist = g_list_next( wrapsublist); + } + } else { + + p.y += ascent; + renderer_ops->draw_string(renderer, opstr, &p, ALIGN_LEFT, ¨class->text_color); + } if (op->class_scope) { p1 = p; @@ -787,7 +836,11 @@ umlclass->operationsbox_height = 2*0.1; + int pos_next_comma, pos_brace, wrap_pos, last_wrap_pos, ident, offset, maxlinewidth, length; + GList *sublist, *wrapsublist; + umlclass->operations_strings = NULL; + umlclass->operations_wrappos = NULL; if (0 != g_list_length(umlclass->operations)) { i = 0; list = umlclass->operations; @@ -798,6 +851,94 @@ umlclass->operations_strings = g_list_append(umlclass->operations_strings, opstr); + length = 0; + if( umlclass->wrap_operations == TRUE) { + + length = strlen( (const gchar*)opstr); + + sublist = NULL; + if( length > umlclass->wrap_after_char) { + + sublist = g_list_append( sublist, GINT_TO_POINTER( 1)); + + /* count maximal line width to create a secure buffer (part_opstr) + and build the sublist with the wrapping data for the current operation, which will be used by umlclass_draw(), too. + The content of the sublist is: + 1st element: (bool) wrapping needed or not, 2nd: indentation in chars, 3rd-last: absolute wrapping positions */ + pos_next_comma = pos_brace = wrap_pos = offset = maxlinewidth = umlclass->max_wrapped_line_width = 0; + while( wrap_pos + offset < length) { + + do { + pos_next_comma = strcspn( (const gchar*)opstr + wrap_pos + offset, ","); + wrap_pos += pos_next_comma + 1; + } + while( wrap_pos < umlclass->wrap_after_char - pos_brace && wrap_pos + offset < length); + + if( offset == 0) { + pos_brace = strcspn( opstr, "("); + sublist = g_list_append( sublist, GINT_TO_POINTER( pos_brace+1)); + } + sublist = g_list_append( sublist, GINT_TO_POINTER( wrap_pos + offset)); + + maxlinewidth = MAX(maxlinewidth, wrap_pos); + + offset += wrap_pos; + wrap_pos = 0; + } + umlclass->max_wrapped_line_width = MAX( umlclass->max_wrapped_line_width, maxlinewidth+1); + + gchar part_opstr[umlclass->max_wrapped_line_width]; + pos_next_comma = pos_brace = wrap_pos = offset = 0; + + wrapsublist = g_list_next( sublist); + ident = GPOINTER_TO_INT( wrapsublist->data); + wrapsublist = g_list_next( wrapsublist); + wrap_pos = last_wrap_pos = 0; + + while( wrapsublist != NULL) { + + wrap_pos = GPOINTER_TO_INT( wrapsublist->data); + + if( last_wrap_pos == 0) { + strncpy( part_opstr, opstr, wrap_pos); + memset( part_opstr+wrap_pos, '\0', 1); + } else { + memset( part_opstr, ' ', ident); + memset( part_opstr+ident, '\0', 1); + strncat( part_opstr, opstr+last_wrap_pos, wrap_pos-last_wrap_pos); + } + + if (op->inheritance_type == UML_ABSTRACT) { + width = dia_font_string_width(part_opstr, + umlclass->abstract_font, + umlclass->abstract_font_height); + umlclass->operationsbox_height += umlclass->abstract_font_height; + } else if (op->inheritance_type == UML_POLYMORPHIC) { + width = dia_font_string_width(part_opstr, + umlclass->polymorphic_font, + umlclass->polymorphic_font_height); + umlclass->operationsbox_height += umlclass->polymorphic_font_height; + } else { + width = dia_font_string_width(part_opstr, + umlclass->normal_font, + umlclass->font_height); + umlclass->operationsbox_height += umlclass->font_height; + } + + maxwidth = MAX(width, maxwidth); + last_wrap_pos = wrap_pos; + wrapsublist = g_list_next( wrapsublist); + } + + } else { + + sublist = g_list_append( sublist, GINT_TO_POINTER( 0)); + } + umlclass->operations_wrappos = g_list_append( umlclass->operations_wrappos, sublist); + } + + if( umlclass->wrap_operations == FALSE || !(length > umlclass->wrap_after_char)) { + if (op->inheritance_type == UML_ABSTRACT) { width = dia_font_string_width(opstr, umlclass->abstract_font, @@ -814,8 +955,11 @@ umlclass->font_height); umlclass->operationsbox_height += umlclass->font_height; } + maxwidth = MAX(width, maxwidth); + } + if (umlclass->visible_comments && op->comment != NULL && op->comment[0] != '\0') { width = dia_font_string_width(op->comment, umlclass->comment_font, @@ -953,6 +1097,9 @@ umlclass->visible_operations = TRUE; umlclass->visible_comments = FALSE; + umlclass->wrap_operations = TRUE; + umlclass->wrap_after_char = UMLCLASS_WRAP_AFTER_CHAR; + umlclass->attributes = NULL; umlclass->operations = NULL; @@ -963,6 +1110,7 @@ umlclass->stereotype_string = NULL; umlclass->attributes_strings = NULL; umlclass->operations_strings = NULL; + umlclass->operations_wrappos = NULL; umlclass->templates_strings = NULL; umlclass->text_color = color_black; @@ -1059,6 +1207,12 @@ umlclass->operations_strings = NULL; } + if (umlclass->operations_wrappos != NULL) { + g_list_foreach(umlclass->operations_wrappos, (GFunc)g_list_free, NULL); + g_list_free(umlclass->operations_wrappos); + umlclass->operations_wrappos = NULL; + } + if (umlclass->templates_strings != NULL) { for (i=0;inum_templates;i++) { g_free(umlclass->templates_strings[i]); @@ -1134,6 +1288,8 @@ newumlclass->visible_attributes = umlclass->visible_attributes; newumlclass->visible_operations = umlclass->visible_operations; newumlclass->visible_comments = umlclass->visible_comments; + newumlclass->wrap_operations = umlclass->wrap_operations; + newumlclass->wrap_after_char = umlclass->wrap_after_char; newumlclass->text_color = umlclass->text_color; newumlclass->line_color = umlclass->line_color; newumlclass->fill_color = umlclass->fill_color; @@ -1196,6 +1352,7 @@ newumlclass->stereotype_string = NULL; newumlclass->attributes_strings = NULL; newumlclass->operations_strings = NULL; + newumlclass->operations_wrappos = NULL; newumlclass->templates_strings = NULL; for (i=0;ivisible_operations); data_add_boolean(new_attribute(obj_node, "visible_comments"), umlclass->visible_comments); + data_add_boolean(new_attribute(obj_node, "wrap_operations"), + umlclass->wrap_operations); + data_add_int(new_attribute(obj_node, "wrap_after_char"), + umlclass->wrap_after_char); data_add_color(new_attribute(obj_node, "line_color"), ¨class->line_color); data_add_color(new_attribute(obj_node, "fill_color"), @@ -1402,6 +1563,16 @@ if (attr_node != NULL) umlclass->visible_comments = data_boolean(attribute_first_data(attr_node)); + umlclass->wrap_operations = TRUE; + attr_node = object_find_attribute(obj_node, "wrap_operations"); + if (attr_node != NULL) + umlclass->wrap_operations = data_boolean(attribute_first_data(attr_node)); + + umlclass->wrap_after_char = UMLCLASS_WRAP_AFTER_CHAR; + attr_node = object_find_attribute(obj_node, "wrap_after_char"); + if (attr_node != NULL) + umlclass->wrap_after_char = data_int(attribute_first_data(attr_node)); + umlclass->line_color = color_black; /* support the old name ... */ attr_node = object_find_attribute(obj_node, "foreground_color"); @@ -1559,6 +1730,7 @@ umlclass->stereotype_string = NULL; umlclass->attributes_strings = NULL; umlclass->operations_strings = NULL; + umlclass->operations_wrappos = NULL; umlclass->templates_strings = NULL; umlclass_calculate_data(umlclass); diff -urNbB dia-0.93_orig/objects/UML/class.h dia-0.93/objects/UML/class.h --- dia-0.93_orig/objects/UML/class.h 2004-02-29 21:55:14.000000000 +0100 +++ dia-0.93/objects/UML/class.h 2004-05-13 10:50:32.000000000 +0200 @@ -26,6 +26,7 @@ #include "uml.h" #define UMLCLASS_CONNECTIONPOINTS 8 +#define UMLCLASS_WRAP_AFTER_CHAR 40 typedef struct _UMLClass UMLClass; typedef struct _UMLClassDialog UMLClassDialog; @@ -61,6 +62,9 @@ int visible_operations; int visible_comments; + int wrap_operations; /* wrap operations with many parameters */ + int wrap_after_char; + Color line_color; Color fill_color; Color text_color; @@ -85,6 +89,8 @@ real operationsbox_height; GList *operations_strings; + GList **operations_wrappos; + int max_wrapped_line_width; real templates_height; real templates_width; @@ -114,6 +120,7 @@ GtkToggleButton *op_vis; GtkToggleButton *op_supp; GtkToggleButton *comments_vis; + GtkToggleButton *op_wrap; DiaFontSelector *normal_font; DiaFontSelector *abstract_font; DiaFontSelector *polymorphic_font; @@ -126,9 +133,11 @@ GtkSpinButton *classname_font_height; GtkSpinButton *abstract_classname_font_height; GtkSpinButton *comment_font_height; + GtkSpinButton *wrap_after_char; DiaColorSelector *text_color; DiaColorSelector *line_color; DiaColorSelector *fill_color; + GtkLabel *max_length_label; GList *disconnected_connections; GList *added_connections; diff -urNbB dia-0.93_orig/objects/UML/class_dialog.c dia-0.93/objects/UML/class_dialog.c --- dia-0.93_orig/objects/UML/class_dialog.c 2004-02-29 19:25:02.000000000 +0100 +++ dia-0.93/objects/UML/class_dialog.c 2004-05-13 11:50:59.000000000 +0200 @@ -149,6 +149,8 @@ umlclass->abstract = prop_dialog->abstract_class->active; umlclass->visible_attributes = prop_dialog->attr_vis->active; umlclass->visible_operations = prop_dialog->op_vis->active; + umlclass->wrap_operations = prop_dialog->op_wrap->active; + umlclass->wrap_after_char = gtk_spin_button_get_value_as_int(prop_dialog->wrap_after_char); umlclass->visible_comments = prop_dialog->comments_vis->active; umlclass->suppress_attributes = prop_dialog->attr_supp->active; umlclass->suppress_operations = prop_dialog->op_supp->active; @@ -193,6 +195,8 @@ gtk_toggle_button_set_active(prop_dialog->abstract_class, umlclass->abstract); gtk_toggle_button_set_active(prop_dialog->attr_vis, umlclass->visible_attributes); gtk_toggle_button_set_active(prop_dialog->op_vis, umlclass->visible_operations); + gtk_toggle_button_set_active(prop_dialog->op_wrap, umlclass->wrap_operations); + gtk_spin_button_set_value (prop_dialog->wrap_after_char, umlclass->wrap_after_char); gtk_toggle_button_set_active(prop_dialog->comments_vis, umlclass->visible_comments); gtk_toggle_button_set_active(prop_dialog->attr_supp, umlclass->suppress_attributes); gtk_toggle_button_set_active(prop_dialog->op_supp, umlclass->suppress_operations); @@ -245,6 +249,7 @@ GtkWidget *page_label; GtkWidget *label; GtkWidget *hbox; + GtkWidget *hbox2; GtkWidget *vbox; GtkWidget *entry; GtkWidget *checkbox; @@ -252,6 +257,7 @@ GtkWidget *fill_color; GtkWidget *line_color; GtkWidget *table; + GtkObject *adj; prop_dialog = umlclass->properties_dialog; @@ -310,6 +316,21 @@ gtk_box_pack_start (GTK_BOX (hbox), checkbox, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0); + hbox = gtk_hbox_new(TRUE, 5); + hbox2 = gtk_hbox_new(FALSE, 5); + checkbox = gtk_check_button_new_with_label(_("Wrap Operations")); + prop_dialog->op_wrap = GTK_TOGGLE_BUTTON( checkbox ); + gtk_box_pack_start (GTK_BOX (hbox), checkbox, TRUE, TRUE, 0); + adj = gtk_adjustment_new( umlclass->wrap_after_char, 0.0, 200.0, 1.0, 5.0, 1.0); + prop_dialog->wrap_after_char = GTK_SPIN_BUTTON(gtk_spin_button_new( GTK_ADJUSTMENT( adj), 0.1, 0)); + gtk_spin_button_set_numeric( GTK_SPIN_BUTTON( prop_dialog->wrap_after_char), TRUE); + gtk_spin_button_set_snap_to_ticks( GTK_SPIN_BUTTON( prop_dialog->wrap_after_char), TRUE); + prop_dialog->max_length_label = GTK_LABEL( gtk_label_new( "Wrap after this length: ")); + gtk_box_pack_start (GTK_BOX (hbox2), GTK_WIDGET( prop_dialog->max_length_label), FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox2), GTK_WIDGET( prop_dialog->wrap_after_char), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET( hbox2), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0); + hbox = gtk_hbox_new(FALSE, 5); checkbox = gtk_check_button_new_with_label(_("Comments visible")); prop_dialog->comments_vis = GTK_TOGGLE_BUTTON( checkbox );