[dia/dia-next: 40/59] Parameters as a GObject & a listboxrow to edit them



commit 0c3a4f57293771779801b3e576ed39a9437c96f0
Author: Zander Brown <zbrown gnome org>
Date:   Sat Dec 29 23:53:58 2018 +0000

    Parameters as a GObject & a listboxrow to edit them

 data/dia-uml-operation-dialog.ui        |  41 ++--
 data/dia-uml-operation-parameter-row.ui | 156 ++++++------
 objects/UML/class_dialog.h              |  24 +-
 objects/UML/class_operations_dialog.c   | 417 +++++++++++++++++++++++++++++---
 objects/UML/uml.h                       |  29 ++-
 objects/UML/umloperation.c              |  50 ++--
 objects/UML/umlparameter.c              | 195 ++++++++++++---
 7 files changed, 721 insertions(+), 191 deletions(-)
---
diff --git a/data/dia-uml-operation-dialog.ui b/data/dia-uml-operation-dialog.ui
index 9f5557e8..b9d0962b 100644
--- a/data/dia-uml-operation-dialog.ui
+++ b/data/dia-uml-operation-dialog.ui
@@ -5,6 +5,7 @@
   <object class="GtkTextBuffer" id="comment"/>
   <template class="DiaUmlOperationDialog" parent="GtkDialog">
     <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Operation</property>
     <property name="type_hint">dialog</property>
     <child>
       <placeholder/>
@@ -50,22 +51,6 @@
                     <property name="margin_bottom">8</property>
                     <property name="orientation">vertical</property>
                     <property name="spacing">8</property>
-                    <child>
-                      <object class="GtkLabel" id="title">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">Operation</property>
-                        <property name="xalign">0</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
                     <child>
                       <object class="GtkGrid">
                         <property name="visible">True</property>
@@ -323,7 +308,7 @@
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">True</property>
-                        <property name="position">1</property>
+                        <property name="position">0</property>
                       </packing>
                     </child>
                     <child>
@@ -339,7 +324,7 @@
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">True</property>
-                        <property name="position">2</property>
+                        <property name="position">1</property>
                       </packing>
                     </child>
                     <child>
@@ -353,12 +338,32 @@
                           <object class="GtkListBox" id="list">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
+                            <property name="selection_mode">none</property>
+                            <property name="activate_on_single_click">False</property>
+                            <signal name="add" handler="parameter_added" object="DiaUmlOperationDialog" 
swapped="yes"/>
+                            <signal name="remove" handler="parameter_removed" object="DiaUmlOperationDialog" 
swapped="yes"/>
                           </object>
                         </child>
                         <child type="label_item">
                           <placeholder/>
                         </child>
                       </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton">
+                        <property name="label" translatable="yes">Add Parameter</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="halign">end</property>
+                        <property name="valign">center</property>
+                        <signal name="clicked" handler="dlg_add_parameter" object="DiaUmlOperationDialog" 
swapped="yes"/>
+                      </object>
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">True</property>
diff --git a/data/dia-uml-operation-parameter-row.ui b/data/dia-uml-operation-parameter-row.ui
index 4dad4e81..322da6b1 100644
--- a/data/dia-uml-operation-parameter-row.ui
+++ b/data/dia-uml-operation-parameter-row.ui
@@ -2,16 +2,7 @@
 <!-- Generated with glade 3.22.1 -->
 <interface>
   <requires lib="gtk+" version="3.20"/>
-  <object class="GtkImage" id="image1">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="icon_name">go-up-symbolic</property>
-  </object>
-  <object class="GtkImage" id="image2">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="icon_name">go-down-symbolic</property>
-  </object>
+  <object class="GtkTextBuffer" id="comment"/>
   <template class="DiaUmlOperationParameterRow" parent="GtkListBoxRow">
     <property name="width_request">100</property>
     <property name="height_request">80</property>
@@ -28,7 +19,7 @@
         <property name="margin_bottom">8</property>
         <property name="hexpand">True</property>
         <property name="row_spacing">8</property>
-        <property name="column_spacing">8</property>
+        <property name="column_spacing">16</property>
         <child>
           <object class="GtkLabel">
             <property name="visible">True</property>
@@ -38,7 +29,7 @@
           </object>
           <packing>
             <property name="left_attach">0</property>
-            <property name="top_attach">1</property>
+            <property name="top_attach">0</property>
           </packing>
         </child>
         <child>
@@ -50,7 +41,7 @@
           </object>
           <packing>
             <property name="left_attach">0</property>
-            <property name="top_attach">2</property>
+            <property name="top_attach">1</property>
           </packing>
         </child>
         <child>
@@ -62,7 +53,7 @@
           </object>
           <packing>
             <property name="left_attach">2</property>
-            <property name="top_attach">1</property>
+            <property name="top_attach">0</property>
           </packing>
         </child>
         <child>
@@ -74,7 +65,7 @@
           </object>
           <packing>
             <property name="left_attach">2</property>
-            <property name="top_attach">2</property>
+            <property name="top_attach">1</property>
           </packing>
         </child>
         <child>
@@ -86,46 +77,50 @@
           </object>
           <packing>
             <property name="left_attach">0</property>
-            <property name="top_attach">3</property>
+            <property name="top_attach">2</property>
           </packing>
         </child>
         <child>
           <object class="GtkEntry" id="name">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
           </object>
           <packing>
             <property name="left_attach">1</property>
-            <property name="top_attach">1</property>
+            <property name="top_attach">0</property>
           </packing>
         </child>
         <child>
           <object class="GtkEntry" id="type">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
           </object>
           <packing>
             <property name="left_attach">1</property>
-            <property name="top_attach">2</property>
+            <property name="top_attach">1</property>
           </packing>
         </child>
         <child>
           <object class="GtkEntry" id="value">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
           </object>
           <packing>
             <property name="left_attach">1</property>
-            <property name="top_attach">3</property>
+            <property name="top_attach">2</property>
           </packing>
         </child>
         <child>
           <object class="GtkScrolledWindow">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
             <property name="shadow_type">in</property>
             <child>
-              <object class="GtkTextView" id="comment">
+              <object class="GtkTextView">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="wrap_mode">word</property>
@@ -133,106 +128,107 @@
                 <property name="right_margin">8</property>
                 <property name="top_margin">8</property>
                 <property name="bottom_margin">8</property>
+                <property name="buffer">comment</property>
               </object>
             </child>
           </object>
           <packing>
             <property name="left_attach">3</property>
-            <property name="top_attach">2</property>
+            <property name="top_attach">1</property>
             <property name="height">2</property>
           </packing>
         </child>
         <child>
