[dia] uml: fix parameters editor



commit f77526bc8ab3aa6546ac3b553ea5fb5de73da395
Author: Zander Brown <zbrown gnome org>
Date:   Sat Oct 12 15:54:01 2019 +0100

    uml: fix parameters editor
    
    Fix the disappearing values problem by simply reimplementing around treeview instead of list
    
    Changes are now stored as they are made and the list better represents the current state
    
    DiaOptionMenu becomes a real class

 app/dia-guide-dialog.c                |   8 +-
 app/diapagelayout.c                   |   6 +-
 lib/diaoptionmenu.c                   | 143 ++++--
 lib/diaoptionmenu.h                   |  27 +-
 lib/widgets.c                         |  18 +-
 objects/UML/class.c                   |  10 +-
 objects/UML/class_attributes_dialog.c |  12 +-
 objects/UML/class_dialog.c            |  58 +--
 objects/UML/class_dialog.h            |  26 +-
 objects/UML/class_operations_dialog.c | 854 ++++++++++++++++++++--------------
 objects/UML/uml.h                     |  48 +-
 objects/UML/umloperation.c            |  93 ++--
 objects/UML/umlparameter.c            | 110 +++--
 13 files changed, 866 insertions(+), 547 deletions(-)
---
diff --git a/app/dia-guide-dialog.c b/app/dia-guide-dialog.c
index c9ff7278..382255c8 100644
--- a/app/dia-guide-dialog.c
+++ b/app/dia-guide-dialog.c
@@ -103,7 +103,7 @@ dia_guide_dialog_response (GtkDialog *dialog,
 
   if (response_id == GTK_RESPONSE_OK) {
     real position = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->position_entry));
-    int orientation = dia_option_menu_get_active (priv->orientation_menu);
+    int orientation = dia_option_menu_get_active (DIA_OPTION_MENU (priv->orientation_menu));
     dia_diagram_add_guide (priv->diagram, position, orientation, TRUE);
   }
 
@@ -174,9 +174,9 @@ dia_guide_dialog_init (DiaGuideDialog *self)
   priv->orientation_menu = dia_option_menu_new ();
   gtk_table_attach (GTK_TABLE (table), priv->orientation_menu, 1,2, 0,1,
                     GTK_FILL, GTK_FILL, 0, 0);
-  dia_option_menu_add_item (priv->orientation_menu, "Horizontal", GTK_ORIENTATION_HORIZONTAL);
-  dia_option_menu_add_item (priv->orientation_menu, "Vertical", GTK_ORIENTATION_VERTICAL);
-  dia_option_menu_set_active (priv->orientation_menu, GTK_ORIENTATION_HORIZONTAL);
+  dia_option_menu_add_item (DIA_OPTION_MENU (priv->orientation_menu), "Horizontal", 
GTK_ORIENTATION_HORIZONTAL);
+  dia_option_menu_add_item (DIA_OPTION_MENU (priv->orientation_menu), "Vertical", GTK_ORIENTATION_VERTICAL);
+  dia_option_menu_set_active (DIA_OPTION_MENU (priv->orientation_menu), GTK_ORIENTATION_HORIZONTAL);
   gtk_widget_show (priv->orientation_menu);
 
   label = gtk_label_new (_("Position"));
diff --git a/app/diapagelayout.c b/app/diapagelayout.c
index 23a295c5..5b35e40d 100644
--- a/app/diapagelayout.c
+++ b/app/diapagelayout.c
@@ -166,7 +166,7 @@ dia_page_layout_init(DiaPageLayout *self)
   for (i = 0; paper_names != NULL;
        i++, paper_names = g_list_next(paper_names)) {
 
-    dia_option_menu_add_item (self->paper_size, paper_names->data, i);
+    dia_option_menu_add_item (DIA_OPTION_MENU (self->paper_size), paper_names->data, i);
   }
   gtk_widget_show(self->paper_size);
 
@@ -386,7 +386,7 @@ dia_page_layout_set_paper(DiaPageLayout *self, const gchar *paper)
   i = find_paper(paper);
   if (i == -1)
     i = find_paper(prefs.new_diagram.papertype);
-  dia_option_menu_set_active (self->paper_size, i);
+  dia_option_menu_set_active (DIA_OPTION_MENU (self->paper_size), i);
 }
 
 void
@@ -721,7 +721,7 @@ paper_size_change (GtkWidget *widget, DiaPageLayout *self)
 
   gtk_widget_get_allocation (self->darea, &alloc);
 
-  self->papernum = dia_option_menu_get_active (widget);
+  self->papernum = dia_option_menu_get_active (DIA_OPTION_MENU (widget));
   size_page (self, &alloc);
   gtk_widget_queue_draw (self->darea);
 
diff --git a/lib/diaoptionmenu.c b/lib/diaoptionmenu.c
index 1201e0c8..71860a2f 100644
--- a/lib/diaoptionmenu.c
+++ b/lib/diaoptionmenu.c
@@ -26,91 +26,152 @@
 
 #include "diaoptionmenu.h"
 
+/**
+ * SECTION:diaoptionmenu
+ * @title: DiaOptionMenu
+ * @short_description: name -> value selector
+ *
+ * GtkOptionMenu replacement specialized for Dia's use
+ * of name (menu entry) to value (int)
+ *
+ * #GtkComboBox is an implementation detail, use of anything other than the
+ * #GtkComboBox:changed signal is undefined behaviour
+ */
+
+
+typedef struct _DiaOptionMenuPrivate DiaOptionMenuPrivate;
+struct _DiaOptionMenuPrivate {
+  GtkListStore *model;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (DiaOptionMenu, dia_option_menu, GTK_TYPE_COMBO_BOX)
+
 enum {
   COL_NAME = 0,
   COL_VALUE,
   COL_N_COLS
 };
 
-/*!
- * GtkOptionMenu replacement specialized for Dia's use
- * of name (menu entry) to value (int)
- */
-GtkWidget *
-dia_option_menu_new (void)
+
+static void
+dia_option_menu_class_init (DiaOptionMenuClass *klass)
 {
-  GtkWidget *combo_box;
-  GtkListStore *model = gtk_list_store_new (COL_N_COLS, G_TYPE_STRING, G_TYPE_INT);
+
+}
+
+
+static void
+dia_option_menu_init (DiaOptionMenu *self)
+{
+  DiaOptionMenuPrivate *priv = dia_option_menu_get_instance_private (self);
   GtkCellRenderer *cell;
 
-  combo_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (model));
+  priv->model = gtk_list_store_new (COL_N_COLS, G_TYPE_STRING, G_TYPE_INT);
+
+  gtk_combo_box_set_model (GTK_COMBO_BOX (self), GTK_TREE_MODEL (priv->model));
 
   cell = gtk_cell_renderer_text_new ();
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), cell, TRUE);
-  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), cell,
-                                  "text", 0,
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), cell, TRUE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self), cell,
+                                  "text", COL_NAME,
                                   NULL);
+}
+
 
-  return combo_box;
+GtkWidget *
+dia_option_menu_new (void)
+{
+  return g_object_new (DIA_TYPE_OPTION_MENU, NULL);
 }
 
-/*!
+
+/**
+ * dia_option_menu_add_item:
+ * @self: the #DiaOptionMenu
+ * @name: the item name
+ * @value: the item value
+ *
  * Convenient form of gtk_menu_append and more
  */
 void
-dia_option_menu_add_item (GtkWidget *widget, const char *name, int value)
+dia_option_menu_add_item (DiaOptionMenu *self,
+                          const char    *name,
+                          int            value)
 {
-  GtkComboBox  *combo_box = GTK_COMBO_BOX (widget);
-  GtkTreeModel *model = gtk_combo_box_get_model (combo_box);
+  DiaOptionMenuPrivate *priv;
   GtkTreeIter iter;
 
-  gtk_list_store_append (GTK_LIST_STORE (model), &iter);
-  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                     COL_NAME, name,
-                     COL_VALUE, value,
-                     -1);
+  g_return_if_fail (DIA_IS_OPTION_MENU (self));
+
+  priv = dia_option_menu_get_instance_private (self);
+
+  gtk_list_store_append (priv->model, &iter);
+  gtk_list_store_set (priv->model, &iter,
+                      COL_NAME, name,
+                      COL_VALUE, value,
+                      -1);
 }
 
-/*!
+
+/**
+ * dia_option_menu_set_active:
+ * @self: the #DiaOptionMenu
+ * @active: the new value
+ *
  * drop in replacement gtk_option_menu_set_history
  */
 void
-dia_option_menu_set_active (GtkWidget *widget, int active)
+dia_option_menu_set_active (DiaOptionMenu *self, int active)
 {
-  GtkComboBox  *combo_box = GTK_COMBO_BOX (widget);
-  GtkTreeModel *model = gtk_combo_box_get_model (combo_box);
+  DiaOptionMenuPrivate *priv;
   GtkTreeIter iter;
 
-  if (!gtk_tree_model_get_iter_first (model, &iter)) {
-    g_warning ("Empty DiaOptionMenu?");
-    return;
-  }
+  g_return_if_fail (DIA_IS_OPTION_MENU (self));
+
+  priv = dia_option_menu_get_instance_private (self);
+
+  g_return_if_fail (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->model), &iter));
+
   do {
     int value;
-    gtk_tree_model_get (model, &iter, COL_VALUE, &value, -1);
+    gtk_tree_model_get (GTK_TREE_MODEL (priv->model),
+                        &iter,
+                        COL_VALUE, &value,
+                        -1);
     if (active == value) {
-      gtk_combo_box_set_active_iter (combo_box, &iter);
+      gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter);
       break;
     }
-  } while (gtk_tree_model_iter_next (model, &iter));
+  } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->model), &iter));
 }
 
-/*!
+
+/**
+ * dia_option_menu_get_active
+ * @self: the #DiaOptionMenu
+ *
  * drop in replacement gtk_option_menu_get_history
  */
 int
-dia_option_menu_get_active (GtkWidget *widget)
+dia_option_menu_get_active (DiaOptionMenu *self)
 {
-  GtkComboBox  *combo_box = GTK_COMBO_BOX (widget);
-  GtkTreeModel *model = gtk_combo_box_get_model (combo_box);
+  DiaOptionMenuPrivate *priv;
   GtkTreeIter iter;
 
-  if (gtk_combo_box_get_active_iter  (combo_box, &iter)) {
+  g_return_val_if_fail (DIA_IS_OPTION_MENU (self), -1);
+
+  priv = dia_option_menu_get_instance_private (self);
+
+  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self), &iter)) {
     int value;
 
-    gtk_tree_model_get (model, &iter, COL_VALUE, &value, -1);
+    gtk_tree_model_get (GTK_TREE_MODEL (priv->model),
+                        &iter,
+                        COL_VALUE, &value,
+                        -1);
+
     return value;
   }
