[dia/dia-next: 38/59] Operation as a GObject



commit 83540b45241665f4efd21a176fe79e0fe01d164a
Author: Zander Brown <zbrown gnome org>
Date:   Sat Dec 29 18:00:27 2018 +0000

    Operation as a GObject
    
    Start of a new editor, ironically fixing the old one in the proccess

 data/dia-uml-operation-dialog.ui        | 382 ++++++++++++++++++++++++++++++++
 data/dia-uml-operation-parameter-row.ui | 253 +++++++++++++++++++++
 lib/widgets/dialist.c                   |   3 +-
 objects/UML/class.c                     |  36 +--
 objects/UML/class_dialog.c              |  16 +-
 objects/UML/class_dialog.h              |  22 ++
 objects/UML/class_operations_dialog.c   | 229 +++++++++++++++----
 objects/UML/uml.h                       |  32 +--
 objects/UML/umloperation.c              | 312 +++++++++++++++++++-------
 9 files changed, 1123 insertions(+), 162 deletions(-)
---
diff --git a/data/dia-uml-operation-dialog.ui b/data/dia-uml-operation-dialog.ui
new file mode 100644
index 00000000..9f5557e8
--- /dev/null
+++ b/data/dia-uml-operation-dialog.ui
@@ -0,0 +1,382 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkTextBuffer" id="comment"/>
+  <template class="DiaUmlOperationDialog" parent="GtkDialog">
+    <property name="can_focus">False</property>
+    <property name="type_hint">dialog</property>
+    <child>
+      <placeholder/>
+    </child>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">never</property>
+            <property name="propagate_natural_width">True</property>
+            <property name="propagate_natural_height">True</property>
+            <child>
+              <object class="GtkViewport">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_left">8</property>
+                    <property name="margin_right">8</property>
+                    <property name="margin_top">8</property>
+                    <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>
+                        <property name="can_focus">False</property>
+                        <property name="row_spacing">8</property>
+                        <property name="column_spacing">8</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Name</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="name">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="valign">center</property>
+                            <property name="hexpand">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Type</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="type">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="valign">center</property>
+                            <property name="hexpand">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Stereotype</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="stereotype">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="valign">center</property>
+                            <property name="hexpand">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Visibility</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">2</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkComboBoxText" id="visibility">
+                            <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">public</property>
+                            <items>
+                              <item id="public" translatable="yes">Public</item>
+                              <item id="private" translatable="yes">Private</item>
+                              <item id="protected" translatable="yes">Protected</item>
+                              <item id="implementation" translatable="yes">Implementation</item>
+                            </items>
+                          </object>
+                          <packing>
+                            <property name="left_attach">3</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkComboBoxText" id="inheritance">
+                            <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">leaf</property>
+                            <items>
+                              <item id="abstract" translatable="yes">Abstract</item>
+                              <item id="poly" translatable="yes">Polymorphic (virtual)</item>
+                              <item id="leaf" translatable="yes">Leaf (final)</item>
+                            </items>
+                          </object>
+                          <packing>
+                            <property name="left_attach">3</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Inheritance</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">2</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Class scope</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">2</property>
+                            <property name="top_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Query</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">2</property>
+                            <property name="top_attach">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSwitch" id="scope">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="halign">end</property>
+                            <property name="valign">center</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">3</property>
+                            <property name="top_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkSwitch" id="query">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="halign">end</property>
+                            <property name="valign">center</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">3</property>
+                            <property name="top_attach">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="label" translatable="yes">Comment</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkScrolledWindow">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="shadow_type">in</property>
+                            <child>
+                              <object class="GtkTextView">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="wrap_mode">word</property>
+                                <property name="left_margin">8</property>
+                                <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">1</property>
+                            <property name="top_attach">3</property>
+                            <property name="height">2</property>
+                          </packing>
+                        </child>
+                        <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="halign">end</property>
+                            <property name="valign">center</property>
+                            <style>
+                              <class name="destructive-action"/>
+                            </style>
+                          </object>
+                          <packing>
+                            <property name="left_attach">3</property>
+                            <property name="top_attach">4</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Parameters</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">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkFrame">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label_xalign">0</property>
+                        <property name="label_yalign">0</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <object class="GtkListBox" id="list">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                          </object>
+                        </child>
+                        <child type="label_item">
+                          <placeholder/>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/data/dia-uml-operation-parameter-row.ui b/data/dia-uml-operation-parameter-row.ui
new file mode 100644
index 00000000..4dad4e81
--- /dev/null
+++ b/data/dia-uml-operation-parameter-row.ui
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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>
+  <template class="DiaUmlOperationParameterRow" parent="GtkListBoxRow">
+    <property name="width_request">100</property>
+    <property name="height_request">80</property>
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="hexpand">True</property>
+    <child>
+      <object class="GtkGrid">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin_left">8</property>
+        <property name="margin_right">8</property>
+        <property name="margin_top">8</property>
+        <property name="margin_bottom">8</property>
+        <property name="hexpand">True</property>
+        <property name="row_spacing">8</property>
+        <property name="column_spacing">8</property>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Name</property>
+            <property name="xalign">0</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Type</property>
+            <property name="xalign">0</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Direction</property>
+            <property name="xalign">0</property>
+          </object>
+          <packing>
+            <property name="left_attach">2</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Comment</property>
+            <property name="xalign">0</property>
+          </object>
+          <packing>
+            <property name="left_attach">2</property>
+            <property name="top_attach">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Value</property>
+            <property name="xalign">0</property>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="name">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="type">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="value">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTextView" id="comment">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="wrap_mode">word</property>
+                <property name="left_margin">8</property>
+                <property name="right_margin">8</property>
+                <property name="top_margin">8</property>
+                <property name="bottom_margin">8</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">3</property>
+            <property name="top_attach">2</property>
+            <property name="height">2</property>
+          </packing>
+        </child>
+        <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="halign">end</property>
+            <property name="valign">center</property>
+            <style>
+              <class name="destructive-action"/>
+            </style>
+          </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>
+            <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="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>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/lib/widgets/dialist.c b/lib/widgets/dialist.c
index 7f53c1b3..d2d7d033 100644
--- a/lib/widgets/dialist.c
+++ b/lib/widgets/dialist.c
@@ -313,7 +313,7 @@ dia_list_get_children (DiaList* self)
 
   g_return_val_if_fail (self != NULL, NULL);
 