-          <object class="GtkButton">
-            <property name="label" translatable="yes">Delete</property>
+          <object class="GtkComboBoxText" id="direction">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
+            <property name="can_focus">False</property>
             <property name="halign">end</property>
             <property name="valign">center</property>
-            <style>
-              <class name="destructive-action"/>
-            </style>
+            <property name="active_id">undefined</property>
+            <items>
+              <item id="undefined" translatable="yes">Undefined</item>
+              <item id="in" translatable="yes">In</item>
+              <item id="out" translatable="yes">Out</item>
+              <item id="inout" translatable="yes">In &amp; Out</item>
+            </items>
           </object>
           <packing>
             <property name="left_attach">3</property>
-            <property name="top_attach">4</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="title">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="label" translatable="yes">Parameter</property>
-            <property name="xalign">0</property>
-            <style>
-              <class name="dim-label"/>
-            </style>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
             <property name="top_attach">0</property>
-            <property name="width">3</property>
           </packing>
         </child>
         <child>
           <object class="GtkBox">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="halign">end</property>
-            <property name="valign">center</property>
+            <property name="spacing">16</property>
             <child>
               <object class="GtkButton">
+                <property name="label" translatable="yes">Delete</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
-                <property name="image">image1</property>
+                <property name="halign">end</property>
+                <property name="valign">center</property>
+                <signal name="clicked" handler="gtk_widget_destroy" object="DiaUmlOperationParameterRow" 
swapped="yes"/>
+                <style>
+                  <class name="destructive-action"/>
+                </style>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">True</property>
+                <property name="pack_type">end</property>
                 <property name="position">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkButton">
+              <object class="GtkBox">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="image">image2</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="valign">center</property>
+                <child>
+                  <object class="GtkButton">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="image">image1</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="image">image2</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <style>
+                  <class name="linked"/>
+                </style>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">True</property>
-                <property name="position">1</property>
+                <property name="pack_type">end</property>
+                <property name="position">2</property>
               </packing>
             </child>
-            <style>
-              <class name="linked"/>
-            </style>
           </object>
           <packing>
             <property name="left_attach">3</property>
-            <property name="top_attach">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkComboBoxText" id="direction">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="halign">end</property>
-            <property name="valign">center</property>
-            <property name="active_id">undefined</property>
-            <items>
-              <item id="undefined" translatable="yes">Undefined</item>
-              <item id="in" translatable="yes">In</item>
-              <item id="out" translatable="yes">Out</item>
-              <item id="inout" translatable="yes">In &amp; Out</item>
-            </items>
-          </object>
-          <packing>
-            <property name="left_attach">3</property>
-            <property name="top_attach">1</property>
+            <property name="top_attach">3</property>
           </packing>
         </child>
         <child>
@@ -250,4 +246,14 @@
       </object>
     </child>
   </template>
+  <object class="GtkImage" id="image1">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="icon_name">go-up-symbolic</property>
+  </object>
+  <object class="GtkImage" id="image2">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="icon_name">go-down-symbolic</property>
+  </object>
 </interface>
diff --git a/objects/UML/class_dialog.h b/objects/UML/class_dialog.h
index 65eb6565..36e6386d 100644
--- a/objects/UML/class_dialog.h
+++ b/objects/UML/class_dialog.h
@@ -110,12 +110,11 @@ void _operations_create_page(GtkNotebook *notebook,  UMLClass *umlclass);
 void _templates_create_page(GtkNotebook *notebook,  UMLClass *umlclass);
 
 #define DIA_UML_TYPE_OPERATION_DIALOG (dia_uml_operation_dialog_get_type ())