-  g_warning ("DiaOptionMenu: no selection");
-  return 0;
+
+  g_return_val_if_reached (-1);
 }
diff --git a/lib/diaoptionmenu.h b/lib/diaoptionmenu.h
index a1136311..933bdb8e 100644
--- a/lib/diaoptionmenu.h
+++ b/lib/diaoptionmenu.h
@@ -18,9 +18,28 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
+
+#pragma once
+
 #include <gtk/gtk.h>
 
-GtkWidget *dia_option_menu_new (void);
-void dia_option_menu_add_item (GtkWidget *widget, const char *name, int value);
-void dia_option_menu_set_active (GtkWidget *widget, int active);
-int  dia_option_menu_get_active (GtkWidget *widget);
+G_BEGIN_DECLS
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkComboBox, g_object_unref)
+
+#define DIA_TYPE_OPTION_MENU dia_option_menu_get_type ()
+G_DECLARE_DERIVABLE_TYPE (DiaOptionMenu, dia_option_menu, DIA, OPTION_MENU, GtkComboBox)
+
+struct _DiaOptionMenuClass {
+  GtkComboBoxClass parent;
+};
+
+GtkWidget *dia_option_menu_new        (void);
+void       dia_option_menu_add_item   (DiaOptionMenu *self,
+                                       const char    *name,
+                                       int            value);
+void       dia_option_menu_set_active (DiaOptionMenu *self,
+                                       int            active);
+int        dia_option_menu_get_active (DiaOptionMenu *self);
+
+G_END_DECLS
diff --git a/lib/widgets.c b/lib/widgets.c
index 141a3032..f78d9d0a 100644
--- a/lib/widgets.c
+++ b/lib/widgets.c
@@ -260,30 +260,36 @@ dia_size_selector_get_size(DiaSizeSelector *ss, real *width, real *height)
 }
 
 /************* DiaAlignmentSelector: ***************/
+
+
 GtkWidget *
 dia_alignment_selector_new ()
 {
   GtkWidget *omenu = dia_option_menu_new ();
-  dia_option_menu_add_item(omenu, _("Left"), ALIGN_LEFT);
-  dia_option_menu_add_item(omenu, _("Center"), ALIGN_CENTER);
-  dia_option_menu_add_item(omenu, _("Right"), ALIGN_RIGHT);
+
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Left"), ALIGN_LEFT);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Center"), ALIGN_CENTER);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Right"), ALIGN_RIGHT);
 
   return omenu;
 }
 
+
 Alignment
 dia_alignment_selector_get_alignment(GtkWidget *as)
 {
-  return (Alignment)dia_option_menu_get_active (GTK_WIDGET (as));
+  return (Alignment) dia_option_menu_get_active (DIA_OPTION_MENU (as));
 }
 
+
 void
 dia_alignment_selector_set_alignment (GtkWidget *as,
-                                     Alignment align)
+                                      Alignment  align)
 {
-  dia_option_menu_set_active (GTK_WIDGET (as), align);
+  dia_option_menu_set_active (DIA_OPTION_MENU (as), align);
 }
 
+
 /************* DiaFileSelector: ***************/
 struct _DiaFileSelector
 {
diff --git a/objects/UML/class.c b/objects/UML/class.c
index 7b06e828..6c0508ee 100644
--- a/objects/UML/class.c
+++ b/objects/UML/class.c
@@ -1967,12 +1967,12 @@ umlclass_destroy(UMLClass *umlclass)
   list = umlclass->operations;
   while (list != NULL) {
     op = (UMLOperation *)list->data;
-    g_free(op->left_connection);
-    g_free(op->right_connection);
-    uml_operation_destroy(op);
-    list = g_list_next(list);
+    g_free (op->left_connection);
+    g_free (op->right_connection);
+    uml_operation_free (op);
+    list = g_list_next (list);
   }
-  g_list_free(umlclass->operations);
+  g_list_free (umlclass->operations);
 
   list = umlclass->formal_params;
   while (list != NULL) {
diff --git a/objects/UML/class_attributes_dialog.c b/objects/UML/class_attributes_dialog.c
index 49404719..dac7bed1 100644
--- a/objects/UML/class_attributes_dialog.c
+++ b/objects/UML/class_attributes_dialog.c
@@ -58,7 +58,7 @@ attributes_set_values(UMLClassDialog *prop_dialog, UMLAttribute *attr)
     _class_set_comment(prop_dialog->attr_comment, "");
 
 
-  dia_option_menu_set_active(prop_dialog->attr_visible, attr->visibility);
+  dia_option_menu_set_active (DIA_OPTION_MENU (prop_dialog->attr_visible), attr->visibility);
   gtk_toggle_button_set_active(prop_dialog->attr_class_scope, attr->class_scope);
 }
 
@@ -86,7 +86,7 @@ attributes_get_values (UMLClassDialog *prop_dialog, UMLAttribute *attr)
   attr->value = g_strdup (gtk_entry_get_text(prop_dialog->attr_value));
   attr->comment = g_strdup (_class_get_comment(prop_dialog->attr_comment));
 
-  attr->visibility = (UMLVisibility)dia_option_menu_get_active (prop_dialog->attr_visible);
+  attr->visibility = (UMLVisibility) dia_option_menu_get_active (DIA_OPTION_MENU 
(prop_dialog->attr_visible));
 
   attr->class_scope = gtk_toggle_button_get_active (prop_dialog->attr_class_scope);
 }
@@ -574,10 +574,10 @@ _attributes_create_page(GtkNotebook *notebook,  UMLClass *umlclass)
   prop_dialog->attr_visible = omenu = dia_option_menu_new ();
   g_signal_connect (G_OBJECT (omenu), "changed",
                    G_CALLBACK (attributes_update), umlclass);
-  dia_option_menu_add_item(omenu, _("Public"), UML_PUBLIC);
-  dia_option_menu_add_item(omenu, _("Private"), UML_PRIVATE);
-  dia_option_menu_add_item(omenu, _("Protected"), UML_PROTECTED);
-  dia_option_menu_add_item(omenu, _("Implementation"), UML_IMPLEMENTATION);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Public"), UML_PUBLIC);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Private"), UML_PRIVATE);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Protected"), UML_PROTECTED);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Implementation"), UML_IMPLEMENTATION);
 
   {
     GtkWidget * align;
diff --git a/objects/UML/class_dialog.c b/objects/UML/class_dialog.c
index 35b03dba..8f14c4de 100644
--- a/objects/UML/class_dialog.c
+++ b/objects/UML/class_dialog.c
@@ -689,7 +689,7 @@ umlclass_get_properties(UMLClass *umlclass, gboolean is_default)
   umlclass_sanity_check(umlclass, "Get properties start");
 #endif
   if (umlclass->properties_dialog == NULL) {
-    prop_dialog = g_new(UMLClassDialog, 1);
+    prop_dialog = g_new0 (UMLClassDialog, 1);
     umlclass->properties_dialog = prop_dialog;
 
     vbox = gtk_vbox_new(FALSE, 0);
@@ -698,7 +698,6 @@ umlclass_get_properties(UMLClass *umlclass, gboolean is_default)
 
     prop_dialog->current_attr = NULL;
     prop_dialog->current_op = NULL;
-    prop_dialog->current_param = NULL;
     prop_dialog->current_templ = NULL;
     prop_dialog->deleted_connections = NULL;
     prop_dialog->added_connections = NULL;
@@ -711,13 +710,17 @@ umlclass_get_properties(UMLClass *umlclass, gboolean is_default)
 
     g_object_set_data(G_OBJECT(notebook), "user_data", (gpointer) umlclass);
 
-    g_signal_connect (G_OBJECT (notebook), "switch_page",
-                     G_CALLBACK(switch_page_callback), umlclass);
-    g_signal_connect (G_OBJECT (umlclass->properties_dialog->dialog), "destroy",
-                     G_CALLBACK(destroy_properties_dialog), umlclass);
-
     create_dialog_pages(GTK_NOTEBOOK( notebook ), umlclass);
 
+    g_signal_connect (G_OBJECT (notebook),
+                      "switch-page",
+                      G_CALLBACK (switch_page_callback),
+                      umlclass);
+    g_signal_connect (G_OBJECT (umlclass->properties_dialog->dialog),
+                      "destroy",
+                      G_CALLBACK (destroy_properties_dialog),
+                      umlclass);
+
     gtk_widget_show (notebook);
   }
 
@@ -753,12 +756,7 @@ umlclass_free_state(UMLClassState *state)
   }
   g_list_free(state->attributes);
 