-  result = gtk_container_get_children (GTK_CONTAINER (self));
+  result = gtk_container_get_children (GTK_CONTAINER (((DiaListPrivate *) dia_list_get_instance_private 
(self))->real));
 
   return result;
 }
@@ -546,6 +546,7 @@ dia_list_item_init (DiaListItem *self)
 {
   ((DiaListItemPrivate *) dia_list_item_get_instance_private (self))->label = g_object_new (GTK_TYPE_LABEL,
                                                                                             "xalign", 0.0,
+                                                                                            "visible", TRUE,
                                                                                             NULL);
 }
 
diff --git a/objects/UML/class.c b/objects/UML/class.c
index 0e9e2f52..808600bf 100644
--- a/objects/UML/class.c
+++ b/objects/UML/class.c
@@ -470,9 +470,9 @@ umlclass_set_props(UMLClass *umlclass, GPtrArray *props)
     }
     list = (!umlclass->visible_operations || umlclass->suppress_operations) ? NULL : umlclass->operations;
     while (list != NULL) {
-      UMLOperation *op = (UMLOperation *)list->data;
+      DiaUmlOperation *op = (DiaUmlOperation *)list->data;
 
-      uml_operation_ensure_connection_points (op, obj);
+      dia_uml_operation_ensure_connection_points (op, obj);
       obj->connections[i] = op->left_connection;
       obj->connections[i]->object = obj;
       i++;
@@ -994,8 +994,8 @@ umlclass_draw_operationbox(UMLClass *umlclass, DiaRenderer *renderer, Element *e
 
     list = umlclass->operations;
     while (list != NULL) {
-      UMLOperation *op = (UMLOperation *)list->data;
-      gchar* opstr = uml_get_operation_string(op);
+      DiaUmlOperation *op = (DiaUmlOperation *)list->data;
+      gchar* opstr = dia_uml_operation_format(op);
       real ascent;
 
       switch (op->inheritance_type) {
@@ -1306,7 +1306,7 @@ umlclass_update_data(UMLClass *umlclass)
     
   list = (!umlclass->visible_operations || umlclass->suppress_operations) ? NULL : umlclass->operations;
   while (list != NULL) {
-    UMLOperation *op = (UMLOperation *)list->data;
+    DiaUmlOperation *op = (DiaUmlOperation *)list->data;
 
     op->left_connection->pos.x = x;
     op->left_connection->pos.y = y;
@@ -1522,8 +1522,8 @@ umlclass_calculate_operation_data(UMLClass *umlclass)
     list = umlclass->operations;
     while (list != NULL)
     {
-      UMLOperation *op = (UMLOperation *) list->data;
-      gchar *opstr = uml_get_operation_string(op);
+      DiaUmlOperation *op = (DiaUmlOperation *) list->data;
+      gchar *opstr = dia_uml_operation_format(op);
       DiaFont   *Font;
       real       FontHeight;
 
@@ -1906,7 +1906,7 @@ umlclass_destroy(UMLClass *umlclass)
 {
   GList *list;
   UMLAttribute *attr;
-  UMLOperation *op;
+  DiaUmlOperation *op;
   UMLFormalParameter *param;
 
 #ifdef DEBUG
@@ -1940,10 +1940,10 @@ umlclass_destroy(UMLClass *umlclass)
   
   list = umlclass->operations;
   while (list != NULL) {
-    op = (UMLOperation *)list->data;
+    op = (DiaUmlOperation *)list->data;
     g_free(op->left_connection);
     g_free(op->right_connection);
-    uml_operation_destroy(op);
+    g_object_unref (G_OBJECT (op));
     list = g_list_next(list);
   }
   g_list_free(umlclass->operations);
@@ -2048,9 +2048,9 @@ umlclass_copy(UMLClass *umlclass)
   newumlclass->operations = NULL;
   list = umlclass->operations;
   while (list != NULL) {
-    UMLOperation *op = (UMLOperation *)list->data;
-    UMLOperation *newop = uml_operation_copy(op);
-    uml_operation_ensure_connection_points (newop, newobj);
+    DiaUmlOperation *op = (DiaUmlOperation *)list->data;
+    DiaUmlOperation *newop = dia_uml_operation_copy(op);
+    dia_uml_operation_ensure_connection_points (newop, newobj);
 
     newumlclass->operations = g_list_append(newumlclass->operations,
                                             newop);
@@ -2099,7 +2099,7 @@ umlclass_copy(UMLClass *umlclass)
        (!newumlclass->suppress_operations)) {
     list = newumlclass->operations;
     while (list != NULL) {
-      UMLOperation *op = (UMLOperation *)list->data;
+      DiaUmlOperation *op = (DiaUmlOperation *)list->data;
       newobj->connections[i++] = op->left_connection;
       newobj->connections[i++] = op->right_connection;
       
@@ -2132,7 +2132,7 @@ umlclass_save(UMLClass *umlclass, ObjectNode obj_node,
              DiaContext *ctx)
 {
   UMLAttribute *attr;
-  UMLOperation *op;
+  DiaUmlOperation *op;
   UMLFormalParameter *formal_param;
   GList *list;
   AttributeNode attr_node;
@@ -2218,7 +2218,7 @@ umlclass_save(UMLClass *umlclass, ObjectNode obj_node,
   attr_node = new_attribute(obj_node, "operations");
   list = umlclass->operations;
   while (list != NULL) {
-    op = (UMLOperation *) list->data;
+    op = (DiaUmlOperation *) list->data;
     uml_operation_write(attr_node, op, ctx);
     list = g_list_next(list);
   }
@@ -2350,10 +2350,10 @@ umlclass_load(ObjectNode obj_node, int version, DiaContext *ctx)
   /* Operations info: */
   list = umlclass->operations;
   while (list) {
-    UMLOperation *op = (UMLOperation *)list->data;
+    DiaUmlOperation *op = (DiaUmlOperation *)list->data;
     g_assert(op);
 
-    uml_operation_ensure_connection_points (op, obj);
+    dia_uml_operation_ensure_connection_points (op, obj);
     list = g_list_next(list);
   }
 
diff --git a/objects/UML/class_dialog.c b/objects/UML/class_dialog.c
index b898c6d7..9e4431d5 100644
--- a/objects/UML/class_dialog.c
+++ b/objects/UML/class_dialog.c
@@ -786,7 +786,7 @@ umlclass_free_state(UMLClassState *state)
 
   list = state->operations;
   while (list) {
-    uml_operation_destroy((UMLOperation *) list->data);
+    g_object_unref (G_OBJECT (list->data));
     list = g_list_next(list);
   }
   g_list_free(state->operations);
@@ -854,17 +854,13 @@ umlclass_get_state(UMLClass *umlclass)
     list = g_list_next(list);
   }
 
-  
+  /* TODO: Why? */
   state->operations = NULL;
   list = umlclass->operations;
   while (list != NULL) {
-    UMLOperation *op = (UMLOperation *)list->data;
-    UMLOperation *op_copy;
-      
-    op_copy = uml_operation_copy(op);
-    op_copy->left_connection = op->left_connection;
-    op_copy->right_connection = op->right_connection;
-    state->operations = g_list_append(state->operations, op_copy);
+    DiaUmlOperation *op = (DiaUmlOperation *)list->data;
+
+    state->operations = g_list_append(state->operations, op);
     list = g_list_next(list);
   }
 
@@ -940,7 +936,7 @@ umlclass_update_connectionpoints(UMLClass *umlclass)
 
   list = umlclass->operations;
   while (list != NULL) {
-    UMLOperation *op = (UMLOperation *) list->data;
+    DiaUmlOperation *op = (DiaUmlOperation *) list->data;
     
     if ( (umlclass->visible_operations) &&
         (!umlclass->suppress_operations)) {
diff --git a/objects/UML/class_dialog.h b/objects/UML/class_dialog.h
index f3c538b5..65eb6565 100644
--- a/objects/UML/class_dialog.h
+++ b/objects/UML/class_dialog.h
@@ -108,3 +108,25 @@ void _templates_read_from_dialog(UMLClass *umlclass, UMLClassDialog *prop_dialog
 void _attributes_create_page(GtkNotebook *notebook,  UMLClass *umlclass);
 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)
+
+struct _DiaUmlOperationDialog {
+  GtkDialog parent;
+
+  GtkWidget *title;
+  GtkWidget *name;
+  GtkWidget *type;
+  GtkWidget *stereotype;
+  GtkWidget *visibility;
+  GtkWidget *inheritance;
+  GtkWidget *scope;
+  GtkWidget *query;
+  GtkTextBuffer *comment;
+  GtkWidget *list;
+
+  DiaUmlOperation *operation;
+};
+
+GtkWidget *dia_uml_operation_dialog_new (DiaUmlOperation *op);
diff --git a/objects/UML/class_operations_dialog.c b/objects/UML/class_operations_dialog.c
index 3c02cc11..812b3cf0 100644
--- a/objects/UML/class_operations_dialog.c
+++ b/objects/UML/class_operations_dialog.c
@@ -25,6 +25,129 @@
 #include "diaoptionmenu.h"
 
 #include "class_dialog.h"
+#include "dia_dirs.h"
+
+G_DEFINE_TYPE (DiaUmlOperationDialog, dia_uml_operation_dialog, GTK_TYPE_DIALOG)
+
+enum {
+  UML_OP_DLG_PROP_OPERATION = 1,
+  UML_OP_DLG_N_PROPS
+};
+static GParamSpec* uml_op_dlg_properties[UML_OP_DLG_N_PROPS];
+
+static void
+dia_uml_operation_dialog_set_property (GObject      *object,
+                                       guint         property_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+  DiaUmlOperationDialog *self = DIA_UML_OPERATION_DIALOG (object);
+  switch (property_id) {
+    case UML_OP_DLG_PROP_OPERATION:
+      self->operation = g_value_get_object (value);
+      g_object_bind_property (G_OBJECT (self->operation), "name",
+                              G_OBJECT (self->name), "text",
+                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+      g_object_bind_property (G_OBJECT (self->operation), "type",
+                              G_OBJECT (self->type), "text",
+                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+      g_object_bind_property (G_OBJECT (self->operation), "stereotype",
+                              G_OBJECT (self->stereotype), "text",
+                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+      g_object_bind_property (G_OBJECT (self->operation), "comment",
+                              G_OBJECT (self->comment), "text",
+                              G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+      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);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+dia_uml_operation_dialog_get_property (GObject    *object,
+                                       guint       property_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+  DiaUmlOperationDialog *self = DIA_UML_OPERATION_DIALOG (object);
+  switch (property_id) {
+    case UML_OP_DLG_PROP_OPERATION:
+      g_value_set_object (value, self->operation);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+dia_uml_operation_dialog_class_init (DiaUmlOperationDialogClass *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->set_property = dia_uml_operation_dialog_set_property;
+  object_class->get_property = dia_uml_operation_dialog_get_property;
+
+  uml_op_dlg_properties[UML_OP_DLG_PROP_OPERATION] =
+    g_param_spec_object ("operation",
+                         "Operation",
+                         "Operation this editor controls",
+                         DIA_UML_TYPE_OPERATION,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+  g_object_class_install_properties (object_class,
+                                     UML_OP_DLG_N_PROPS,
+                                     uml_op_dlg_properties);
+
+  /* TODO: Use GResource */
+  template_file = g_file_new_for_path (build_ui_filename ("ui/dia-uml-operation-dialog.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, 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);
+  gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationDialog, visibility);
+  gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationDialog, inheritance);
+  gtk_widget_class_bind_template_child (widget_class, DiaUmlOperationDialog, scope);
+  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);
+
+  g_object_unref (template_file);
+}
+
+static void
+dia_uml_operation_dialog_init (DiaUmlOperationDialog *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+GtkWidget *
+dia_uml_operation_dialog_new (DiaUmlOperation *op)
+{
+  return g_object_new (DIA_UML_TYPE_OPERATION_DIALOG,
+                       "operation", op, 
+                       NULL);
+}
+
+
 
 /*************************************************************
  ******************** OPERATIONS *****************************
@@ -111,7 +234,6 @@ static void
 parameters_list_selection_changed_callback(GtkWidget *gtklist,
                                           UMLClass *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
   GObject *list_item;
   UMLParameter *param;
@@ -123,15 +245,14 @@ parameters_list_selection_changed_callback(GtkWidget *gtklist,
 
   parameters_get_current_values(prop_dialog);
   
-  list = dia_list_get_selection (DIA_LIST (gtklist));
-  if (!list) { /* No selected */
+  list_item = dia_list_get_selection (DIA_LIST (gtklist));
+  if (!list_item) { /* 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);
@@ -147,7 +268,7 @@ parameters_list_new_callback(GtkWidget *button,
   GList *list;
   UMLClassDialog *prop_dialog;
   GtkWidget *list_item;
-  UMLOperation *current_op;
+  DiaUmlOperation *current_op;
   UMLParameter *param;
   char *utf;
 
@@ -155,7 +276,7 @@ parameters_list_new_callback(GtkWidget *button,
 
   parameters_get_current_values(prop_dialog);
 
-  current_op = (UMLOperation *)
+  current_op = (DiaUmlOperation *)
     g_object_get_data(G_OBJECT(prop_dialog->current_op), "user_data");
   
   param = uml_parameter_new();
@@ -188,7 +309,7 @@ parameters_list_delete_callback(GtkWidget *button,
   GList *list;
   UMLClassDialog *prop_dialog;
   DiaList *gtklist;
-  UMLOperation *current_op;
+  DiaUmlOperation *current_op;
   UMLParameter *param;
   
   prop_dialog = umlclass->properties_dialog;
@@ -197,7 +318,7 @@ parameters_list_delete_callback(GtkWidget *button,
 
   if (dia_list_get_selection (DIA_LIST (gtklist)) != NULL) {
     /* Remove from current operations parameter list: */
-    current_op = (UMLOperation *)
+    current_op = (DiaUmlOperation *)
       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");
@@ -224,7 +345,7 @@ parameters_list_move_up_callback(GtkWidget *button,
   UMLClassDialog *prop_dialog;
   DiaList *gtklist;
   DiaListItem *list_item;
-  UMLOperation *current_op;
+  DiaUmlOperation *current_op;
   UMLParameter *param;
   int i;
   
@@ -241,7 +362,7 @@ parameters_list_move_up_callback(GtkWidget *button,
     param = (UMLParameter *) g_object_get_data(G_OBJECT(list_item), "user_data");
 
     /* Move parameter in current operations list: */
-    current_op = (UMLOperation *)
+    current_op = (DiaUmlOperation *)
       g_object_get_data(G_OBJECT(prop_dialog->current_op), "user_data");
     
     current_op->parameters = g_list_remove(current_op->parameters,
@@ -271,7 +392,7 @@ parameters_list_move_down_callback(GtkWidget *button,
   UMLClassDialog *prop_dialog;
   DiaList *gtklist;
   DiaListItem *list_item;
-  UMLOperation *current_op;
+  DiaUmlOperation *current_op;
   UMLParameter *param;
   int i;
   
@@ -288,7 +409,7 @@ parameters_list_move_down_callback(GtkWidget *button,
     param = (UMLParameter *) g_object_get_data(G_OBJECT(list_item), "user_data");
 
     /* Move parameter in current operations list: */
-    current_op = (UMLOperation *)
+    current_op = (DiaUmlOperation *)
       g_object_get_data(G_OBJECT(prop_dialog->current_op), "user_data");
     
     current_op->parameters = g_list_remove(current_op->parameters,
@@ -329,7 +450,7 @@ operations_set_sensitive(UMLClassDialog *prop_dialog, gint val)
 }
 
 static void
-operations_set_values(UMLClassDialog *prop_dialog, UMLOperation *op)
+operations_set_values(UMLClassDialog *prop_dialog, DiaUmlOperation *op)
 {
   GList *list;
   UMLParameter *param;
@@ -394,7 +515,7 @@ operations_clear_values(UMLClassDialog *prop_dialog)
 
 
 static void
-operations_get_values(UMLClassDialog *prop_dialog, UMLOperation *op)
+operations_get_values(UMLClassDialog *prop_dialog, DiaUmlOperation *op)
 {
   const gchar *s;
 
@@ -424,19 +545,19 @@ operations_get_values(UMLClassDialog *prop_dialog, UMLOperation *op)
 void
 _operations_get_current_values(UMLClassDialog *prop_dialog)
 {
-  UMLOperation *current_op;
+  DiaUmlOperation *current_op;
   GtkLabel *label;
   char *new_str;
 
   parameters_get_current_values(prop_dialog);
 
   if (prop_dialog->current_op != NULL) {
-    current_op = (UMLOperation *)
+    current_op = (DiaUmlOperation *)
       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);
+      new_str = dia_uml_operation_format(current_op);
       gtk_label_set_text (label, new_str);
       g_free (new_str);
     }
@@ -447,12 +568,12 @@ static void
 operations_list_item_destroy_callback(GtkWidget *list_item,
                                      gpointer data)
 {
-  UMLOperation *op;
+  DiaUmlOperation *op;
 
-  op = (UMLOperation *) g_object_get_data(G_OBJECT(list_item), "user_data");
+  op = (DiaUmlOperation *) g_object_get_data(G_OBJECT(list_item), "user_data");
 
   if (op != NULL) {
-    uml_operation_destroy(op);
+    g_object_unref (G_OBJECT (op));
     /*printf("Destroying operation list_item's user_data!\n");*/
   }
 }
@@ -461,10 +582,9 @@ static void
 operations_list_selection_changed_callback(GtkWidget *gtklist,
                                           UMLClass *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
   GObject *list_item;
-  UMLOperation *op;
+  DiaUmlOperation *op;
 
   prop_dialog = umlclass->properties_dialog;
 
@@ -473,16 +593,15 @@ operations_list_selection_changed_callback(GtkWidget *gtklist,
 
   _operations_get_current_values(prop_dialog);
   
-  list = dia_list_get_selection (DIA_LIST (gtklist));
-  if (!list) { /* No selected */
+  list_item = dia_list_get_selection (DIA_LIST (gtklist));
+  if (!list_item) { /* No selected */
     operations_set_sensitive(prop_dialog, FALSE);
     operations_clear_values(prop_dialog);
     prop_dialog->current_op = NULL;
     return;
   }
   
-  list_item = G_OBJECT(list->data);
-  op = (UMLOperation *)g_object_get_data(G_OBJECT(list_item), "user_data");
+  op = (DiaUmlOperation *)g_object_get_data(G_OBJECT(list_item), "user_data");
   operations_set_values(prop_dialog, op);
   operations_set_sensitive(prop_dialog, TRUE);
 
@@ -497,23 +616,23 @@ operations_list_new_callback(GtkWidget *button,
   GList *list;
   UMLClassDialog *prop_dialog;
   GtkWidget *list_item;
-  UMLOperation *op;
+  DiaUmlOperation *op;
   char *utfstr;
 
   prop_dialog = umlclass->properties_dialog;
 
   _operations_get_current_values(prop_dialog);
 
-  op = uml_operation_new();
+  op = dia_uml_operation_new();
   /* need to make new ConnectionPoints valid and remember them */
-  uml_operation_ensure_connection_points (op, &umlclass->element.object);
+  dia_uml_operation_ensure_connection_points (op, &umlclass->element.object);
   prop_dialog->added_connections = 
     g_list_prepend(prop_dialog->added_connections, op->left_connection);
   prop_dialog->added_connections = 
     g_list_prepend(prop_dialog->added_connections, op->right_connection);
 
 
-  utfstr = uml_get_operation_string (op);
+  utfstr = dia_uml_operation_format (op);
   list_item = dia_list_item_new_with_label (utfstr);
   gtk_widget_show (list_item);
   g_free (utfstr);
@@ -538,14 +657,14 @@ operations_list_delete_callback(GtkWidget *button,
   GList *list;
   UMLClassDialog *prop_dialog;
   DiaList *gtklist;
-  UMLOperation *op;
+  DiaUmlOperation *op;
   
 
   prop_dialog = umlclass->properties_dialog;
   gtklist = DIA_LIST(prop_dialog->operations_list);
 
   if (dia_list_get_selection (DIA_LIST (gtklist)) != NULL) {
-    op = (UMLOperation *)
+    op = (DiaUmlOperation *)
       g_object_get_data (G_OBJECT (dia_list_get_selection (DIA_LIST (gtklist))), "user_data");
 
     if (op->left_connection != NULL) {
@@ -565,6 +684,27 @@ operations_list_delete_callback(GtkWidget *button,
   }
 }
 
+static void
+operations_list_edit_callback (GtkWidget *button,
+                               UMLClass  *umlclass)
+{
+  UMLClassDialog *prop_dialog;
+  DiaList *gtklist;
+  DiaUmlOperation *op;
+  GtkWidget *edit;
+  
+  prop_dialog = umlclass->properties_dialog;
+  gtklist = DIA_LIST(prop_dialog->operations_list);
+
+  if (dia_list_get_selection (DIA_LIST (gtklist)) != NULL) {
+    op = (DiaUmlOperation *)
+      g_object_get_data (G_OBJECT (dia_list_get_selection (DIA_LIST (gtklist))), "user_data");
+
+    edit = dia_uml_operation_dialog_new (op);
+    gtk_widget_show (edit);
+  }
+}
+
 static void
 operations_list_move_up_callback(GtkWidget *button,
                                 UMLClass *umlclass)
@@ -632,7 +772,7 @@ _operations_read_from_dialog(UMLClass *umlclass,
                            int connection_index)
 {
   GList *list;
-  UMLOperation *op;
+  DiaUmlOperation *op;
   GtkWidget *list_item;
   GList *clear_list;
   DiaObject *obj;
@@ -645,8 +785,8 @@ _operations_read_from_dialog(UMLClass *umlclass,
   /* Free current operations: */
   list = umlclass->operations;
   while (list != NULL) {
-    op = (UMLOperation *)list->data;
-    uml_operation_destroy(op);
+    op = (DiaUmlOperation *)list->data;
+    g_object_unref (G_OBJECT (op));
     list = g_list_next(list);
   }
   g_list_free (umlclass->operations);
@@ -659,13 +799,13 @@ _operations_read_from_dialog(UMLClass *umlclass,
     list_item = GTK_WIDGET(list->data);
     
     clear_list = g_list_prepend (clear_list, list_item);
-    op = (UMLOperation *)
+    op = (DiaUmlOperation *)
       g_object_get_data(G_OBJECT(list_item), "user_data");
     g_object_set_data(G_OBJECT(list_item), "user_data", NULL);
     umlclass->operations = g_list_append(umlclass->operations, op);
     
     if (op->left_connection == NULL) {
-      uml_operation_ensure_connection_points (op, obj);
+      dia_uml_operation_ensure_connection_points (op, obj);
       
       prop_dialog->added_connections =
        g_list_prepend(prop_dialog->added_connections,
@@ -699,7 +839,7 @@ void
 _operations_fill_in_dialog(UMLClass *umlclass)
 {
   UMLClassDialog *prop_dialog;
-  UMLOperation *op_copy;
+  DiaUmlOperation *op_copy;
   GtkWidget *list_item;
   GList *list;
   int i;
@@ -710,11 +850,11 @@ _operations_fill_in_dialog(UMLClass *umlclass)
     i = 0;
     list = umlclass->operations;
     while (list != NULL) {
-      UMLOperation *op = (UMLOperation *)list->data;
-      gchar *opstr = uml_get_operation_string (op);
+      DiaUmlOperation *op = (DiaUmlOperation *)list->data;
+      gchar *opstr = dia_uml_operation_format (op);
 
       list_item = dia_list_item_new_with_label (opstr);
-      op_copy = uml_operation_copy (op);
+      op_copy = dia_uml_operation_copy (op);
       /* Looks wrong but is required for the complicate connections memory management */
       op_copy->left_connection = op->left_connection;
       op_copy->right_connection = op->right_connection;
@@ -1149,6 +1289,13 @@ _operations_create_page(GtkNotebook *notebook,  UMLClass *umlclass)
                    G_CALLBACK(operations_list_move_up_callback), umlclass);
   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, TRUE, 0);
   gtk_widget_show (button);
+
+  button = gtk_button_new_with_label (_("Edit"));
+  g_signal_connect (G_OBJECT (button), "clicked",
+                   G_CALLBACK(operations_list_edit_callback), umlclass);
+  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, TRUE, 0);
+  gtk_widget_show (button);
+
   button = gtk_button_new_with_label (_("Down"));
   g_signal_connect (G_OBJECT (button), "clicked",
                    G_CALLBACK(operations_list_move_down_callback), umlclass);
diff --git a/objects/UML/uml.h b/objects/UML/uml.h
index 0d30b0c2..73bdf999 100644
--- a/objects/UML/uml.h
+++ b/objects/UML/uml.h
@@ -27,7 +27,6 @@
 #include "dia_xml.h"
 
 typedef struct _UMLAttribute UMLAttribute;
-typedef struct _UMLOperation UMLOperation;
 typedef struct _UMLParameter UMLParameter;
 typedef struct _UMLFormalParameter UMLFormalParameter;
 
@@ -74,10 +73,15 @@ struct _UMLAttribute {
   ConnectionPoint* right_connection; /**< right */
 };
 
-/** \brief A list of UMLOperation is contained in UMLClass
+#define DIA_UML_TYPE_OPERATION (dia_uml_operation_get_type ())
+G_DECLARE_FINAL_TYPE (DiaUmlOperation, dia_uml_operation, DIA_UML, OPERATION, GObject)
+
+/** \brief A list of DiaUmlOperation is contained in UMLClass
  * Some would call them member functions ;)
  */
-struct _UMLOperation {
+struct _DiaUmlOperation {
+  GObject parent;
+
   gint internal_id; /**< Arbitrary integer to recognize operations after
                     * the user has shuffled them in the dialog. */
   gchar *name; /**< the function name */
@@ -100,7 +104,7 @@ struct _UMLOperation {
 };
 
 
-/** \brief A list of UMLParameter is contained in UMLOperation
+/** \brief A list of UMLParameter is contained in DiaUmlOperation
  * Some would call them functions parameters ;)
  */
 struct _UMLParameter {
@@ -111,7 +115,7 @@ struct _UMLParameter {
   UMLParameterKind kind; /**< Not currently used */
 };
 
-/** \brief A list of UMLFormalParameter is contained in UMLOperation
+/** \brief A list of UMLFormalParameter is contained in DiaUmlOperation
  * Some would call them template parameters ;)
  */
 struct _UMLFormalParameter {
@@ -128,30 +132,32 @@ struct _UMLFormalParameter {
 /** calculated the 'formated' representation */
 extern gchar *uml_get_attribute_string (UMLAttribute *attribute);
 /** calculated the 'formated' representation */
-extern gchar *uml_get_operation_string(UMLOperation *operation);
-/** 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 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);
+
+DiaUmlOperation *dia_uml_operation_new                      ();
+/** calculated the 'formated' representation */
+gchar           *dia_uml_operation_format                   (DiaUmlOperation *operation);
+/* TODO: Why */
+DiaUmlOperation *dia_uml_operation_copy                     (DiaUmlOperation *op);
+void             dia_uml_operation_ensure_connection_points (DiaUmlOperation *oper,
+                                                             DiaObject       *obj);
+
 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_operation_write(AttributeNode attr_node, DiaUmlOperation *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 bf7924cc..cc5cd53e 100644
--- a/objects/UML/umloperation.c
+++ b/objects/UML/umloperation.c
@@ -54,6 +54,21 @@ for c in theClasses :
 #include "uml.h"
 #include "properties.h"
 
+G_DEFINE_TYPE (DiaUmlOperation, dia_uml_operation, G_TYPE_OBJECT)
+
+enum {
+  UML_OP_NAME = 1,
+  UML_OP_TYPE,
+  UML_OP_COMMENT,
+  UML_OP_STEREOTYPE,
+  UML_OP_VISIBILITY,
+  UML_OP_INHERITANCE_TYPE,
+  UML_OP_QUERY,
+  UML_OP_CLASS_SCOPE,
+  UML_OP_N_PROPS
+};
+static GParamSpec* uml_op_properties[UML_OP_N_PROPS];
+
 extern PropEnumData _uml_visibilities[];
 extern PropEnumData _uml_inheritances[];
 
@@ -82,50 +97,33 @@ static PropDescription umloperation_props[] = {
 };
 
 static PropOffset umloperation_offsets[] = {
-  { "name", PROP_TYPE_STRING, offsetof(UMLOperation, name) },
-  { "type", PROP_TYPE_STRING, offsetof(UMLOperation, type) },
-  { "comment", PROP_TYPE_MULTISTRING, offsetof(UMLOperation, comment) },
-  { "stereotype", PROP_TYPE_STRING, offsetof(UMLOperation, stereotype) },
-  { "visibility", PROP_TYPE_ENUM, offsetof(UMLOperation, visibility) },
-  { "inheritance_type", PROP_TYPE_ENUM, offsetof(UMLOperation, inheritance_type) },
-  { "query", PROP_TYPE_BOOL, offsetof(UMLOperation, query) },
-  { "class_scope", PROP_TYPE_BOOL, offsetof(UMLOperation, class_scope) },
-  { "parameters", PROP_TYPE_DARRAY, offsetof(UMLOperation, parameters) },
+  { "name", PROP_TYPE_STRING, offsetof(DiaUmlOperation, name) },
+  { "type", PROP_TYPE_STRING, offsetof(DiaUmlOperation, type) },
+  { "comment", PROP_TYPE_MULTISTRING, offsetof(DiaUmlOperation, comment) },
+  { "stereotype", PROP_TYPE_STRING, offsetof(DiaUmlOperation, stereotype) },
+  { "visibility", PROP_TYPE_ENUM, offsetof(DiaUmlOperation, visibility) },
+  { "inheritance_type", PROP_TYPE_ENUM, offsetof(DiaUmlOperation, inheritance_type) },
+  { "query", PROP_TYPE_BOOL, offsetof(DiaUmlOperation, query) },
+  { "class_scope", PROP_TYPE_BOOL, offsetof(DiaUmlOperation, class_scope) },
+  { "parameters", PROP_TYPE_DARRAY, offsetof(DiaUmlOperation, parameters) },
   { NULL, 0, 0 },
 };
 
 PropDescDArrayExtra umloperation_extra = {
   { umloperation_props, umloperation_offsets, "umloperation" },
-  (NewRecordFunc)uml_operation_new,
-  (FreeRecordFunc)uml_operation_destroy
+  (NewRecordFunc) dia_uml_operation_new,
+  (FreeRecordFunc) g_object_unref
 };
 
-UMLOperation *
-uml_operation_new(void)
-{
-  UMLOperation *op;
-  static gint next_id = 1;
-
-  op = g_new0(UMLOperation, 1);
-  op->internal_id = next_id++;
-  op->name = g_strdup("");
-  op->comment = g_strdup("");
-  op->visibility = UML_PUBLIC;
-  op->inheritance_type = UML_LEAF;
-
-#if 0 /* setup elsewhere */
-  op->left_connection = g_new0(ConnectionPoint, 1);
-  op->right_connection = g_new0(ConnectionPoint, 1);
-#endif
-  return op;
-}
-
-void
-uml_operation_copy_into(UMLOperation *srcop, UMLOperation *destop)
+DiaUmlOperation *
+dia_uml_operation_copy (DiaUmlOperation *srcop)
 {
+  DiaUmlOperation *destop;
   UMLParameter *param;
   UMLParameter *newparam;
   GList *list;
+  
+  destop = g_object_new (DIA_UML_TYPE_OPERATION, NULL);
 
   destop->internal_id = srcop->internal_id;
 
@@ -192,16 +190,9 @@ uml_operation_copy_into(UMLOperation *srcop, UMLOperation *destop)
     
     list = g_list_next(list);
   }
-}
 
-UMLOperation *
-uml_operation_copy(UMLOperation *op)
-{
-  UMLOperation *newop;
-  
-  newop = g_new0(UMLOperation, 1);
+  return destop;
 
-  uml_operation_copy_into(op, newop);
 #if 0 /* setup elsewhere */
   newop->left_connection = g_new0(ConnectionPoint,1);
   *newop->left_connection = *op->left_connection;
@@ -211,43 +202,10 @@ uml_operation_copy(UMLOperation *op)
   *newop->right_connection = *op->right_connection;
   newop->right_connection->object = NULL; /* must be setup later */
 #endif
-  return newop;
 }
 
 void
-uml_operation_destroy(UMLOperation *op)
-{
-  GList *list;
-  UMLParameter *param;
-  
-  g_free(op->name);
-  if (op->type != NULL)
-    g_free(op->type);
-  if (op->stereotype != NULL)
-    g_free(op->stereotype);
-
-  g_free(op->comment);
-
-  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);
-  }
-
-#if 0 /* freed elsewhere */
-  /* These are merely temporary reminders, don't need to unconnect */
-  g_free(op->left_connection);
-  g_free(op->right_connection);
-#endif
-  g_free(op);
-}
-
-void
-uml_operation_write(AttributeNode attr_node, UMLOperation *op, DiaContext *ctx)
+uml_operation_write(AttributeNode attr_node, DiaUmlOperation *op, DiaContext *ctx)
 {
   GList *list;
   UMLParameter *param;
@@ -302,7 +260,7 @@ uml_operation_write(AttributeNode attr_node, UMLOperation *op, DiaContext *ctx)
 extern char visible_char[];
 
 char *
-uml_get_operation_string (UMLOperation *operation)
+dia_uml_operation_format (DiaUmlOperation *operation)
 {
   int len;
   char *str;
@@ -430,8 +388,8 @@ uml_get_operation_string (UMLOperation *operation)
 
 /*!
  * The ownership of these connection points is quite complicated. Instead of being part of
- * the UMLOperation as one may expect at first, they are somewhat in between the DiaObject
- * (see: DiaObject::connections and the concrete user, here UMLClass) and the UMLOperation.
+ * the DiaUmlOperation as one may expect at first, they are somewhat in between the DiaObject
+ * (see: DiaObject::connections and the concrete user, here UMLClass) and the DiaUmlOperation.
  *
  * But with taking undo state mangement into account it gets even worse. Deleted (to be
  * restored connection points) live inside the UMLClassChange until they get reverted back
@@ -444,7 +402,7 @@ uml_get_operation_string (UMLOperation *operation)
  * with C++ it would be a template function ;)
  */
 void
-uml_operation_ensure_connection_points (UMLOperation* op, DiaObject* obj)
+dia_uml_operation_ensure_connection_points (DiaUmlOperation* op, DiaObject* obj)
 {
   if (!op->left_connection)
     op->left_connection = g_new0(ConnectionPoint,1);
@@ -453,3 +411,199 @@ uml_operation_ensure_connection_points (UMLOperation* op, DiaObject* obj)
     op->right_connection = g_new0(ConnectionPoint,1);
   op->right_connection->object = obj;
 }
+
+static void
+dia_uml_operation_finalize (GObject *object)
+{
+  GList *list;
+  UMLParameter *param;
+  DiaUmlOperation *self = DIA_UML_OPERATION (object);
+  
+  g_free (self->name);
+  if (self->type != NULL)
+    g_free (self->type);
+  if (self->stereotype != NULL)
+    g_free (self->stereotype);
+
+  g_free (self->comment);
+
+  list = self->parameters;
+  while (list != NULL) {
+    param = (UMLParameter *)list->data;
+    uml_parameter_destroy(param);
+    list = g_list_next(list);
+  }
+  if (self->wrappos) {
+    g_list_free (self->wrappos);
+  }
+
+  /* freed elsewhere */
+  /* These are merely temporary reminders, don't need to unconnect */
+  /*
+  g_free(op->left_connection);
+  g_free(op->right_connection);
+  */
+}
+
+static void
+dia_uml_operation_set_property (GObject      *object,
+                                guint         property_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  DiaUmlOperation *self = DIA_UML_OPERATION (object);
+
+  switch (property_id) {
+    case UML_OP_NAME:
+      self->name = g_value_dup_string (value);
+      g_object_notify_by_pspec (object, uml_op_properties[UML_OP_NAME]);
+      break;
+    case UML_OP_TYPE:
+      self->type = g_value_dup_string (value);
+      g_object_notify_by_pspec (object, uml_op_properties[UML_OP_TYPE]);
+      break;
+    case UML_OP_COMMENT:
+      self->comment = g_value_dup_string (value);
+      g_object_notify_by_pspec (object, uml_op_properties[UML_OP_COMMENT]);
+      break;
+    case UML_OP_STEREOTYPE:
+      self->stereotype = g_value_dup_string (value);
+      g_object_notify_by_pspec (object, uml_op_properties[UML_OP_STEREOTYPE]);
+      break;
+    case UML_OP_VISIBILITY:
+      self->visibility = g_value_get_int (value);
+      g_object_notify_by_pspec (object, uml_op_properties[UML_OP_VISIBILITY]);
+      break;
+    case UML_OP_INHERITANCE_TYPE:
+      self->inheritance_type = g_value_get_int (value);
+      g_object_notify_by_pspec (object, uml_op_properties[UML_OP_INHERITANCE_TYPE]);
+      break;
+    case UML_OP_QUERY:
+      self->query = g_value_get_boolean (value);
+      g_object_notify_by_pspec (object, uml_op_properties[UML_OP_QUERY]);
+      break;
+    case UML_OP_CLASS_SCOPE:
+      self->class_scope = g_value_get_boolean (value);
+      g_object_notify_by_pspec (object, uml_op_properties[UML_OP_CLASS_SCOPE]);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+dia_uml_operation_get_property (GObject    *object,
+                                guint       property_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  DiaUmlOperation *self = DIA_UML_OPERATION (object);
+
+  switch (property_id) {
+    case UML_OP_NAME:
+      g_value_set_string (value, self->name);
+      break;
+    case UML_OP_TYPE:
+      g_value_set_string (value, self->type);
+      break;
+    case UML_OP_COMMENT:
+      g_value_set_string (value, self->comment);
+      break;
+    case UML_OP_STEREOTYPE:
+      g_value_set_string (value, self->stereotype);
+      break;
+    case UML_OP_VISIBILITY:
+      g_value_set_int (value, self->visibility);
+      break;
+    case UML_OP_INHERITANCE_TYPE:
+      g_value_set_int (value, self->inheritance_type);
+      break;
+    case UML_OP_QUERY:
+      g_value_set_boolean (value, self->query);
+      break;
+    case UML_OP_CLASS_SCOPE:
+      g_value_set_boolean (value, self->class_scope);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+dia_uml_operation_class_init (DiaUmlOperationClass *klass)
+{
+  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = dia_uml_operation_finalize;
+  object_class->set_property = dia_uml_operation_set_property;
+  object_class->get_property = dia_uml_operation_get_property;
+
+  uml_op_properties[UML_OP_NAME] = g_param_spec_string ("name",
+                                                        "Name",
+                                                        "Function name",
+                                                        "",
+                                                        G_PARAM_READWRITE);
+  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",
+                                                           "Comment",
+                                                           "",
+                                                           G_PARAM_READWRITE);
+  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",
+                                                           "Visibility",
+                                                           UML_PUBLIC,
+                                                           UML_IMPLEMENTATION,
+                                                           UML_PUBLIC,
+                                                           G_PARAM_READWRITE);
+  uml_op_properties[UML_OP_INHERITANCE_TYPE] = g_param_spec_int ("inheritance-type",
+                                                                 "Inheritance type",
+                                                                 "Inheritance type",
+                                                                 UML_ABSTRACT,
+                                                                 UML_LEAF,
+                                                                 UML_LEAF,
+                                                                 G_PARAM_READWRITE);
+  uml_op_properties[UML_OP_QUERY] = g_param_spec_boolean ("query",
+                                                          "Query",
+                                                          "Const function",
+                                                          FALSE,
+                                                          G_PARAM_READWRITE);
+  uml_op_properties[UML_OP_CLASS_SCOPE] = g_param_spec_boolean ("class-scope",
+                                                                "Class scope",
+                                                                "Class scope",
+                                                                FALSE,
+                                                                G_PARAM_READWRITE);
+
+  g_object_class_install_properties (object_class,
+                                     UML_OP_N_PROPS,
+                                     uml_op_properties);
+}
+
+static void
+dia_uml_operation_init (DiaUmlOperation *self)
+{
+  static gint next_id = 1;
+
+  self->internal_id = next_id++;
+  self->name = g_strdup("");
+  self->comment = g_strdup("");
+  self->visibility = UML_PUBLIC;
+  self->inheritance_type = UML_LEAF;
+}
+
+DiaUmlOperation *
+dia_uml_operation_new ()
+{
+  return g_object_new (DIA_UML_TYPE_OPERATION, NULL);
+}


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