-G_DECLARE_FINAL_TYPE (DiaUmlOperationDialog, dia_uml_operation_dialog, DIA, UML_OPERATION_DIALOG, GtkDialog)
+G_DECLARE_FINAL_TYPE (DiaUmlOperationDialog, dia_uml_operation_dialog, DIA_UML, OPERATION_DIALOG, GtkDialog)
 
 struct _DiaUmlOperationDialog {
   GtkDialog parent;
 
-  GtkWidget *title;
   GtkWidget *name;
   GtkWidget *type;
   GtkWidget *stereotype;
@@ -129,4 +128,23 @@ struct _DiaUmlOperationDialog {
   DiaUmlOperation *operation;
 };
 
-GtkWidget *dia_uml_operation_dialog_new (DiaUmlOperation *op);
+GtkWidget *dia_uml_operation_dialog_new (GtkWindow       *parent,
+                                         DiaUmlOperation *op);
+
+#define DIA_UML_TYPE_OPERATION_PARAMETER_ROW (dia_uml_operation_parameter_row_get_type ())
+G_DECLARE_FINAL_TYPE (DiaUmlOperationParameterRow, dia_uml_operation_parameter_row, DIA_UML, 
OPERATION_PARAMETER_ROW, GtkListBoxRow)
+
+struct _DiaUmlOperationParameterRow {
+  GtkListBoxRow parent;
+
+  GtkWidget *name;
+  GtkWidget *type;
+  GtkWidget *value;
+  GtkWidget *direction;
+  GtkTextBuffer *comment;
+
+  DiaUmlParameter *parameter;
+};
+
+GtkWidget       *dia_uml_operation_parameter_row_new           (DiaUmlParameter             *parameter);
+DiaUmlParameter *dia_uml_operation_parameter_row_get_parameter (DiaUmlOperationParameterRow *self);
diff --git a/objects/UML/class_operations_dialog.c b/objects/UML/class_operations_dialog.c
index 812b3cf0..b4e58e3f 100644
--- a/objects/UML/class_operations_dialog.c
+++ b/objects/UML/class_operations_dialog.c
@@ -27,6 +27,174 @@
 #include "class_dialog.h"
 #include "dia_dirs.h"
 
+G_DEFINE_TYPE (DiaUmlOperationParameterRow, dia_uml_operation_parameter_row, GTK_TYPE_LIST_BOX_ROW)
+
+enum {
+  UML_OP_PROW_PROP_PARAMETER = 1,
+  UML_OP_PROW_N_PROPS
+};
+static GParamSpec* uml_op_prow_properties[UML_OP_PROW_N_PROPS];
+
+static void
+dia_uml_operation_parameter_row_finalize (GObject *object)
+{
+  DiaUmlOperationParameterRow *self = DIA_UML_OPERATION_PARAMETER_ROW (object);
+
+  g_object_unref (G_OBJECT (self->parameter));
+}
+
+gboolean
+direction_to (GBinding *binding,
+              const GValue *from_value,
+              GValue *to_value,
+              gpointer user_data)
+{
+  gchar *name = g_value_get_string (from_value);
+
+  if (g_strcmp0 (name, "in") == 0) {
+    g_value_set_int (to_value, UML_IN);
+  } else if (g_strcmp0 (name, "out") == 0) {
+    g_value_set_int (to_value, UML_OUT);
+  } else if (g_strcmp0 (name, "inout") == 0) {
+    g_value_set_int (to_value, UML_INOUT);
+  } else {
+    g_value_set_int (to_value, UML_UNDEF_KIND);
+  }
+  
+  return TRUE;
+}
+
+gboolean
+direction_from (GBinding *binding,
+                const GValue *from_value,
+                GValue *to_value,
+                gpointer user_data)
+{
+  int mode = g_value_get_int (from_value);
+
+  if (mode == UML_IN) {
+    g_value_set_static_string (to_value, "in");
+  } else if (mode == UML_OUT) {
+    g_value_set_static_string (to_value, "out");
+  } else if (mode == UML_INOUT) {
+    g_value_set_static_string (to_value, "inout");
+  } else {
+    g_value_set_static_string (to_value, "undefined");
+  }
+  
+  return TRUE;
+}
+
+static void
+dia_uml_operation_parameter_row_set_property (GObject      *object,
+                                       guint         property_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+  DiaUmlOperationParameterRow *self = DIA_UML_OPERATION_PARAMETER_ROW (object);
+  switch (property_id) {
+    case UML_OP_PROW_PROP_PARAMETER:
+      self->parameter = g_value_dup_object (value);
+      g_object_bind_property (G_OBJECT (self->parameter), "name",
+                              G_OBJECT (self->name), "text",
+                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+      g_object_bind_property (G_OBJECT (self->parameter), "type",
+                              G_OBJECT (self->type), "text",
+                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+      g_object_bind_property (G_OBJECT (self->parameter), "value",
+                              G_OBJECT (self->value), "text",
+                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+      g_object_bind_property_full (G_OBJECT (self->parameter), "kind",
+                                   G_OBJECT (self->direction), "active-id",
+                                   G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
+                                   direction_from,
+                                   direction_to,
+                                   NULL, NULL);
+
+      g_object_bind_property (G_OBJECT (self->parameter), "comment",
+                              G_OBJECT (self->comment), "text",
+                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+dia_uml_operation_parameter_row_get_property (GObject    *object,
+                                              guint       property_id,
+                                              GValue     *value,
+                                              GParamSpec *pspec)
+{
+  DiaUmlOperationParameterRow *self = DIA_UML_OPERATION_PARAMETER_ROW (object);
+  switch (property_id) {
+    case UML_OP_PROW_PROP_PARAMETER:
+      g_value_set_object (value, self->parameter);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+dia_uml_operation_parameter_row_class_init (DiaUmlOperationParameterRowClass *klass)
+{
+  GFile *template_file;
+  GBytes *template;
+  GError *err = NULL;
+  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = dia_uml_operation_parameter_row_finalize;
+  object_class->set_property = dia_uml_operation_parameter_row_set_property;
+  object_class->get_property = dia_uml_operation_parameter_row_get_property;
+
+  uml_op_prow_properties[UML_OP_PROW_PROP_PARAMETER] =
+    g_param_spec_object ("parameter",
+                         "Parameter",
+                         "Parameter this editor controls",
+                         DIA_UML_TYPE_PARAMETER,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+  g_object_class_install_properties (object_class,
+                                     UML_OP_PROW_N_PROPS,
+                                     uml_op_prow_properties);
+
+  /* TODO: Use GResource */
+  template_file = g_file_new_for_path (build_ui_filename ("ui/dia-uml-operation-parameter-row.ui"));
+  template = g_file_load_bytes (template_file, NULL, NULL, &err);
+
+  if (err)
+    g_critical ("Failed to load template: %s", err->message);
+
+  gtk_widget_class_set_template (widget_class, template);
+  gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationParameterRow, name);
+  gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationParameterRow, type);
+  gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationParameterRow, value);
+  gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationParameterRow, direction);
+  gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationParameterRow, comment);
+
+  g_object_unref (template_file);
+}
+
+static void
+dia_uml_operation_parameter_row_init (DiaUmlOperationParameterRow *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+GtkWidget *
+dia_uml_operation_parameter_row_new (DiaUmlParameter *op)
+{
+  return g_object_new (DIA_UML_TYPE_OPERATION_PARAMETER_ROW,
+                       "parameter", op, 
+                       NULL);
+}
+
 G_DEFINE_TYPE (DiaUmlOperationDialog, dia_uml_operation_dialog, GTK_TYPE_DIALOG)
 
 enum {
@@ -35,6 +203,94 @@ enum {
 };
 static GParamSpec* uml_op_dlg_properties[UML_OP_DLG_N_PROPS];
 
+static void
+dia_uml_operation_dialog_finalize (GObject *object)
+{
+  DiaUmlOperationDialog *self = DIA_UML_OPERATION_DIALOG (object);
+
+  g_object_unref (G_OBJECT (self->operation));
+}
+
+gboolean
+visibility_to (GBinding *binding,
+               const GValue *from_value,
+               GValue *to_value,
+               gpointer user_data)
+{
+  gchar *name = g_value_get_string (from_value);
+
+  if (g_strcmp0 (name, "private") == 0) {
+    g_value_set_int (to_value, UML_PRIVATE);
+  } else if (g_strcmp0 (name, "protected") == 0) {
+    g_value_set_int (to_value, UML_PROTECTED);
+  } else if (g_strcmp0 (name, "implementation") == 0) {
+    g_value_set_int (to_value, UML_IMPLEMENTATION);
+  } else {
+    g_value_set_int (to_value, UML_PUBLIC);
+  }
+  
+  return TRUE;
+}
+
+gboolean
+visibility_from (GBinding *binding,
+                 const GValue *from_value,
+                 GValue *to_value,
+                 gpointer user_data)
+{
+  int mode = g_value_get_int (from_value);
+
+  if (mode == UML_ABSTRACT) {
+    g_value_set_static_string (to_value, "abstract");
+  } else if (mode == UML_POLYMORPHIC) {
+    g_value_set_static_string (to_value, "poly");
+  } else {
+    g_value_set_static_string (to_value, "leaf");
+  }
+  
+  return TRUE;
+}
+
+gboolean
+inheritance_to (GBinding *binding,
+                const GValue *from_value,
+                GValue *to_value,
+                gpointer user_data)
+{
+  gchar *name = g_value_get_string (from_value);
+
+  if (g_strcmp0 (name, "abstract") == 0) {
+    g_value_set_int (to_value, UML_ABSTRACT);
+  } else if (g_strcmp0 (name, "poly") == 0) {
+    g_value_set_int (to_value, UML_POLYMORPHIC);
+  } else {
+    g_value_set_int (to_value, UML_LEAF);
+  }
+  
+  return TRUE;
+}
+
+gboolean
+inheritance_from (GBinding *binding,
+                  const GValue *from_value,
+                  GValue *to_value,
+                  gpointer user_data)
+{
+  int mode = g_value_get_int (from_value);
+
+  if (mode == UML_PRIVATE) {
+    g_value_set_static_string (to_value, "private");
+  } else if (mode == UML_PROTECTED) {
+    g_value_set_static_string (to_value, "protected");
+  } else if (mode == UML_IMPLEMENTATION) {
+    g_value_set_static_string (to_value, "implementation");
+  } else {
+    g_value_set_static_string (to_value, "public");
+  }
+  
+  return TRUE;
+}
+
 static void
 dia_uml_operation_dialog_set_property (GObject      *object,
                                        guint         property_id,
@@ -42,9 +298,12 @@ dia_uml_operation_dialog_set_property (GObject      *object,
                                        GParamSpec   *pspec)
 {
   DiaUmlOperationDialog *self = DIA_UML_OPERATION_DIALOG (object);
+  GList *paras;
+  GtkWidget *row;
+
   switch (property_id) {
     case UML_OP_DLG_PROP_OPERATION:
-      self->operation = g_value_get_object (value);
+      self->operation = g_value_dup_object (value);
       g_object_bind_property (G_OBJECT (self->operation), "name",
                               G_OBJECT (self->name), "text",
                               G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
@@ -58,12 +317,34 @@ dia_uml_operation_dialog_set_property (GObject      *object,
                               G_OBJECT (self->comment), "text",
                               G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
 
+      g_object_bind_property_full (G_OBJECT (self->operation), "visibility",
+                                   G_OBJECT (self->visibility), "active-id",
+                                   G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
+                                   visibility_from,
+                                   visibility_to,
+                                   NULL, NULL);
+
+      g_object_bind_property_full (G_OBJECT (self->operation), "inheritance-type",
+                                   G_OBJECT (self->inheritance), "active-id",
+                                   G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
+                                   inheritance_from,
+                                   inheritance_to,
+                                   NULL, NULL);
+
       g_object_bind_property (G_OBJECT (self->operation), "query",
                               G_OBJECT (self->query), "active",
                               G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
       g_object_bind_property (G_OBJECT (self->operation), "class-scope",
                               G_OBJECT (self->scope), "active",
                               G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+      paras = dia_uml_operation_get_parameters (self->operation);
+      for (; paras != NULL; paras = g_list_next (paras)) {
+        // do something with l->data
+        row = dia_uml_operation_parameter_row_new (DIA_UML_PARAMETER (paras->data));
+        gtk_widget_show (row);
+        gtk_container_add (GTK_CONTAINER (self->list), row);
+      }
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -88,6 +369,50 @@ dia_uml_operation_dialog_get_property (GObject    *object,
   }
 }
 
+static void
+dlg_add_parameter (DiaUmlOperationDialog *self)
+{
+  GtkWidget *row = dia_uml_operation_parameter_row_new (dia_uml_parameter_new ());
+
+  g_assert (DIA_UML_IS_OPERATION_DIALOG (self));
+  gtk_widget_show (row);
+  gtk_container_add (GTK_CONTAINER (self->list), row);
+}
+
+static void
+parameter_added (DiaUmlOperationDialog *self,
+                 GtkWidget             *row)
+{
+  DiaUmlParameter *para = NULL;
+  int index;
+
+  if (!DIA_UML_IS_OPERATION_PARAMETER_ROW (row))
+    return;
+
+  g_object_get (G_OBJECT (row),
+                "parameter", &para,
+                NULL);
+  index = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row));
+
+  dia_uml_operation_insert_parameter (self->operation, para, index);
+}
+
+static void
+parameter_removed (DiaUmlOperationDialog *self,
+                   GtkWidget             *row)
+{
+  DiaUmlParameter *para = NULL;
+
+  if (!DIA_UML_IS_OPERATION_PARAMETER_ROW (row) || gtk_widget_in_destruction (GTK_WIDGET (self)))
+    return;
+
+  g_object_get (G_OBJECT (row),
+                "parameter", &para,
+                NULL);
+
+  dia_uml_operation_remove_parameter (self->operation, para);
+}
+
 static void
 dia_uml_operation_dialog_class_init (DiaUmlOperationDialogClass *klass)
 {
@@ -97,6 +422,7 @@ dia_uml_operation_dialog_class_init (DiaUmlOperationDialogClass *klass)
   GObjectClass   *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
+  object_class->finalize = dia_uml_operation_dialog_finalize;
   object_class->set_property = dia_uml_operation_dialog_set_property;
   object_class->get_property = dia_uml_operation_dialog_get_property;
 
@@ -119,7 +445,6 @@ dia_uml_operation_dialog_class_init (DiaUmlOperationDialogClass *klass)
     g_critical ("Failed to load template: %s", err->message);
 
   gtk_widget_class_set_template (widget_class, template);
-  gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationDialog, title);
   gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationDialog, name);
   gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationDialog, type);
   gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationDialog, stereotype);
@@ -129,6 +454,9 @@ dia_uml_operation_dialog_class_init (DiaUmlOperationDialogClass *klass)
   gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationDialog, query);
   gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationDialog, comment);
   gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationDialog, list);
+  gtk_widget_class_bind_template_callback (widget_class, dlg_add_parameter);
+  gtk_widget_class_bind_template_callback (widget_class, parameter_added);
+  gtk_widget_class_bind_template_callback (widget_class, parameter_removed);
 
   g_object_unref (template_file);
 }
@@ -136,19 +464,36 @@ dia_uml_operation_dialog_class_init (DiaUmlOperationDialogClass *klass)
 static void
 dia_uml_operation_dialog_init (DiaUmlOperationDialog *self)
 {
+  GtkWidget *box;
+  GtkWidget *widget;
+
   gtk_widget_init_template (GTK_WIDGET (self));
+
+  box = g_object_new (GTK_TYPE_BOX,
+                      "orientation", GTK_ORIENTATION_VERTICAL,
+                      "spacing", 16,
+                      "margin", 16,
+                      NULL);
+  gtk_widget_show (box);
+
+  widget = gtk_label_new ("No parameters");
+  gtk_widget_show (widget);
+  gtk_container_add (GTK_CONTAINER (box), widget);
+
+  gtk_list_box_set_placeholder (GTK_LIST_BOX (self->list), box);
 }
 
 GtkWidget *
-dia_uml_operation_dialog_new (DiaUmlOperation *op)
+dia_uml_operation_dialog_new (GtkWindow       *parent,
+                              DiaUmlOperation *op)
 {
   return g_object_new (DIA_UML_TYPE_OPERATION_DIALOG,
-                       "operation", op, 
+                       "operation", op,
+                       "transient-for", parent,
+                       "modal", TRUE,
                        NULL);
 }
 
-
-
 /*************************************************************
  ******************** OPERATIONS *****************************
  *************************************************************/
@@ -164,7 +509,7 @@ parameters_set_sensitive(UMLClassDialog *prop_dialog, gint val)
 }
 
 static void
-parameters_set_values(UMLClassDialog *prop_dialog, UMLParameter *param)
+parameters_set_values(UMLClassDialog *prop_dialog, DiaUmlParameter *param)
 {
   gtk_entry_set_text(prop_dialog->param_name, param->name);
   gtk_entry_set_text(prop_dialog->param_type, param->type);
@@ -192,7 +537,7 @@ parameters_clear_values(UMLClassDialog *prop_dialog)
 }
 
 static void
-parameters_get_values (UMLClassDialog *prop_dialog, UMLParameter *param)
+parameters_get_values (UMLClassDialog *prop_dialog, DiaUmlParameter *param)
 {
   g_free(param->name);
   g_free(param->type);
@@ -212,17 +557,17 @@ parameters_get_values (UMLClassDialog *prop_dialog, UMLParameter *param)
 static void
 parameters_get_current_values(UMLClassDialog *prop_dialog)
 {
-  UMLParameter *current_param;
+  DiaUmlParameter *current_param;
   GtkLabel *label;
   char *new_str;
 
   if (prop_dialog->current_param != NULL) {
-    current_param = (UMLParameter *)
+    current_param = (DiaUmlParameter *)
       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);
+      new_str = dia_uml_parameter_format(current_param);
       gtk_label_set_text(label, new_str);
       g_free(new_str);
     }
@@ -236,7 +581,7 @@ parameters_list_selection_changed_callback(GtkWidget *gtklist,
 {
   UMLClassDialog *prop_dialog;
   GObject *list_item;
-  UMLParameter *param;
+  DiaUmlParameter *param;
 
   prop_dialog = umlclass->properties_dialog;
 
@@ -253,7 +598,7 @@ parameters_list_selection_changed_callback(GtkWidget *gtklist,
     return;
   }
   
-  param = (UMLParameter *)g_object_get_data(G_OBJECT(list_item), "user_data");
+  param = (DiaUmlParameter *)g_object_get_data(G_OBJECT(list_item), "user_data");
   parameters_set_values(prop_dialog, param);
   parameters_set_sensitive(prop_dialog, TRUE);
 
@@ -269,7 +614,7 @@ parameters_list_new_callback(GtkWidget *button,
   UMLClassDialog *prop_dialog;
   GtkWidget *list_item;
   DiaUmlOperation *current_op;
-  UMLParameter *param;
+  DiaUmlParameter *param;
   char *utf;
 
   prop_dialog = umlclass->properties_dialog;
@@ -279,9 +624,9 @@ parameters_list_new_callback(GtkWidget *button,
   current_op = (DiaUmlOperation *)
     g_object_get_data(G_OBJECT(prop_dialog->current_op), "user_data");
   
-  param = uml_parameter_new();
+  param = dia_uml_parameter_new();
 
-  utf = uml_get_parameter_string (param);
+  utf = dia_uml_parameter_format (param);
   list_item = dia_list_item_new_with_label (utf);
   gtk_widget_show (list_item);
   g_free (utf);
@@ -310,7 +655,7 @@ parameters_list_delete_callback(GtkWidget *button,
   UMLClassDialog *prop_dialog;
   DiaList *gtklist;
   DiaUmlOperation *current_op;
-  UMLParameter *param;
+  DiaUmlParameter *param;
   
   prop_dialog = umlclass->properties_dialog;
   gtklist = DIA_LIST(prop_dialog->parameters_list);
@@ -320,12 +665,12 @@ parameters_list_delete_callback(GtkWidget *button,
     /* Remove from current operations parameter list: */
     current_op = (DiaUmlOperation *)
       g_object_get_data(G_OBJECT(prop_dialog->current_op), "user_data");
-    param = (UMLParameter *)
+    param = (DiaUmlParameter *)
       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_unref (G_OBJECT (param));
     
     /* Remove from gtk list: */
     list = g_list_prepend(NULL, prop_dialog->current_param);
@@ -346,7 +691,7 @@ parameters_list_move_up_callback(GtkWidget *button,
   DiaList *gtklist;
   DiaListItem *list_item;
   DiaUmlOperation *current_op;
-  UMLParameter *param;
+  DiaUmlParameter *param;
   int i;
   
   prop_dialog = umlclass->properties_dialog;
@@ -359,7 +704,7 @@ parameters_list_move_up_callback(GtkWidget *button,
     if (i>0)
       i--;
 
-    param = (UMLParameter *) g_object_get_data(G_OBJECT(list_item), "user_data");
+    param = (DiaUmlParameter *) g_object_get_data(G_OBJECT(list_item), "user_data");
 
     /* Move parameter in current operations list: */
     current_op = (DiaUmlOperation *)
@@ -393,7 +738,7 @@ parameters_list_move_down_callback(GtkWidget *button,
   DiaList *gtklist;
   DiaListItem *list_item;
   DiaUmlOperation *current_op;
-  UMLParameter *param;
+  DiaUmlParameter *param;
   int i;
   
   prop_dialog = umlclass->properties_dialog;
@@ -406,7 +751,7 @@ parameters_list_move_down_callback(GtkWidget *button,
     if (i<(g_list_length(dia_list_get_children (DIA_LIST (gtklist)))-1))
       i++;
 
-    param = (UMLParameter *) g_object_get_data(G_OBJECT(list_item), "user_data");
+    param = (DiaUmlParameter *) g_object_get_data(G_OBJECT(list_item), "user_data");
 
     /* Move parameter in current operations list: */
     current_op = (DiaUmlOperation *)
@@ -453,7 +798,7 @@ static void
 operations_set_values(UMLClassDialog *prop_dialog, DiaUmlOperation *op)
 {
   GList *list;
-  UMLParameter *param;
+  DiaUmlParameter *param;
   GtkWidget *list_item;
   gchar *str;
 
@@ -484,9 +829,9 @@ operations_set_values(UMLClassDialog *prop_dialog, DiaUmlOperation *op)
 
   list = op->parameters;
   while (list != NULL) {
-    param = (UMLParameter *)list->data;
+    param = (DiaUmlParameter *)list->data;
 
-    str = uml_get_parameter_string (param);
+    str = dia_uml_parameter_format (param);
     list_item = dia_list_item_new_with_label (str);
     g_free (str);
 
@@ -700,7 +1045,7 @@ operations_list_edit_callback (GtkWidget *button,
     op = (DiaUmlOperation *)
       g_object_get_data (G_OBJECT (dia_list_get_selection (DIA_LIST (gtklist))), "user_data");
 
-    edit = dia_uml_operation_dialog_new (op);
+    edit = dia_uml_operation_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (prop_dialog->dialog)), op);
     gtk_widget_show (edit);
   }
 }
@@ -719,19 +1064,19 @@ operations_list_move_up_callback(GtkWidget *button,
   gtklist = DIA_LIST(prop_dialog->operations_list);
 
   if (dia_list_get_selection (DIA_LIST (gtklist)) != NULL) {
-    list_item = GTK_WIDGET (dia_list_get_selection (DIA_LIST (gtklist)));
+    DiaListItem *list_item = dia_list_get_selection (DIA_LIST (gtklist));
     
-    i = dia_list_child_position(gtklist, list_item);
+    i = dia_list_child_position (gtklist, list_item);
     if (i>0)
       i--;
 
     g_object_ref(list_item);
-    list = g_list_prepend(NULL, list_item);
-    dia_list_remove_items(gtklist, list);
-    dia_list_insert_items(gtklist, list, i);
-    g_object_unref(list_item);
+    list = g_list_prepend (NULL, list_item);
+    dia_list_remove_items (gtklist, list);
+    dia_list_insert_items (gtklist, list, i);
+    g_object_unref (list_item);
 
-    dia_list_select_child(gtklist, list_item);
+    dia_list_select_child (gtklist, list_item);
   }
 
 }
@@ -1064,7 +1409,7 @@ operations_parameters_editor_create_vbox (UMLClass *umlclass)
   list = dia_list_new ();
   prop_dialog->parameters_list = DIA_LIST(list);
   dia_list_set_selection_mode (DIA_LIST (list), GTK_SELECTION_SINGLE);
-  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
+  gtk_container_add (GTK_CONTAINER (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);
@@ -1262,7 +1607,7 @@ _operations_create_page(GtkNotebook *notebook,  UMLClass *umlclass)
   list = dia_list_new ();
   prop_dialog->operations_list = DIA_LIST(list);
   dia_list_set_selection_mode (DIA_LIST (list), GTK_SELECTION_SINGLE);
-  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
+  gtk_container_add (GTK_CONTAINER (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);
diff --git a/objects/UML/uml.h b/objects/UML/uml.h
index 73bdf999..c1e073a3 100644
--- a/objects/UML/uml.h
+++ b/objects/UML/uml.h
@@ -27,9 +27,10 @@
 #include "dia_xml.h"
 
 typedef struct _UMLAttribute UMLAttribute;
-typedef struct _UMLParameter UMLParameter;
 typedef struct _UMLFormalParameter UMLFormalParameter;
 
+/* TODO: enums as GEnum for _spec_enum ext */
+
 /** the visibility (allowed acces) of (to) various UML sub elements */
 typedef enum _UMLVisibility {
   UML_PUBLIC, /**< everyone can use it */
@@ -92,7 +93,7 @@ struct _DiaUmlOperation {
   UMLInheritanceType inheritance_type;
   int query; /**< Do not modify the object, in C++ this is a const function */
   int class_scope;
-  GList *parameters; /**< List of UMLParameter */
+  GList *parameters; /**< List of DiaUmlParameter */
 
   ConnectionPoint* left_connection; /**< left */
   ConnectionPoint* right_connection; /**< right */
@@ -104,10 +105,15 @@ struct _DiaUmlOperation {
 };
 
 
-/** \brief A list of UMLParameter is contained in DiaUmlOperation
+#define DIA_UML_TYPE_PARAMETER (dia_uml_parameter_get_type ())
+G_DECLARE_FINAL_TYPE (DiaUmlParameter, dia_uml_parameter, DIA_UML, PARAMETER, GObject)
+
+/** \brief A list of DiaUmlParameter is contained in DiaUmlOperation
  * Some would call them functions parameters ;)
  */
-struct _UMLParameter {
+struct _DiaUmlParameter {
+  GObject parent;
+
   gchar *name; /**<  name*/
   gchar *type; /**< return value */
   gchar *value; /**< Initialization,  can be NULL => No default value */
@@ -132,14 +138,11 @@ struct _UMLFormalParameter {
 /** calculated the 'formated' representation */
 extern gchar *uml_get_attribute_string (UMLAttribute *attribute);
 /** calculated the 'formated' representation */
-extern gchar *uml_get_parameter_string(UMLParameter *param);
-/** 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 UMLFormalParameter *uml_formalparameter_copy(UMLFormalParameter *param);
 extern void uml_attribute_destroy(UMLAttribute *attribute);
-extern void uml_parameter_destroy(UMLParameter *param);
 extern void uml_formalparameter_destroy(UMLFormalParameter *param);
 extern UMLAttribute *uml_attribute_new(void);
 
@@ -150,8 +153,18 @@ gchar           *dia_uml_operation_format                   (DiaUmlOperation *op
 DiaUmlOperation *dia_uml_operation_copy                     (DiaUmlOperation *op);
 void             dia_uml_operation_ensure_connection_points (DiaUmlOperation *oper,
                                                              DiaObject       *obj);
+void             dia_uml_operation_insert_parameter         (DiaUmlOperation *self,
+                                                             DiaUmlParameter *parameter,
+                                                             int              index);
+void             dia_uml_operation_remove_parameter         (DiaUmlOperation *self,
+                                                             DiaUmlParameter *parameter);
+GList           *dia_uml_operation_get_parameters           (DiaUmlOperation *self);
+
+
+DiaUmlParameter *dia_uml_parameter_new                      ();
+/** calculated the 'formated' representation */
+gchar           *dia_uml_parameter_format                   (DiaUmlParameter *param);
 
-extern UMLParameter *uml_parameter_new(void);
 extern UMLFormalParameter *uml_formalparameter_new(void);
 
 extern void uml_attribute_ensure_connection_points (UMLAttribute *attr, DiaObject* obj);
diff --git a/objects/UML/umloperation.c b/objects/UML/umloperation.c
index cc5cd53e..1378f2bd 100644
--- a/objects/UML/umloperation.c
+++ b/objects/UML/umloperation.c
@@ -119,8 +119,8 @@ DiaUmlOperation *
 dia_uml_operation_copy (DiaUmlOperation *srcop)
 {
   DiaUmlOperation *destop;
-  UMLParameter *param;
-  UMLParameter *newparam;
+  DiaUmlParameter *param;
+  DiaUmlParameter *newparam;
   GList *list;
   
   destop = g_object_new (DIA_UML_TYPE_OPERATION, NULL);
@@ -166,16 +166,16 @@ dia_uml_operation_copy (DiaUmlOperation *srcop)
 
   list = destop->parameters;
   while (list != NULL) {
-    param = (UMLParameter *)list->data;
-    uml_parameter_destroy(param);
+    param = (DiaUmlParameter *)list->data;
+    g_object_unref (G_OBJECT (param));
     list = g_list_next(list);
   }
   destop->parameters = NULL;
   list = srcop->parameters;
   while (list != NULL) {
-    param = (UMLParameter *)list->data;
+    param = (DiaUmlParameter *)list->data;
 
-    newparam = g_new0(UMLParameter, 1);
+    newparam = g_new0(DiaUmlParameter, 1);
     newparam->name = g_strdup(param->name);
     newparam->type = g_strdup(param->type);
     newparam->comment = g_strdup(param->comment);
@@ -208,7 +208,7 @@ void
 uml_operation_write(AttributeNode attr_node, DiaUmlOperation *op, DiaContext *ctx)
 {
   GList *list;
-  UMLParameter *param;
+  DiaUmlParameter *param;
   DataNode composite;
   DataNode composite2;
   AttributeNode attr_node2;
@@ -239,7 +239,7 @@ uml_operation_write(AttributeNode attr_node, DiaUmlOperation *op, DiaContext *ct
   
   list = op->parameters;
   while (list != NULL) {
-    param = (UMLParameter *) list->data;
+    param = (DiaUmlParameter *) list->data;
 
     composite2 = data_add_composite(attr_node2, "umlparameter", ctx);
 
@@ -265,7 +265,7 @@ dia_uml_operation_format (DiaUmlOperation *operation)
   int len;
   char *str;
   GList *list;
-  UMLParameter *param;
+  DiaUmlParameter *param;
 
   /* Calculate length: */
   len = 1 + (operation->name ? strlen (operation->name) : 0) + 1;
@@ -275,7 +275,7 @@ dia_uml_operation_format (DiaUmlOperation *operation)
   
   list = operation->parameters;
   while (list != NULL) {
-    param = (UMLParameter  *) list->data;
+    param = (DiaUmlParameter  *) list->data;
     list = g_list_next (list);
     
     switch(param->kind)
@@ -334,7 +334,7 @@ dia_uml_operation_format (DiaUmlOperation *operation)
   
   list = operation->parameters;
   while (list != NULL) {
-    param = (UMLParameter  *) list->data;
+    param = (DiaUmlParameter  *) list->data;
     list = g_list_next (list);
     
     switch(param->kind)
@@ -416,7 +416,7 @@ static void
 dia_uml_operation_finalize (GObject *object)
 {
   GList *list;
-  UMLParameter *param;
+  DiaUmlParameter *param;
   DiaUmlOperation *self = DIA_UML_OPERATION (object);
   
   g_free (self->name);
@@ -429,8 +429,8 @@ dia_uml_operation_finalize (GObject *object)
 
   list = self->parameters;
   while (list != NULL) {
-    param = (UMLParameter *)list->data;
-    uml_parameter_destroy(param);
+    param = (DiaUmlParameter *)list->data;
+    g_object_unref (G_OBJECT (param));
     list = g_list_next(list);
   }
   if (self->wrappos) {
@@ -548,7 +548,7 @@ dia_uml_operation_class_init (DiaUmlOperationClass *klass)
   uml_op_properties[UML_OP_TYPE] = g_param_spec_string ("type",
                                                         "Type",
                                                         "Return type",
-                                                        NULL,
+                                                        "",
                                                         G_PARAM_READWRITE);
   uml_op_properties[UML_OP_COMMENT] = g_param_spec_string ("comment",
                                                            "Comment",
@@ -558,7 +558,7 @@ dia_uml_operation_class_init (DiaUmlOperationClass *klass)
   uml_op_properties[UML_OP_STEREOTYPE] = g_param_spec_string ("stereotype",
                                                               "Stereotype",
                                                               "Stereotype",
-                                                              NULL,
+                                                              "",
                                                               G_PARAM_READWRITE);
   uml_op_properties[UML_OP_VISIBILITY] = g_param_spec_int ("visibility",
                                                            "Visibility",
@@ -607,3 +607,21 @@ dia_uml_operation_new ()
 {
   return g_object_new (DIA_UML_TYPE_OPERATION, NULL);
 }
+
+void
+dia_uml_operation_insert_parameter (DiaUmlOperation *self,
+                                    DiaUmlParameter *parameter,
+                                    int              index)
+{
+  self->parameters = g_list_insert (self->parameters,
+                                    g_object_ref (G_OBJECT (parameter)),
+                                    index);
+}
+
+void
+dia_uml_operation_remove_parameter (DiaUmlOperation *self,
+                                    DiaUmlParameter *parameter)
+{
+  self->parameters = g_list_remove (self->parameters, parameter);
+  g_object_unref (G_OBJECT (parameter));
+}
diff --git a/objects/UML/umlparameter.c b/objects/UML/umlparameter.c
index 0fb35221..d7a0fa9a 100644
--- a/objects/UML/umlparameter.c
+++ b/objects/UML/umlparameter.c
@@ -30,6 +30,18 @@
 #include "uml.h"
 #include "properties.h"
 
+G_DEFINE_TYPE (DiaUmlParameter, dia_uml_parameter, G_TYPE_OBJECT)
+
+enum {
+  UML_PARA_NAME = 1,
+  UML_PARA_TYPE,
+  UML_PARA_VALUE,
+  UML_PARA_COMMENT,
+  UML_PARA_KIND,
+  UML_PARA_N_PROPS
+};
+static GParamSpec* uml_para_properties[UML_PARA_N_PROPS];
+
 static PropEnumData _uml_parameter_kinds[] = {
   { N_("Undefined"), UML_UNDEF_KIND} ,
   { N_("In"), UML_IN },
@@ -54,49 +66,22 @@ static PropDescription umlparameter_props[] = {
 };
 
 static PropOffset umlparameter_offsets[] = {
-  { "name", PROP_TYPE_STRING, offsetof(UMLParameter, name) },
-  { "type", PROP_TYPE_STRING, offsetof(UMLParameter, type) },
-  { "value", PROP_TYPE_STRING, offsetof(UMLParameter, value) },
-  { "comment", PROP_TYPE_MULTISTRING, offsetof(UMLParameter, comment) },
-  { "kind", PROP_TYPE_ENUM, offsetof(UMLParameter, kind) },
+  { "name", PROP_TYPE_STRING, offsetof(DiaUmlParameter, name) },
+  { "type", PROP_TYPE_STRING, offsetof(DiaUmlParameter, type) },
+  { "value", PROP_TYPE_STRING, offsetof(DiaUmlParameter, value) },
+  { "comment", PROP_TYPE_MULTISTRING, offsetof(DiaUmlParameter, comment) },
+  { "kind", PROP_TYPE_ENUM, offsetof(DiaUmlParameter, kind) },
   { NULL, 0, 0 },
 };
 
 PropDescDArrayExtra umlparameter_extra = {
   { umlparameter_props, umlparameter_offsets, "umlparameter" },
-  (NewRecordFunc)uml_parameter_new,
-  (FreeRecordFunc)uml_parameter_destroy
+  (NewRecordFunc) dia_uml_parameter_new,
+  (FreeRecordFunc) g_object_unref
 };
 
-UMLParameter *
-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->kind = UML_UNDEF_KIND;
-
-  return param;
-}
-
-void
-uml_parameter_destroy(UMLParameter *param)
-{
-  g_free(param->name);
-  g_free(param->type);
-  if (param->value != NULL) 
-    g_free(param->value);
-  g_free(param->comment);
-
-  g_free(param);
-}
-
 char *
-uml_get_parameter_string (UMLParameter *param)
+dia_uml_parameter_format (DiaUmlParameter *param)
 {
   int len;
   char *str;
@@ -157,3 +142,143 @@ uml_get_parameter_string (UMLParameter *param)
   return str;
 }
 
+static void
+dia_uml_parameter_finalize (GObject *object)
+{
+  DiaUmlParameter *self = DIA_UML_PARAMETER (object);
+
+  g_free (self->name);
+  g_free (self->type);
+  if (self->value != NULL) 
+    g_free (self->value);
+  g_free (self->comment);
+}
+
+static void
+dia_uml_parameter_set_property (GObject      *object,
+                                guint         property_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  DiaUmlParameter *self = DIA_UML_PARAMETER (object);
+
+  switch (property_id) {
+    case UML_PARA_NAME:
+      self->name = g_value_dup_string (value);
+      g_object_notify_by_pspec (object, uml_para_properties[UML_PARA_NAME]);
+      break;
+    case UML_PARA_TYPE:
+      self->type = g_value_dup_string (value);
+      g_object_notify_by_pspec (object, uml_para_properties[UML_PARA_TYPE]);
+      break;
+    case UML_PARA_VALUE:
+      self->value = g_value_dup_string (value);
+      g_object_notify_by_pspec (object, uml_para_properties[UML_PARA_VALUE]);
+      break;
+    case UML_PARA_COMMENT:
+      self->comment = g_value_dup_string (value);
+      g_object_notify_by_pspec (object, uml_para_properties[UML_PARA_COMMENT]);
+      break;
+    case UML_PARA_KIND:
+      self->kind = g_value_get_int (value);
+      g_object_notify_by_pspec (object, uml_para_properties[UML_PARA_KIND]);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+dia_uml_parameter_get_property (GObject    *object,
+                                guint       property_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  DiaUmlParameter *self = DIA_UML_PARAMETER (object);
+
+  switch (property_id) {
+    case UML_PARA_NAME:
+      g_value_set_string (value, self->name);
+      break;
+    case UML_PARA_TYPE:
+      g_value_set_string (value, self->type);
+      break;
+    case UML_PARA_VALUE:
+      g_value_set_string (value, self->value);
+      break;
+    case UML_PARA_COMMENT:
+      g_value_set_string (value, self->comment);
+      break;
+    case UML_PARA_KIND:
+      g_value_set_int (value, self->kind);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+dia_uml_parameter_class_init (DiaUmlParameterClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = dia_uml_parameter_finalize;
+  object_class->set_property = dia_uml_parameter_set_property;
+  object_class->get_property = dia_uml_parameter_get_property;
+
+  uml_para_properties[UML_PARA_NAME] = g_param_spec_string ("name",
+                                                            "Name",
+                                                            "Function name",
+                                                            "",
+                                                            G_PARAM_READWRITE);
+  uml_para_properties[UML_PARA_TYPE] = g_param_spec_string ("type",
+                                                            "Type",
+                                                            "Return type",
+                                                            "",
+                                                            G_PARAM_READWRITE);
+  uml_para_properties[UML_PARA_VALUE] = g_param_spec_string ("value",
+                                                             "Value",
+                                                             "Default value",
+                                                             "",
+                                                             G_PARAM_READWRITE);
+  uml_para_properties[UML_PARA_COMMENT] = g_param_spec_string ("comment",
+                                                               "Comment",
+                                                               "Comment",
+                                                               "",
+                                                               G_PARAM_READWRITE);
+  uml_para_properties[UML_PARA_KIND] = g_param_spec_int ("kind",
+                                                         "Kind",
+                                                         "Parameter type",
+                                                         UML_UNDEF_KIND,
+                                                         UML_INOUT,
+                                                         UML_UNDEF_KIND,
+                                                         G_PARAM_READWRITE);
+
+  g_object_class_install_properties (object_class,
+                                     UML_PARA_N_PROPS,
+                                     uml_para_properties);
+}
+
+static void
+dia_uml_parameter_init (DiaUmlParameter *self)
+{
+  self->name = g_strdup("");
+  self->type = g_strdup("");
+  self->comment = g_strdup("");
+  self->value = g_strdup("");
+  self->kind = UML_UNDEF_KIND;
+}
+
+DiaUmlParameter *
+dia_uml_parameter_new ()
+{
+  return g_object_new (DIA_UML_TYPE_PARAMETER, NULL);
+}
+
+GList *
+dia_uml_operation_get_parameters (DiaUmlOperation *self)
+{
+  return self->parameters;
+}


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