-  list = state->operations;
-  while (list) {
-    uml_operation_destroy((UMLOperation *) list->data);
-    list = g_list_next(list);
-  }
-  g_list_free(state->operations);
+  g_list_free_full (state->operations, (GDestroyNotify) uml_operation_free);
 
   list = state->formal_params;
   while (list) {
@@ -1090,29 +1088,37 @@ new_umlclass_change(UMLClass *obj, UMLClassState *saved_state,
 /*
         get the contents of a comment text view.
 */
-const gchar *
-_class_get_comment(GtkTextView *view)
+gchar *
+_class_get_comment (GtkTextView *view)
 {
   GtkTextBuffer * buffer = gtk_text_view_get_buffer(view);
   GtkTextIter start;
   GtkTextIter end;
 
-  gtk_text_buffer_get_start_iter(buffer, &start);
-  gtk_text_buffer_get_end_iter(buffer, &end);
+  gtk_text_buffer_get_start_iter (buffer, &start);
+  gtk_text_buffer_get_end_iter (buffer, &end);
 
-  return gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+  return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
 }
 
-void
-_class_set_comment(GtkTextView *view, gchar *text)
+
+char *
+buffer_get_text (GtkTextBuffer *buffer)
 {
-  GtkTextBuffer * buffer = gtk_text_view_get_buffer(view);
   GtkTextIter start;
   GtkTextIter end;
 
-  gtk_text_buffer_get_start_iter(buffer, &start);
-  gtk_text_buffer_get_end_iter(buffer, &end);
-  gtk_text_buffer_delete(buffer,&start,&end);
-  gtk_text_buffer_get_start_iter(buffer, &start);
-  gtk_text_buffer_insert( buffer, &start, text, strlen(text));
+  gtk_text_buffer_get_start_iter (buffer, &start);
+  gtk_text_buffer_get_end_iter (buffer, &end);
+
+  return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+}
+
+
+void
+_class_set_comment(GtkTextView *view, gchar *text)
+{
+  GtkTextBuffer * buffer = gtk_text_view_get_buffer (view);
+
+  gtk_text_buffer_set_text (buffer, text, -1);
 }
diff --git a/objects/UML/class_dialog.h b/objects/UML/class_dialog.h
index 919d0b52..341a264a 100644
--- a/objects/UML/class_dialog.h
+++ b/objects/UML/class_dialog.h
@@ -2,7 +2,7 @@
 /**
  * \brief Very special user interface for UMLClass parametrization
  *
- * There is a (too) tight coupling between the UMLClass and it's user interface. 
+ * There is a (too) tight coupling between the UMLClass and it's user interface.
  * And the dialog is too huge in code as well as on screen.
  */
 struct _UMLClassDialog {
@@ -31,7 +31,7 @@ struct _UMLClassDialog {
   GtkSpinButton *classname_font_height;
   GtkSpinButton *abstract_classname_font_height;
   GtkSpinButton *comment_font_height;
-  GtkSpinButton *wrap_after_char;  
+  GtkSpinButton *wrap_after_char;
   GtkSpinButton *comment_line_length;
   GtkToggleButton *comment_tagging;
   GtkSpinButton *line_width;
@@ -42,8 +42,8 @@ struct _UMLClassDialog {
   GtkLabel *Comment_length_label;
 
   GList *disconnected_connections;
-  GList *added_connections; 
-  GList *deleted_connections; 
+  GList *added_connections;
+  GList *deleted_connections;
 
   GtkList *attributes_list;
   GtkListItem *current_attr;
@@ -53,7 +53,7 @@ struct _UMLClassDialog {
   GtkTextView *attr_comment;
   GtkWidget *attr_visible;
   GtkToggleButton *attr_class_scope;
-  
+
   GtkList *operations_list;
   GtkListItem *current_op;
   GtkEntry *op_name;
@@ -64,20 +64,23 @@ struct _UMLClassDialog {
   GtkWidget *op_visible;
   GtkToggleButton *op_class_scope;
   GtkWidget *op_inheritance_type;
-  GtkToggleButton *op_query;  
-  
-  GtkList *parameters_list;
-  GtkListItem *current_param;
+  GtkToggleButton *op_query;
+
+  GtkWidget *parameters;
+  GtkListStore *parameters_store;
+
   GtkEntry *param_name;
   GtkEntry *param_type;
   GtkEntry *param_value;
   GtkTextView *param_comment;
   GtkWidget *param_kind;
+  GtkTextBuffer *param_comment_buffer;
+
   GtkWidget *param_new_button;
   GtkWidget *param_delete_button;
   GtkWidget *param_up_button;
   GtkWidget *param_down_button;
-  
+
   GtkList *templates_list;
   GtkListItem *current_templ;
   GtkToggleButton *templ_template;
@@ -87,8 +90,9 @@ struct _UMLClassDialog {
 
 void _umlclass_store_disconnects(UMLClassDialog *prop_dialog, ConnectionPoint *cp);
 
-const gchar *_class_get_comment(GtkTextView *);
+gchar *_class_get_comment(GtkTextView *);
 void _class_set_comment(GtkTextView *, gchar *);
+char *buffer_get_text (GtkTextBuffer *buffer);
 
 void _attributes_get_current_values(UMLClassDialog *prop_dialog);
 void _operations_get_current_values(UMLClassDialog *prop_dialog);
diff --git a/objects/UML/class_operations_dialog.c b/objects/UML/class_operations_dialog.c
index 1cb12b40..83be47d8 100644
--- a/objects/UML/class_operations_dialog.c
+++ b/objects/UML/class_operations_dialog.c
@@ -31,6 +31,13 @@
  ******************** OPERATIONS *****************************
  *************************************************************/
 
+enum {
+  COL_PARAM_TITLE,
+  COL_PARAM_PARAM,
+  N_PARAM_COLS
+};
+
+
 static void
 parameters_set_sensitive(UMLClassDialog *prop_dialog, gint val)
 {
@@ -41,273 +48,202 @@ parameters_set_sensitive(UMLClassDialog *prop_dialog, gint val)
   gtk_widget_set_sensitive(GTK_WIDGET(prop_dialog->param_kind), val);
 }
 
-static void
-parameters_set_values(UMLClassDialog *prop_dialog, UMLParameter *param)
-{
-  gtk_entry_set_text(prop_dialog->param_name, param->name);
-  gtk_entry_set_text(prop_dialog->param_type, param->type);
-  if (param->value != NULL)
-    gtk_entry_set_text(prop_dialog->param_value, param->value);
-  else
-    gtk_entry_set_text(prop_dialog->param_value, "");
-  if (param->comment != NULL)
-    _class_set_comment(prop_dialog->param_comment, param->comment);
-  else
-    _class_set_comment(prop_dialog->param_comment, "");
-
-  dia_option_menu_set_active(prop_dialog->param_kind, param->kind);
-}
 
 static void
-parameters_clear_values(UMLClassDialog *prop_dialog)
+parameters_set_values (UMLClassDialog *prop_dialog,
+                       UMLParameter   *param)
 {
-  gtk_entry_set_text(prop_dialog->param_name, "");
-  gtk_entry_set_text(prop_dialog->param_type, "");
-  gtk_entry_set_text(prop_dialog->param_value, "");
-  _class_set_comment(prop_dialog->param_comment, "");
-  dia_option_menu_set_active(prop_dialog->param_kind, UML_UNDEF_KIND);
-
+  gtk_entry_set_text (prop_dialog->param_name, param->name? param->name : "");
+  gtk_entry_set_text (prop_dialog->param_type, param->type? param->type : "");
+  gtk_entry_set_text (prop_dialog->param_value, param->value? param->value : "");
+  gtk_text_buffer_set_text (prop_dialog->param_comment_buffer,
+                            param->comment? g_strdup (param->comment) : "",
+                            -1);
+
+  dia_option_menu_set_active (DIA_OPTION_MENU (prop_dialog->param_kind),
+                              param->kind);
 }
 
-static void
-parameters_get_values (UMLClassDialog *prop_dialog, UMLParameter *param)
-{
-  g_free(param->name);
-  g_free(param->type);
-  g_free(param->comment);
-  if (param->value != NULL)
-    g_free(param->value);
-
-  param->name = g_strdup (gtk_entry_get_text (prop_dialog->param_name));
-  param->type = g_strdup (gtk_entry_get_text (prop_dialog->param_type));
-
-  param->value = g_strdup (gtk_entry_get_text(prop_dialog->param_value));
-  param->comment = g_strdup (_class_get_comment(prop_dialog->param_comment));
-
-  param->kind = (UMLParameterKind) dia_option_menu_get_active(prop_dialog->param_kind);
-}
 
 static void
-parameters_get_current_values(UMLClassDialog *prop_dialog)
+parameters_clear_values (UMLClassDialog *prop_dialog)
 {
-  UMLParameter *current_param;
-  GtkLabel *label;
-  char *new_str;
-
-  if (prop_dialog->current_param != NULL) {
-    current_param = (UMLParameter *)
-      g_object_get_data(G_OBJECT(prop_dialog->current_param), "user_data");
-    if (current_param != NULL) {
-      parameters_get_values(prop_dialog, current_param);
-      label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(prop_dialog->current_param)));
-      new_str = uml_get_parameter_string(current_param);
-      gtk_label_set_text(label, new_str);
-      g_free(new_str);
-    }
-  }
+  gtk_entry_set_text (prop_dialog->param_name, "");
+  gtk_entry_set_text (prop_dialog->param_type, "");
+  gtk_entry_set_text (prop_dialog->param_value, "");
+  gtk_text_buffer_set_text (prop_dialog->param_comment_buffer, "", -1);
+  dia_option_menu_set_active (DIA_OPTION_MENU (prop_dialog->param_kind),
+                              UML_UNDEF_KIND);
 }
 
 
-static void
-parameters_list_selection_changed_callback(GtkWidget *gtklist,
-                                          UMLClass *umlclass)
+static gboolean
+add_to_list (GtkTreeModel *model,
+             GtkTreePath *path,
+             GtkTreeIter *iter,
+             gpointer data)
 {
-  GList *list;
-  UMLClassDialog *prop_dialog;
-  GObject *list_item;
-  UMLParameter *param;
+  UMLOperation *op = data;
+  UMLParameter *param = NULL;
 
-  prop_dialog = umlclass->properties_dialog;
+  // Don't free param, transfering to the list
+  gtk_tree_model_get (model, iter, COL_PARAM_PARAM, &param, -1);
 
-  if (!prop_dialog)
-    return; /* maybe hiding a bug elsewhere */
+  op->parameters = g_list_append (op->parameters, uml_parameter_ref (param));
 
-  parameters_get_current_values(prop_dialog);
+  return FALSE;
+}
 
-  list = GTK_LIST(gtklist)->selection;
-  if (!list) { /* No selected */
-    parameters_set_sensitive(prop_dialog, FALSE);
-    parameters_clear_values(prop_dialog);
-    prop_dialog->current_param = NULL;
-    return;
-  }
 
-  list_item = G_OBJECT(list->data);
-  param = (UMLParameter *)g_object_get_data(G_OBJECT(list_item), "user_data");
-  parameters_set_values(prop_dialog, param);
-  parameters_set_sensitive(prop_dialog, TRUE);
+static void
+sync_params_to_operation (GtkTreeModel *model,
+                          UMLOperation *op)
+{
+  g_list_free_full (op->parameters, (GDestroyNotify) uml_parameter_unref);
+  op->parameters = NULL;
 
-  prop_dialog->current_param = GTK_LIST_ITEM(list_item);
-  gtk_widget_grab_focus(GTK_WIDGET(prop_dialog->param_name));
+  gtk_tree_model_foreach (model, add_to_list, op);
 }
 
+
 static void
-parameters_list_new_callback(GtkWidget *button,
-                            UMLClass *umlclass)
+parameters_list_new_callback (GtkWidget *button,
+                              UMLClass  *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
-  GtkWidget *list_item;
   UMLOperation *current_op;
   UMLParameter *param;
   char *utf;
+  GtkTreeIter iter;
+  GtkTreeSelection *selection;
 
   prop_dialog = umlclass->properties_dialog;
 
-  parameters_get_current_values(prop_dialog);
-
   current_op = (UMLOperation *)
-    g_object_get_data(G_OBJECT(prop_dialog->current_op), "user_data");
+    g_object_get_data (G_OBJECT (prop_dialog->current_op), "user_data");
 
-  param = uml_parameter_new();
+  param = uml_parameter_new ();
 
-  utf = uml_get_parameter_string (param);
-  list_item = gtk_list_item_new_with_label (utf);
-  gtk_widget_show (list_item);
-  g_free (utf);
+  utf = uml_parameter_get_string (param);
 
-  g_object_set_data(G_OBJECT(list_item), "user_data", param);
+  gtk_list_store_append (prop_dialog->parameters_store, &iter);
+  gtk_list_store_set (prop_dialog->parameters_store,
+                      &iter,
+                      COL_PARAM_TITLE, utf,
+                      COL_PARAM_PARAM, param,
+                      -1);
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
+  gtk_tree_selection_select_iter (selection, &iter);
 
-  current_op->parameters = g_list_append(current_op->parameters,
-                                        (gpointer) param);
+  sync_params_to_operation (GTK_TREE_MODEL (prop_dialog->parameters_store),
+                            current_op);
 
-  list = g_list_append(NULL, list_item);
-  gtk_list_append_items(prop_dialog->parameters_list, list);
-
-  if (prop_dialog->parameters_list->children != NULL)
-    gtk_list_unselect_child(prop_dialog->parameters_list,
-                           GTK_WIDGET(prop_dialog->parameters_list->children->data));
-  gtk_list_select_child(prop_dialog->parameters_list, list_item);
-
-  prop_dialog->current_param = GTK_LIST_ITEM(list_item);
+  g_clear_pointer (&utf, g_free);
+  g_clear_pointer (&param, uml_parameter_unref);
 }
 
+
 static void
-parameters_list_delete_callback(GtkWidget *button,
-                               UMLClass *umlclass)
+parameters_list_delete_callback (GtkWidget *button,
+                                 UMLClass  *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
-  GtkList *gtklist;
   UMLOperation *current_op;
   UMLParameter *param;
+  GtkTreeIter iter;
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
 
   prop_dialog = umlclass->properties_dialog;
-  gtklist = GTK_LIST(prop_dialog->parameters_list);
 
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    gtk_tree_model_get (model, &iter, COL_PARAM_PARAM, &param, -1);
 
-  if (gtklist->selection != NULL) {
     /* Remove from current operations parameter list: */
     current_op = (UMLOperation *)
-      g_object_get_data(G_OBJECT(prop_dialog->current_op), "user_data");
-    param = (UMLParameter *)
-      g_object_get_data(G_OBJECT(prop_dialog->current_param), "user_data");
-
-    current_op->parameters = g_list_remove(current_op->parameters,
-                                          (gpointer) param);
-    uml_parameter_destroy(param);
+      g_object_get_data (G_OBJECT (prop_dialog->current_op), "user_data");
 
-    /* Remove from gtk list: */
-    list = g_list_prepend(NULL, prop_dialog->current_param);
+    gtk_list_store_remove (prop_dialog->parameters_store, &iter);
 
-    prop_dialog->current_param = NULL;
+    sync_params_to_operation (model, current_op);
 
-    gtk_list_remove_items(gtklist, list);
-    g_list_free(list);
+    g_clear_pointer (&param, uml_parameter_unref);
   }
 }
 
+
 static void
-parameters_list_move_up_callback(GtkWidget *button,
-                                UMLClass *umlclass)
+parameters_list_move_up_callback (GtkWidget *button,
+                                  UMLClass  *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
-  GtkList *gtklist;
-  GtkWidget *list_item;
   UMLOperation *current_op;
-  UMLParameter *param;
-  int i;
+  GtkTreeIter iter;
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
 
   prop_dialog = umlclass->properties_dialog;
-  gtklist = GTK_LIST(prop_dialog->parameters_list);
 
-  if (gtklist->selection != NULL) {
-    list_item = GTK_WIDGET(gtklist->selection->data);
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
+    GtkTreeIter prev;
 
-    i = gtk_list_child_position(gtklist, list_item);
-    if (i>0)
-      i--;
+    if (path != NULL && gtk_tree_path_prev (path)
+        && gtk_tree_model_get_iter (model, &prev, path)) {
+      gtk_list_store_move_before (prop_dialog->parameters_store, &iter, &prev);
+    } else {
+      gtk_list_store_move_before (prop_dialog->parameters_store, &iter, NULL);
+    }
+    gtk_tree_path_free (path);
 
-    param = (UMLParameter *) g_object_get_data(G_OBJECT(list_item), "user_data");
+    gtk_tree_selection_select_iter (selection, &iter);
 
     /* Move parameter in current operations list: */
     current_op = (UMLOperation *)
-      g_object_get_data(G_OBJECT(prop_dialog->current_op), "user_data");
-
-    current_op->parameters = g_list_remove(current_op->parameters,
-                                          (gpointer) param);
-    current_op->parameters = g_list_insert(current_op->parameters,
-                                          (gpointer) param,
-                                          i);
+      g_object_get_data (G_OBJECT (prop_dialog->current_op), "user_data");
 
-    /* Move parameter in gtk list: */
-    g_object_ref(list_item);
-    list = g_list_prepend(NULL, list_item);
-    gtk_list_remove_items(gtklist, list);
-    gtk_list_insert_items(gtklist, list, i);
-    g_object_unref(list_item);
-
-    gtk_list_select_child(gtklist, list_item);
-
-    _operations_get_current_values(prop_dialog);
+    sync_params_to_operation (model, current_op);
   }
 }
 
 static void
-parameters_list_move_down_callback(GtkWidget *button,
-                                  UMLClass *umlclass)
+parameters_list_move_down_callback (GtkWidget *button,
+                                    UMLClass  *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
-  GtkList *gtklist;
-  GtkWidget *list_item;
   UMLOperation *current_op;
-  UMLParameter *param;
-  int i;
+  GtkTreeIter iter;
+  GtkTreeSelection *selection;
+  GtkTreeModel *model;
 
   prop_dialog = umlclass->properties_dialog;
-  gtklist = GTK_LIST(prop_dialog->parameters_list);
 
-  if (gtklist->selection != NULL) {
-    list_item = GTK_WIDGET(gtklist->selection->data);
-
-    i = gtk_list_child_position(gtklist, list_item);
-    if (i<(g_list_length(gtklist->children)-1))
-      i++;
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    GtkTreePath *path = gtk_tree_model_get_path (model,  &iter);
+    GtkTreeIter prev;
+
+    if (path != NULL) {
+      gtk_tree_path_next (path);
+      if (gtk_tree_model_get_iter (model, &prev, path)) {
+        gtk_list_store_move_after (prop_dialog->parameters_store, &iter, &prev);
+      } else {
+        gtk_list_store_move_after (prop_dialog->parameters_store, &iter, NULL);
+      }
+    } else {
+      gtk_list_store_move_after (prop_dialog->parameters_store, &iter, NULL);
+    }
+    gtk_tree_path_free (path);
 
-    param = (UMLParameter *) g_object_get_data(G_OBJECT(list_item), "user_data");
+    gtk_tree_selection_select_iter (selection, &iter);
 
     /* Move parameter in current operations list: */
     current_op = (UMLOperation *)
-      g_object_get_data(G_OBJECT(prop_dialog->current_op), "user_data");
+      g_object_get_data (G_OBJECT (prop_dialog->current_op), "user_data");
 
-    current_op->parameters = g_list_remove(current_op->parameters,
-                                          (gpointer) param);
-    current_op->parameters = g_list_insert(current_op->parameters,
-                                          (gpointer) param,
-                                          i);
-
-    /* Move parameter in gtk list: */
-    g_object_ref(list_item);
-    list = g_list_prepend(NULL, list_item);
-    gtk_list_remove_items(gtklist, list);
-    gtk_list_insert_items(gtklist, list, i);
-    g_object_unref(list_item);
-
-    gtk_list_select_child(gtklist, list_item);
-
-    _operations_get_current_values(prop_dialog);
+    sync_params_to_operation (model, current_op);
   }
 }
 
@@ -329,52 +265,47 @@ operations_set_sensitive(UMLClassDialog *prop_dialog, gint val)
   gtk_widget_set_sensitive(prop_dialog->param_up_button, val);
 }
 
+
 static void
-operations_set_values(UMLClassDialog *prop_dialog, UMLOperation *op)
+operations_set_values (UMLClassDialog *prop_dialog, UMLOperation *op)
 {
   GList *list;
   UMLParameter *param;
-  GtkWidget *list_item;
+  GtkTreeIter iter;
   gchar *str;
 
-  gtk_entry_set_text(prop_dialog->op_name, op->name);
-  if (op->type != NULL)
-    gtk_entry_set_text(prop_dialog->op_type, op->type);
-  else
-    gtk_entry_set_text(prop_dialog->op_type, "");
-
-  if (op->stereotype != NULL)
-    gtk_entry_set_text(prop_dialog->op_stereotype, op->stereotype);
-  else
-    gtk_entry_set_text(prop_dialog->op_stereotype, "");
-
-  if (op->comment != NULL)
-    _class_set_comment(prop_dialog->op_comment, op->comment);
-  else
-    _class_set_comment(prop_dialog->op_comment, "");
-
-  dia_option_menu_set_active(prop_dialog->op_visible, op->visibility);
-  gtk_toggle_button_set_active(prop_dialog->op_class_scope, op->class_scope);
-  gtk_toggle_button_set_active(prop_dialog->op_query, op->query);
-  dia_option_menu_set_active(prop_dialog->op_inheritance_type, op->inheritance_type);
-
-  gtk_list_clear_items(prop_dialog->parameters_list, 0, -1);
-  prop_dialog->current_param = NULL;
-  parameters_set_sensitive(prop_dialog, FALSE);
+  gtk_entry_set_text (prop_dialog->op_name, op->name? op->name : "");
+  gtk_entry_set_text (prop_dialog->op_type, op->type? op->type : "");
+  gtk_entry_set_text (prop_dialog->op_stereotype, op->stereotype? op->stereotype : "");
+
+  _class_set_comment (prop_dialog->op_comment, op->comment? op->comment : "");
+
+  dia_option_menu_set_active (DIA_OPTION_MENU (prop_dialog->op_visible),
+                              op->visibility);
+  gtk_toggle_button_set_active (prop_dialog->op_class_scope, op->class_scope);
+  gtk_toggle_button_set_active (prop_dialog->op_query, op->query);
+  dia_option_menu_set_active (DIA_OPTION_MENU (prop_dialog->op_inheritance_type),
+                              op->inheritance_type);
+
+  gtk_list_store_clear (prop_dialog->parameters_store);
+  parameters_set_sensitive (prop_dialog, FALSE);
 
   list = op->parameters;
   while (list != NULL) {
     param = (UMLParameter *)list->data;
 
-    str = uml_get_parameter_string (param);
-    list_item = gtk_list_item_new_with_label (str);
-    g_free (str);
+    str = uml_parameter_get_string (param);
 
-    g_object_set_data(G_OBJECT(list_item), "user_data", (gpointer) param);
-    gtk_container_add (GTK_CONTAINER (prop_dialog->parameters_list), list_item);
-    gtk_widget_show (list_item);
+    gtk_list_store_append (prop_dialog->parameters_store, &iter);
+    gtk_list_store_set (prop_dialog->parameters_store,
+                        &iter,
+                        COL_PARAM_TITLE, str,
+                        COL_PARAM_PARAM, param,
+                        -1);
 
-    list = g_list_next(list);
+    g_free (str);
+
+    list = g_list_next (list);
   }
 }
 
@@ -388,62 +319,56 @@ operations_clear_values(UMLClassDialog *prop_dialog)
   gtk_toggle_button_set_active(prop_dialog->op_class_scope, FALSE);
   gtk_toggle_button_set_active(prop_dialog->op_query, FALSE);
 
-  gtk_list_clear_items(prop_dialog->parameters_list, 0, -1);
-  prop_dialog->current_param = NULL;
+  gtk_list_store_clear (prop_dialog->parameters_store);
+
   parameters_set_sensitive(prop_dialog, FALSE);
 }
 
 
 static void
-operations_get_values(UMLClassDialog *prop_dialog, UMLOperation *op)
+operations_get_values (UMLClassDialog *prop_dialog,
+                       UMLOperation   *op)
 {
-  const gchar *s;
-
-  g_free(op->name);
-  if (op->type != NULL)
-         g_free(op->type);
-
-  op->name = g_strdup(gtk_entry_get_text(prop_dialog->op_name));
-  op->type = g_strdup (gtk_entry_get_text(prop_dialog->op_type));
-  op->comment = g_strdup(_class_get_comment(prop_dialog->op_comment));
+  g_clear_pointer (&op->name, g_free);
+  g_clear_pointer (&op->type, g_free);
+  g_clear_pointer (&op->comment, g_free);
+  g_clear_pointer (&op->stereotype, g_free);
 
-  s = gtk_entry_get_text(prop_dialog->op_stereotype);
-  if (s && s[0])
-    op->stereotype = g_strdup (s);
-  else
-    op->stereotype = NULL;
+  op->name = g_strdup (gtk_entry_get_text (prop_dialog->op_name));
+  op->type = g_strdup (gtk_entry_get_text (prop_dialog->op_type));
+  op->comment = _class_get_comment (prop_dialog->op_comment);
+  op->stereotype = g_strdup (gtk_entry_get_text (prop_dialog->op_stereotype));
 
-  op->visibility = (UMLVisibility)dia_option_menu_get_active(prop_dialog->op_visible);
+  op->visibility = (UMLVisibility) dia_option_menu_get_active (DIA_OPTION_MENU (prop_dialog->op_visible));
 
   op->class_scope = gtk_toggle_button_get_active (prop_dialog->op_class_scope);
-  op->inheritance_type = (UMLInheritanceType)dia_option_menu_get_active(prop_dialog->op_inheritance_type);
+  op->inheritance_type = (UMLInheritanceType) dia_option_menu_get_active (DIA_OPTION_MENU 
(prop_dialog->op_inheritance_type));
 
   op->query = gtk_toggle_button_get_active (prop_dialog->op_query);
-
 }
 
+
 void
-_operations_get_current_values(UMLClassDialog *prop_dialog)
+_operations_get_current_values (UMLClassDialog *prop_dialog)
 {
   UMLOperation *current_op;
   GtkLabel *label;
   char *new_str;
 
-  parameters_get_current_values(prop_dialog);
-
   if (prop_dialog->current_op != NULL) {
     current_op = (UMLOperation *)
-      g_object_get_data(G_OBJECT(prop_dialog->current_op), "user_data");
+      g_object_get_data (G_OBJECT (prop_dialog->current_op), "user_data");
     if (current_op != NULL) {
-      operations_get_values(prop_dialog, current_op);
-      label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(prop_dialog->current_op)));
-      new_str = uml_get_operation_string(current_op);
+      operations_get_values (prop_dialog, current_op);
+      label = GTK_LABEL (gtk_bin_get_child (GTK_BIN (prop_dialog->current_op)));
+      new_str = uml_get_operation_string (current_op);
       gtk_label_set_text (label, new_str);
       g_free (new_str);
     }
   }
 }
 
+
 static void
 operations_list_item_destroy_callback(GtkWidget *list_item,
                                      gpointer data)
@@ -453,7 +378,7 @@ operations_list_item_destroy_callback(GtkWidget *list_item,
   op = (UMLOperation *) g_object_get_data(G_OBJECT(list_item), "user_data");
 
   if (op != NULL) {
-    uml_operation_destroy(op);
+    uml_operation_free (op);
     /*printf("Destroying operation list_item's user_data!\n");*/
   }
 }
@@ -515,6 +440,7 @@ operations_list_new_callback(GtkWidget *button,
 
 
   utfstr = uml_get_operation_string (op);
+
   list_item = gtk_list_item_new_with_label (utfstr);
   gtk_widget_show (list_item);
   g_free (utfstr);
@@ -641,16 +567,10 @@ _operations_read_from_dialog(UMLClass *umlclass,
   obj = &umlclass->element.object;
 
   /* if currently select op is changed in the entries, update from widgets */
-  _operations_get_current_values(prop_dialog);
+  _operations_get_current_values (prop_dialog);
 
   /* Free current operations: */
-  list = umlclass->operations;
-  while (list != NULL) {
-    op = (UMLOperation *)list->data;
-    uml_operation_destroy(op);
-    list = g_list_next(list);
-  }
-  g_list_free (umlclass->operations);
+  g_list_free_full (umlclass->operations, (GDestroyNotify) uml_operation_free);
   umlclass->operations = NULL;
 
   /* Insert new operations and remove them from gtklist: */
@@ -736,16 +656,21 @@ _operations_fill_in_dialog(UMLClass *umlclass)
   }
 }
 
+
 static void
-operations_update(GtkWidget *widget, UMLClass *umlclass)
+operations_update (GtkWidget *widget, UMLClass *umlclass)
 {
-  _operations_get_current_values(umlclass->properties_dialog);
+  _operations_get_current_values (umlclass->properties_dialog);
 }
 
+
 static int
-operations_update_event(GtkWidget *widget, GdkEventFocus *ev, UMLClass *umlclass)
+operations_update_event (GtkWidget     *widget,
+                         GdkEventFocus *ev,
+                         UMLClass      *umlclass)
 {
-  _operations_get_current_values(umlclass->properties_dialog);
+  _operations_get_current_values (umlclass->properties_dialog);
+
   return 0;
 }
 
@@ -811,12 +736,14 @@ operations_data_create_hbox (UMLClass *umlclass)
   label = gtk_label_new(_("Visibility:"));
 
   prop_dialog->op_visible = omenu = dia_option_menu_new ();
-  g_signal_connect (G_OBJECT (omenu), "changed",
-                   G_CALLBACK (operations_update), umlclass);
-  dia_option_menu_add_item(omenu, _("Public"), UML_PUBLIC);
-  dia_option_menu_add_item(omenu, _("Private"), UML_PRIVATE);
-  dia_option_menu_add_item(omenu, _("Protected"), UML_PROTECTED);
-  dia_option_menu_add_item(omenu, _("Implementation"), UML_IMPLEMENTATION);
+  g_signal_connect (G_OBJECT (omenu),
+                    "changed",
+                    G_CALLBACK (operations_update),
+                    umlclass);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Public"), UML_PUBLIC);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Private"), UML_PRIVATE);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Protected"), UML_PROTECTED);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Implementation"), UML_IMPLEMENTATION);
 
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
                                        /* left, right, top, bottom */
@@ -829,9 +756,9 @@ operations_data_create_hbox (UMLClass *umlclass)
   prop_dialog->op_inheritance_type = omenu = dia_option_menu_new ();
   g_signal_connect (G_OBJECT (omenu), "changed",
                    G_CALLBACK (operations_update), umlclass);
-  dia_option_menu_add_item(omenu, _("Abstract"), UML_ABSTRACT);
-  dia_option_menu_add_item(omenu, _("Polymorphic (virtual)"), UML_POLYMORPHIC);
-  dia_option_menu_add_item(omenu, _("Leaf (final)"), UML_LEAF);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Abstract"), UML_ABSTRACT);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Polymorphic (virtual)"), UML_POLYMORPHIC);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Leaf (final)"), UML_LEAF);
 
   gtk_table_attach (GTK_TABLE (table), label, 2,3,1,2, GTK_FILL,0, 0,0);
   gtk_table_attach (GTK_TABLE (table), omenu, 3,4,1,2, GTK_FILL | GTK_EXPAND,0, 0,2);
@@ -867,6 +794,38 @@ operations_data_create_hbox (UMLClass *umlclass)
   return hbox;
 }
 
+
+static void
+parameter_selected (GtkTreeSelection *selection,
+                    UMLClass         *umlclass)
+{
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  UMLParameter *param;
+  UMLClassDialog *prop_dialog;
+
+  prop_dialog = umlclass->properties_dialog;
+
+  if (!prop_dialog) {
+    return; /* maybe hiding a bug elsewhere */
+  }
+
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    gtk_tree_model_get (model, &iter, COL_PARAM_PARAM, &param, -1);
+
+    parameters_set_values (prop_dialog, param);
+    parameters_set_sensitive (prop_dialog, TRUE);
+
+    g_clear_pointer (&param, uml_parameter_unref);
+
+    gtk_widget_grab_focus (GTK_WIDGET (prop_dialog->param_name));
+  } else {
+    parameters_set_sensitive (prop_dialog, FALSE);
+    parameters_clear_values (prop_dialog);
+  }
+}
+
+
 static GtkWidget*
 operations_parameters_editor_create_vbox (UMLClass *umlclass)
 {
@@ -876,8 +835,11 @@ operations_parameters_editor_create_vbox (UMLClass *umlclass)
   GtkWidget *vbox3;
   GtkWidget *label;
   GtkWidget *scrolled_win;
-  GtkWidget *list;
   GtkWidget *button;
+  GtkWidget *image;
+  GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
+  GtkTreeSelection *select;
 
   prop_dialog = umlclass->properties_dialog;
 
@@ -891,62 +853,264 @@ operations_parameters_editor_create_vbox (UMLClass *umlclass)
   gtk_box_pack_start (GTK_BOX (vbox2), hbox2, TRUE, TRUE, 0);
 
   /* Parameters list editor - with of list at least width of buttons*/
-  hbox2 = gtk_hbox_new(TRUE, 5);
+  hbox2 = gtk_vbox_new (FALSE, 6);
 
   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
+                                  GTK_POLICY_AUTOMATIC,
+                                  GTK_POLICY_AUTOMATIC);
   gtk_box_pack_start (GTK_BOX (hbox2), scrolled_win, TRUE, TRUE, 0);
   gtk_widget_show (scrolled_win);
 
-  list = gtk_list_new ();
-  prop_dialog->parameters_list = GTK_LIST(list);
-  gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_SINGLE);
-  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
-  gtk_container_set_focus_vadjustment (GTK_CONTAINER (list),
-                                      gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW 
(scrolled_win)));
-  gtk_widget_show (list);
-
-  g_signal_connect (G_OBJECT (list), "selection_changed",
-                   G_CALLBACK(parameters_list_selection_changed_callback),
-                   umlclass);
-
-  vbox3 = gtk_vbox_new(FALSE, 5);
-
-  button = gtk_button_new_from_stock (GTK_STOCK_NEW);
+  prop_dialog->parameters_store = gtk_list_store_new (N_PARAM_COLS,
+                                                      G_TYPE_STRING,
+                                                      DIA_UML_TYPE_PARAMETER);
+  prop_dialog->parameters = gtk_tree_view_new_with_model (GTK_TREE_MODEL (prop_dialog->parameters_store));
+  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (prop_dialog->parameters), FALSE);
+  select = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
+  g_signal_connect (G_OBJECT (select),
+                    "changed",
+                    G_CALLBACK (parameter_selected),
+                    umlclass);
+  gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
+
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                     renderer,
+                                                     "text",
+                                                     COL_PARAM_TITLE,
+                                                     NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (prop_dialog->parameters),
+                               column);
+
+  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), prop_dialog->parameters);
+  gtk_container_set_focus_vadjustment (GTK_CONTAINER (prop_dialog->parameters),
+                                       gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW 
(scrolled_win)));
+  gtk_widget_show (prop_dialog->parameters);
+
+
+  vbox3 = gtk_hbox_new (TRUE, 6);
+
+
+  button = gtk_button_new ();
+  image = gtk_image_new_from_icon_name ("list-add",
+                                        GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_widget_show (image);
+  gtk_container_add (GTK_CONTAINER (button), image);
+  gtk_widget_set_tooltip_text (button, _("Add Parameter"));
   prop_dialog->param_new_button = button;
-  g_signal_connect (G_OBJECT (button), "clicked",
-                   G_CALLBACK(parameters_list_new_callback), umlclass);
+  g_signal_connect (G_OBJECT (button),
+                    "clicked",
+                    G_CALLBACK (parameters_list_new_callback),
+                    umlclass);
   gtk_box_pack_start (GTK_BOX (vbox3), button, FALSE, TRUE, 0);
   gtk_widget_show (button);
-  button = gtk_button_new_from_stock (GTK_STOCK_DELETE);
+
+
+  button = gtk_button_new ();
+  image = gtk_image_new_from_icon_name ("list-remove",
+                                        GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_widget_show (image);
+  gtk_container_add (GTK_CONTAINER (button), image);
+  gtk_widget_set_tooltip_text (button, _("Remove Parameter"));
   prop_dialog->param_delete_button = button;
-  g_signal_connect (G_OBJECT (button), "clicked",
-                   G_CALLBACK(parameters_list_delete_callback), umlclass);
+  g_signal_connect (G_OBJECT (button),
+                    "clicked",
+                    G_CALLBACK (parameters_list_delete_callback),
+                    umlclass);
   gtk_box_pack_start (GTK_BOX (vbox3), button, FALSE, TRUE, 0);
   gtk_widget_show (button);
-  button = gtk_button_new_from_stock (GTK_STOCK_GO_UP);
+
+
+  button = gtk_button_new ();
+  image = gtk_image_new_from_icon_name ("go-up",
+                                        GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_widget_show (image);
+  gtk_container_add (GTK_CONTAINER (button), image);
+  gtk_widget_set_tooltip_text (button, _("Move Parameter Up"));
   prop_dialog->param_up_button = button;
-  g_signal_connect (G_OBJECT (button), "clicked",
-                   G_CALLBACK(parameters_list_move_up_callback), umlclass);
+  g_signal_connect (G_OBJECT (button),
+                    "clicked",
+                    G_CALLBACK (parameters_list_move_up_callback),
+                    umlclass);
   gtk_box_pack_start (GTK_BOX (vbox3), button, FALSE, TRUE, 0);
   gtk_widget_show (button);
-  button = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN);
+
+
+  button = gtk_button_new ();
+  image = gtk_image_new_from_icon_name ("go-down",
+                                        GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_widget_show (image);
+  gtk_container_add (GTK_CONTAINER (button), image);
+  gtk_widget_set_tooltip_text (button, _("Move Parameter Down"));
   prop_dialog->param_down_button = button;
-  g_signal_connect (G_OBJECT (button), "clicked",
-                   G_CALLBACK(parameters_list_move_down_callback), umlclass);
+  g_signal_connect (G_OBJECT (button),
+                    "clicked",
+                    G_CALLBACK (parameters_list_move_down_callback),
+                    umlclass);
   gtk_box_pack_start (GTK_BOX (vbox3), button, FALSE, TRUE, 0);
   gtk_widget_show (button);
 
-  gtk_box_pack_start (GTK_BOX (hbox2), vbox3, FALSE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (hbox2), vbox3, FALSE, FALSE, 0);
 
-  gtk_box_pack_start (GTK_BOX (vbox2), hbox2, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox2), hbox2, FALSE, FALSE, 0);
   /* end: Parameter list editor */
 
   return vbox2;
 }
 
+
+static void
+param_name_changed (GtkWidget *entry, UMLClass *umlclass)
+{
+  UMLClassDialog *prop_dialog;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkTreeSelection *selection;
+  UMLParameter *param;
+  char *new_str;
+
+  prop_dialog = umlclass->properties_dialog;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    gtk_tree_model_get (model, &iter, COL_PARAM_PARAM, &param, -1);
+
+    g_clear_pointer (&param->name, g_free);
+    param->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+
+    new_str = uml_parameter_get_string (param);
+
+    gtk_list_store_set (prop_dialog->parameters_store,
+                        &iter,
+                        COL_PARAM_TITLE, new_str,
+                        -1);
+
+    g_clear_pointer (&new_str, g_free);
+    g_clear_pointer (&param, uml_parameter_unref);
+  }
+}
+
+
+static void
+param_type_changed (GtkWidget *entry, UMLClass *umlclass)
+{
+  UMLClassDialog *prop_dialog;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkTreeSelection *selection;
+  UMLParameter *param;
+  char *new_str;
+
+  prop_dialog = umlclass->properties_dialog;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    gtk_tree_model_get (model, &iter, COL_PARAM_PARAM, &param, -1);
+
+    g_clear_pointer (&param->type, g_free);
+    param->type = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+
+    new_str = uml_parameter_get_string (param);
+
+    gtk_list_store_set (prop_dialog->parameters_store,
+                        &iter,
+                        COL_PARAM_TITLE, new_str,
+                        -1);
+
+    g_clear_pointer (&new_str, g_free);
+    g_clear_pointer (&param, uml_parameter_unref);
+  }
+}
+
+
+static void
+param_value_changed (GtkWidget *entry, UMLClass *umlclass)
+{
+  UMLClassDialog *prop_dialog;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkTreeSelection *selection;
+  UMLParameter *param;
+  char *new_str;
+
+  prop_dialog = umlclass->properties_dialog;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    gtk_tree_model_get (model, &iter, COL_PARAM_PARAM, &param, -1);
+
+    g_clear_pointer (&param->value, g_free);
+    param->value = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+
+    new_str = uml_parameter_get_string (param);
+
+    gtk_list_store_set (prop_dialog->parameters_store,
+                        &iter,
+                        COL_PARAM_TITLE, new_str,
+                        -1);
+
+    g_clear_pointer (&new_str, g_free);
+    g_clear_pointer (&param, uml_parameter_unref);
+  }
+}
+
+
+static void
+param_comment_changed (GtkTextBuffer *buffer, UMLClass *umlclass)
+{
+  UMLClassDialog *prop_dialog;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkTreeSelection *selection;
+  UMLParameter *param;
+
+  prop_dialog = umlclass->properties_dialog;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    gtk_tree_model_get (model, &iter, COL_PARAM_PARAM, &param, -1);
+
+    g_clear_pointer (&param->comment, g_free);
+    param->comment = buffer_get_text (prop_dialog->param_comment_buffer);
+
+    g_clear_pointer (&param, uml_parameter_unref);
+  }
+}
+
+
+static void
+param_kind_changed (DiaOptionMenu *selector, UMLClass *umlclass)
+{
+  UMLClassDialog *prop_dialog;
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkTreeSelection *selection;
+  UMLParameter *param;
+  char *new_str;
+
+  prop_dialog = umlclass->properties_dialog;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    gtk_tree_model_get (model, &iter, COL_PARAM_PARAM, &param, -1);
+
+    param->kind = (UMLParameterKind) dia_option_menu_get_active (selector);
+
+    new_str = uml_parameter_get_string (param);
+
+    gtk_list_store_set (prop_dialog->parameters_store,
+                        &iter,
+                        COL_PARAM_TITLE, new_str,
+                        -1);
+
+    g_clear_pointer (&new_str, g_free);
+    g_clear_pointer (&param, uml_parameter_unref);
+  }
+}
+
+
 static GtkWidget*
 operations_parameters_data_create_vbox (UMLClass *umlclass)
 {
@@ -974,77 +1138,77 @@ operations_parameters_data_create_vbox (UMLClass *umlclass)
   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
   gtk_box_pack_start (GTK_BOX (vbox3), table, FALSE, FALSE, 0);
 
-  label = gtk_label_new(_("Name:"));
-  entry = gtk_entry_new();
-  prop_dialog->param_name = GTK_ENTRY(entry);
-  g_signal_connect (G_OBJECT (entry), "focus_out_event",
-                   G_CALLBACK (operations_update_event), umlclass);
-  g_signal_connect (G_OBJECT (entry), "activate",
-                   G_CALLBACK (operations_update), umlclass);
+  label = gtk_label_new (_("Name:"));
+  entry = gtk_entry_new ();
+  prop_dialog->param_name = GTK_ENTRY (entry);
+  g_signal_connect (entry,
+                    "changed",
+                    G_CALLBACK (param_name_changed),
+                    umlclass);
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
   gtk_table_attach (GTK_TABLE (table), label, 0,1,0,1, GTK_FILL,0, 0,0);
   gtk_table_attach (GTK_TABLE (table), entry, 1,2,0,1, GTK_FILL | GTK_EXPAND,0, 0,2);
 
-  label = gtk_label_new(_("Type:"));
-  entry = gtk_entry_new();
-  g_signal_connect (G_OBJECT (entry), "focus_out_event",
-                   G_CALLBACK (operations_update_event), umlclass);
-  g_signal_connect (G_OBJECT (entry), "activate",
-                   G_CALLBACK (operations_update), umlclass);
-  prop_dialog->param_type = GTK_ENTRY(entry);
+  label = gtk_label_new (_("Type:"));
+  entry = gtk_entry_new ();
+  prop_dialog->param_type = GTK_ENTRY (entry);
+  g_signal_connect (entry,
+                    "changed",
+                    G_CALLBACK (param_type_changed),
+                    umlclass);
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
   gtk_table_attach (GTK_TABLE (table), label, 0,1,1,2, GTK_FILL,0, 0,0);
   gtk_table_attach (GTK_TABLE (table), entry, 1,2,1,2, GTK_FILL | GTK_EXPAND,0, 0,2);
 
-  label = gtk_label_new(_("Def. value:"));
-  entry = gtk_entry_new();
+  label = gtk_label_new (_("Def. value:"));
+  gtk_widget_set_tooltip_text (label, _("Default value"));
+  entry = gtk_entry_new ();
   prop_dialog->param_value = GTK_ENTRY(entry);
-  g_signal_connect (G_OBJECT (entry), "focus_out_event",
-                   G_CALLBACK (operations_update_event), umlclass);
-  g_signal_connect (G_OBJECT (entry), "activate",
-                   G_CALLBACK (operations_update), umlclass);
+  g_signal_connect (entry,
+                    "changed",
+                    G_CALLBACK (param_value_changed),
+                    umlclass);
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
   gtk_table_attach (GTK_TABLE (table), label, 0,1,2,3, GTK_FILL,0, 0,0);
   gtk_table_attach (GTK_TABLE (table), entry, 1,2,2,3, GTK_FILL | GTK_EXPAND,0, 0,2);
 
-  label = gtk_label_new(_("Comment:"));
+  label = gtk_label_new (_("Comment:"));
   scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
-                                      GTK_SHADOW_IN);
+                                       GTK_SHADOW_IN);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
-                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
-  entry = gtk_text_view_new ();
-  prop_dialog->param_comment = GTK_TEXT_VIEW(entry);
+                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+  prop_dialog->param_comment_buffer = gtk_text_buffer_new (NULL);
+  entry = gtk_text_view_new_with_buffer (prop_dialog->param_comment_buffer);
+  prop_dialog->param_comment = GTK_TEXT_VIEW (entry);
+  g_signal_connect (prop_dialog->param_comment_buffer,
+                    "changed",
+                    G_CALLBACK (param_comment_changed),
+                    umlclass);
   gtk_container_add (GTK_CONTAINER (scrolledwindow), entry);
   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (entry), GTK_WRAP_WORD);
-  gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW (entry),TRUE);
-
-  g_signal_connect (G_OBJECT (entry), "focus_out_event",
-                   G_CALLBACK (operations_update_event), umlclass);
+  gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (entry),TRUE);
 
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
   gtk_table_attach (GTK_TABLE (table), label, 2,3,1,2, GTK_FILL,0, 0,0);
   gtk_table_attach (GTK_TABLE (table), scrolledwindow, 3,4,1,3, GTK_FILL | GTK_EXPAND,0, 0,2);
 
-  label = gtk_label_new(_("Direction:"));
+  label = gtk_label_new (_("Direction:"));
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_table_attach (GTK_TABLE (table), label, 2,3,0,1, GTK_FILL,0, 0,3);
 
   prop_dialog->param_kind = omenu = dia_option_menu_new ();
-  g_signal_connect (G_OBJECT (omenu), "changed",
-                   G_CALLBACK (operations_update), umlclass);
-  dia_option_menu_add_item(omenu, _("Undefined"), UML_UNDEF_KIND);
-  dia_option_menu_add_item(omenu, _("In"), UML_IN);
-  dia_option_menu_add_item(omenu, _("Out"), UML_OUT);
-  dia_option_menu_add_item(omenu, _("In & Out"), UML_INOUT);
-
-  {
-    GtkWidget * align;
-    align = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
-    gtk_container_add(GTK_CONTAINER(align), omenu);
-    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-    gtk_table_attach (GTK_TABLE (table), label, 2,3,0,1, GTK_FILL,0, 0,3);
-    gtk_table_attach (GTK_TABLE (table), align, 3,4,0,1, GTK_FILL,0, 0,3);
-  }
+  g_signal_connect (G_OBJECT (omenu),
+                    "changed",
+                    G_CALLBACK (param_kind_changed),
+                    umlclass);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Undefined"), UML_UNDEF_KIND);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("In"), UML_IN);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Out"), UML_OUT);
+  dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("In & Out"), UML_INOUT);
+  dia_option_menu_set_active (DIA_OPTION_MENU (omenu), UML_UNDEF_KIND);
+  gtk_table_attach (GTK_TABLE (table), omenu, 3,4,0,1, GTK_FILL, 0, 0,3);
 
   return vbox2;
 }
diff --git a/objects/UML/uml.h b/objects/UML/uml.h
index 0d30b0c2..c5be896d 100644
--- a/objects/UML/uml.h
+++ b/objects/UML/uml.h
@@ -60,7 +60,7 @@ typedef gchar * UMLStereotype;
  * Some would call them member variables ;)
  */
 struct _UMLAttribute {
-  gint internal_id; /**< Arbitrary integer to recognize attributes after 
+  gint internal_id; /**< Arbitrary integer to recognize attributes after
                     * the user has shuffled them in the dialog. */
   gchar *name; /**< the member variables name */
   gchar *type; /**< the return value */
@@ -69,7 +69,7 @@ struct _UMLAttribute {
   UMLVisibility visibility; /**< attributes visibility */
   int abstract; /**< not sure if this applicable */
   int class_scope; /**< in C++ : static member */
-  
+
   ConnectionPoint* left_connection; /**< left */
   ConnectionPoint* right_connection; /**< right */
 };
@@ -82,7 +82,7 @@ struct _UMLOperation {
                     * the user has shuffled them in the dialog. */
   gchar *name; /**< the function name */
   gchar *type; /**< Return type, NULL => No return type */
-  gchar *comment; /**< comment */  
+  gchar *comment; /**< comment */
   UMLStereotype stereotype; /**< just some string */
   UMLVisibility visibility; /**< allowed access */
   UMLInheritanceType inheritance_type;
@@ -127,31 +127,53 @@ struct _UMLFormalParameter {
 
 /** calculated the 'formated' representation */
 extern gchar *uml_get_attribute_string (UMLAttribute *attribute);
+
+
+
+#define DIA_UML_TYPE_PARAMETER uml_parameter_get_type ()
+
+UMLParameter *uml_parameter_new                      (void);
+GType         uml_parameter_get_type                 (void);
+UMLParameter *uml_parameter_copy                     (UMLParameter *param);
+UMLParameter *uml_parameter_ref                      (UMLParameter *param);
+void          uml_parameter_unref                    (UMLParameter *param);
 /** calculated the 'formated' representation */
-extern gchar *uml_get_operation_string(UMLOperation *operation);
+gchar        *uml_parameter_get_string               (UMLParameter *param);
+
+
+
+#define DIA_UML_TYPE_OPERATION uml_operation_get_type ()
+
+UMLOperation *uml_operation_new                      (void);
+GType         uml_operation_get_type                 (void);
+UMLOperation *uml_operation_copy                     (UMLOperation  *op);
+void          uml_operation_copy_into                (UMLOperation  *srcop,
+                                                      UMLOperation  *destop);
+void          uml_operation_free                     (UMLOperation  *op);
+void          uml_operation_write                    (AttributeNode  attr_node,
+                                                      UMLOperation  *op,
+                                                      DiaContext    *ctx);
+void          uml_operation_ensure_connection_points (UMLOperation  *oper,
+                                                      DiaObject     *obj);
 /** calculated the 'formated' representation */
-extern gchar *uml_get_parameter_string(UMLParameter *param);
+char         *uml_get_operation_string               (UMLOperation  *operation);
+
+
+
 /** calculated the 'formated' representation */
 extern gchar *uml_get_formalparameter_string(UMLFormalParameter *parameter);
 extern void uml_attribute_copy_into(UMLAttribute *srcattr, UMLAttribute *destattr);
 extern UMLAttribute *uml_attribute_copy(UMLAttribute *attr);
-extern void uml_operation_copy_into(UMLOperation *srcop, UMLOperation *destop);
-extern UMLOperation *uml_operation_copy(UMLOperation *op);
 extern UMLFormalParameter *uml_formalparameter_copy(UMLFormalParameter *param);
 extern void uml_attribute_destroy(UMLAttribute *attribute);
-extern void uml_operation_destroy(UMLOperation *op);
-extern void uml_parameter_destroy(UMLParameter *param);
+
 extern void uml_formalparameter_destroy(UMLFormalParameter *param);
 extern UMLAttribute *uml_attribute_new(void);
-extern UMLOperation *uml_operation_new(void);
-extern UMLParameter *uml_parameter_new(void);
 extern UMLFormalParameter *uml_formalparameter_new(void);
 
 extern void uml_attribute_ensure_connection_points (UMLAttribute *attr, DiaObject* obj);
-extern void uml_operation_ensure_connection_points (UMLOperation *oper, DiaObject* obj);
 
 extern void uml_attribute_write(AttributeNode attr_node, UMLAttribute *attr, DiaContext *ctx);
-extern void uml_operation_write(AttributeNode attr_node, UMLOperation *op, DiaContext *ctx);
 extern void uml_formalparameter_write(AttributeNode attr_node, UMLFormalParameter *param, DiaContext *ctx);
 
 #endif /* UML_H */
diff --git a/objects/UML/umloperation.c b/objects/UML/umloperation.c
index 500d9286..34972f19 100644
--- a/objects/UML/umloperation.c
+++ b/objects/UML/umloperation.c
@@ -95,19 +95,23 @@ static PropOffset umloperation_offsets[] = {
 PropDescDArrayExtra umloperation_extra = {
   { umloperation_props, umloperation_offsets, "umloperation" },
   (NewRecordFunc)uml_operation_new,
-  (FreeRecordFunc)uml_operation_destroy
+  (FreeRecordFunc)uml_operation_free
 };
 
+G_DEFINE_BOXED_TYPE (UMLOperation, uml_operation, uml_operation_copy, uml_operation_free)
+
+
 UMLOperation *
-uml_operation_new(void)
+uml_operation_new (void)
 {
   UMLOperation *op;
   static gint next_id = 1;
 
-  op = g_new0(UMLOperation, 1);
+  op = g_slice_new0 (UMLOperation);
   op->internal_id = next_id++;
-  op->name = g_strdup("");
-  op->comment = g_strdup("");
+  op->name = g_strdup ("");
+  op->type = g_strdup ("");
+  op->comment = g_strdup ("");
   op->visibility = UML_PUBLIC;
   op->inheritance_type = UML_LEAF;
 
@@ -118,8 +122,9 @@ uml_operation_new(void)
   return op;
 }
 
+
 void
-uml_operation_copy_into(UMLOperation *srcop, UMLOperation *destop)
+uml_operation_copy_into (UMLOperation *srcop, UMLOperation *destop)
 {
   UMLParameter *param;
   UMLParameter *newparam;
@@ -128,33 +133,33 @@ uml_operation_copy_into(UMLOperation *srcop, UMLOperation *destop)
   destop->internal_id = srcop->internal_id;
 
   if (destop->name != NULL) {
-    g_free(destop->name);
+    g_free (destop->name);
   }
-  destop->name = g_strdup(srcop->name);
+  destop->name = g_strdup (srcop->name);
 
   if (destop->type != NULL) {
-    g_free(destop->type);
+    g_free (destop->type);
   }
   if (srcop->type != NULL) {
-    destop->type = g_strdup(srcop->type);
+    destop->type = g_strdup (srcop->type);
   } else {
     destop->type = NULL;
   }
 
   if (destop->stereotype != NULL) {
-    g_free(destop->stereotype);
+    g_free (destop->stereotype);
   }
   if(srcop->stereotype != NULL) {
-    destop->stereotype = g_strdup(srcop->stereotype);
+    destop->stereotype = g_strdup (srcop->stereotype);
   } else {
     destop->stereotype = NULL;
   }
 
   if (destop->comment != NULL) {
-    g_free(destop->comment);
+    g_free (destop->comment);
   }
   if (srcop->comment != NULL) {
-    destop->comment = g_strdup(srcop->comment);
+    destop->comment = g_strdup (srcop->comment);
   } else {
     destop->comment = NULL;
   }
@@ -164,42 +169,31 @@ uml_operation_copy_into(UMLOperation *srcop, UMLOperation *destop)
   destop->inheritance_type = srcop->inheritance_type;
   destop->query = srcop->query;
 
-  list = destop->parameters;
-  while (list != NULL) {
-    param = (UMLParameter *)list->data;
-    uml_parameter_destroy(param);
-    list = g_list_next(list);
-  }
+  g_list_free_full (destop->parameters, (GDestroyNotify) uml_parameter_unref);
   destop->parameters = NULL;
+
   list = srcop->parameters;
   while (list != NULL) {
-    param = (UMLParameter *)list->data;
-
-    newparam = g_new0(UMLParameter, 1);
-    newparam->name = g_strdup(param->name);
-    newparam->type = g_strdup(param->type);
-    newparam->comment = g_strdup(param->comment);
+    param = (UMLParameter *) list->data;
 
-    if (param->value != NULL)
-      newparam->value = g_strdup(param->value);
-    else
-      newparam->value = NULL;
-    newparam->kind = param->kind;
+    // Break the link to the original
+    newparam = uml_parameter_copy (param);
 
-    destop->parameters = g_list_append(destop->parameters, newparam);
+    destop->parameters = g_list_append (destop->parameters, newparam);
 
-    list = g_list_next(list);
+    list = g_list_next (list);
   }
 }
 
+
 UMLOperation *
-uml_operation_copy(UMLOperation *op)
+uml_operation_copy (UMLOperation *op)
 {
   UMLOperation *newop;
 
-  newop = g_new0(UMLOperation, 1);
+  newop = uml_operation_new ();
 
-  uml_operation_copy_into(op, newop);
+  uml_operation_copy_into (op, newop);
 #if 0 /* setup elsewhere */
   newop->left_connection = g_new0(ConnectionPoint,1);
   *newop->left_connection = *op->left_connection;
@@ -212,28 +206,22 @@ uml_operation_copy(UMLOperation *op)
   return newop;
 }
 
+
 void
-uml_operation_destroy(UMLOperation *op)
+uml_operation_free (UMLOperation *op)
 {
-  GList *list;
-  UMLParameter *param;
-
-  g_free(op->name);
+  g_free (op->name);
   if (op->type != NULL)
-    g_free(op->type);
+    g_free (op->type);
   if (op->stereotype != NULL)
-    g_free(op->stereotype);
+    g_free (op->stereotype);
 
-  g_free(op->comment);
+  g_free (op->comment);
+
+  g_list_free_full (op->parameters, (GDestroyNotify) uml_parameter_unref);
 
-  list = op->parameters;
-  while (list != NULL) {
-    param = (UMLParameter *)list->data;
-    uml_parameter_destroy(param);
-    list = g_list_next(list);
-  }
   if (op->wrappos) {
-    g_list_free(op->wrappos);
+    g_list_free (op->wrappos);
   }
 
 #if 0 /* freed elsewhere */
@@ -241,9 +229,10 @@ uml_operation_destroy(UMLOperation *op)
   g_free(op->left_connection);
   g_free(op->right_connection);
 #endif
-  g_free(op);
+  g_slice_free (UMLOperation, op);
 }
 
+
 void
 uml_operation_write(AttributeNode attr_node, UMLOperation *op, DiaContext *ctx)
 {
diff --git a/objects/UML/umlparameter.c b/objects/UML/umlparameter.c
index aea4c7c8..a65bdfa1 100644
--- a/objects/UML/umlparameter.c
+++ b/objects/UML/umlparameter.c
@@ -62,52 +62,98 @@ static PropOffset umlparameter_offsets[] = {
 
 PropDescDArrayExtra umlparameter_extra = {
   { umlparameter_props, umlparameter_offsets, "umlparameter" },
-  (NewRecordFunc)uml_parameter_new,
-  (FreeRecordFunc)uml_parameter_destroy
+  (NewRecordFunc) uml_parameter_new,
+  (FreeRecordFunc) uml_parameter_unref
 };
 
+G_DEFINE_BOXED_TYPE (UMLParameter, uml_parameter, uml_parameter_ref, uml_parameter_unref)
+
+
 UMLParameter *
-uml_parameter_new(void)
+uml_parameter_new (void)
 {
   UMLParameter *param;
 
-  param = g_new0(UMLParameter, 1);
-  param->name = g_strdup("");
-  param->type = g_strdup("");
-  param->comment = g_strdup("");
-  param->value = NULL;
+  param = g_rc_box_new0 (UMLParameter);
+  param->name = g_strdup ("");
+  param->type = g_strdup ("");
+  param->value = g_strdup ("");
+  param->comment = g_strdup ("");
   param->kind = UML_UNDEF_KIND;
 
   return param;
 }
 
-void
-uml_parameter_destroy(UMLParameter *param)
+
+UMLParameter *
+uml_parameter_copy (UMLParameter *param)
+{
+  UMLParameter *new;
+
+  g_return_val_if_fail (param != NULL, NULL);
+
+  new = uml_parameter_new ();
+
+  g_clear_pointer (&new->name, g_free);
+  g_clear_pointer (&new->type, g_free);
+  g_clear_pointer (&new->value, g_free);
+  g_clear_pointer (&new->comment, g_free);
+
+  new->name = g_strdup (param->name);
+  new->type = g_strdup (param->type);
+  new->value = g_strdup (param->value);
+  new->comment = g_strdup (param->comment);
+
+  new->kind = param->kind;
+
+  return new;
+}
+
+
+UMLParameter *
+uml_parameter_ref (UMLParameter *param)
+{
+  g_return_val_if_fail (param != NULL, NULL);
+
+  return g_rc_box_acquire (param);
+}
+
+
+static void
+parameter_free (UMLParameter *param)
 {
-  g_free(param->name);
-  g_free(param->type);
-  if (param->value != NULL)
-    g_free(param->value);
-  g_free(param->comment);
+  g_clear_pointer (&param->name, g_free);
+  g_clear_pointer (&param->type, g_free);
+  g_clear_pointer (&param->value, g_free);
+  g_clear_pointer (&param->comment, g_free);
+}
 
-  g_free(param);
+
+void
+uml_parameter_unref (UMLParameter *param)
+{
+  g_rc_box_release_full (param, (GDestroyNotify) parameter_free);
 }
 
+
 char *
-uml_get_parameter_string (UMLParameter *param)
+uml_parameter_get_string (UMLParameter *param)
 {
   int len;
   char *str;
 
   /* Calculate length: */
-  len = strlen (param->name) + 1 + strlen (param->type);
+  len = strlen (param->name);
 
-  if (param->value != NULL) {
-    len += 1 + strlen (param->value) ;
+  if (param->type && strlen (param->type) > 0) {
+    len += 1 + strlen (param->type);
   }
 
-  switch(param->kind)
-    {
+  if (param->value && strlen (param->value) > 0) {
+    len += 1 + strlen (param->value);
+  }
+
+  switch (param->kind) {
     case UML_UNDEF_KIND:
       break;
     case UML_IN:
@@ -119,15 +165,14 @@ uml_get_parameter_string (UMLParameter *param)
     case UML_INOUT:
       len += 6;
       break;
-    }
+  }
 
   /* Generate string: */
   str = g_malloc (sizeof (char) * (len + 1));
 
-  strcpy(str, "");
+  strcpy (str, "");
 
-  switch(param->kind)
-    {
+  switch (param->kind) {
     case UML_UNDEF_KIND:
       break;
     case UML_IN:
@@ -139,13 +184,16 @@ uml_get_parameter_string (UMLParameter *param)
     case UML_INOUT:
       strcat (str, "inout ");
       break;
-    }
-
+  }
 
   strcat (str, param->name);
-  strcat (str, ":");
-  strcat (str, param->type);
-  if (param->value != NULL) {
+
+  if (param->type && strlen (param->type) > 0) {
+    strcat (str, ":");
+    strcat (str, param->type);
+  }
+
+  if (param->value && strlen (param->value) > 0) {
     strcat (str, "=");
     strcat (str, param->value);
   }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]