[dia] uml: port attributes to GtkTreeView



commit fa67ce6b77b59bae34a0b2843e308940b8b6a737
Author: Zander Brown <zbrown gnome org>
Date:   Thu Nov 14 22:39:38 2019 +0000

    uml: port attributes to GtkTreeView
    
    Adds real time updates and removes another use of deprecated widgets

 objects/UML/class.c                   |   8 +-
 objects/UML/class_attributes_dialog.c | 898 ++++++++++++++++++++--------------
 objects/UML/class_dialog.c            |  69 +--
 objects/UML/class_dialog.h            |  11 +-
 objects/UML/class_operations_dialog.c |  56 ++-
 objects/UML/uml.h                     |  31 +-
 objects/UML/umlattribute.c            | 130 ++---
 7 files changed, 695 insertions(+), 508 deletions(-)
---
diff --git a/objects/UML/class.c b/objects/UML/class.c
index 3afb39f3..e1e453bb 100644
--- a/objects/UML/class.c
+++ b/objects/UML/class.c
@@ -904,7 +904,7 @@ umlclass_draw_attributebox (UMLClass    *umlclass,
     list = umlclass->attributes;
     while (list != NULL) {
       UMLAttribute *attr   = (UMLAttribute *)list->data;
-      gchar        *attstr = uml_get_attribute_string (attr);
+      gchar        *attstr = uml_attribute_get_string (attr);
 
       if (attr->abstract)  {
         font = umlclass->abstract_font;
@@ -1469,7 +1469,7 @@ umlclass_calculate_attribute_data(UMLClass *umlclass)
     while (list != NULL)
     {
       UMLAttribute *attr   = (UMLAttribute *) list->data;
-      gchar        *attstr = uml_get_attribute_string(attr);
+      gchar        *attstr = uml_attribute_get_string (attr);
 
       if (attr->abstract)
       {
@@ -1959,8 +1959,8 @@ umlclass_destroy(UMLClass *umlclass)
     attr = (UMLAttribute *)list->data;
     g_free(attr->left_connection);
     g_free(attr->right_connection);
-    uml_attribute_destroy(attr);
-    list = g_list_next(list);
+    uml_attribute_unref (attr);
+    list = g_list_next (list);
   }
   g_list_free(umlclass->attributes);
 
diff --git a/objects/UML/class_attributes_dialog.c b/objects/UML/class_attributes_dialog.c
index dac7bed1..e566930f 100644
--- a/objects/UML/class_attributes_dialog.c
+++ b/objects/UML/class_attributes_dialog.c
@@ -19,7 +19,6 @@
 #include <config.h>
 
 #include <assert.h>
-#undef GTK_DISABLE_DEPRECATED /* GtkList, ... */
 #include <gtk/gtk.h>
 
 #include "class.h"
@@ -31,341 +30,413 @@
  ******************** ATTRIBUTES ****************************
  ************************************************************/
 
+enum {
+  COL_ATTR_TITLE,
+  COL_ATTR_ATTR,
+  N_PARAM_COLS
+};
+
+
+static gboolean
+get_current_attribute (UMLClassDialog  *dialog,
+                       UMLAttribute   **attr,
+                       GtkTreeIter     *c_iter)
+{
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  GtkTreeSelection *selection;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->attributes));
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    gtk_tree_model_get (model, &iter, COL_ATTR_ATTR, attr, -1);
+
+    if (c_iter) {
+      *c_iter = iter;
+    }
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+
 static void
-attributes_set_sensitive(UMLClassDialog *prop_dialog, gint val)
+update_attribute (UMLClassDialog *dialog,
+                  UMLAttribute   *attr,
+                  GtkTreeIter    *iter)
 {
-  gtk_widget_set_sensitive(GTK_WIDGET(prop_dialog->attr_name), val);
-  gtk_widget_set_sensitive(GTK_WIDGET(prop_dialog->attr_type), val);
-  gtk_widget_set_sensitive(GTK_WIDGET(prop_dialog->attr_value), val);
-  gtk_widget_set_sensitive(GTK_WIDGET(prop_dialog->attr_comment), val);
-  gtk_widget_set_sensitive(GTK_WIDGET(prop_dialog->attr_visible), val);
-  gtk_widget_set_sensitive(GTK_WIDGET(prop_dialog->attr_class_scope), val);
+  char *title;
+
+  title = uml_attribute_get_string (attr);
+
+  gtk_list_store_set (dialog->attributes_store,
+                      iter,
+                      COL_ATTR_ATTR, attr,
+                      COL_ATTR_TITLE, title,
+                      -1);
+
+  g_clear_pointer (&title, g_free);
 }
 
+
 static void
-attributes_set_values(UMLClassDialog *prop_dialog, UMLAttribute *attr)
+attributes_set_sensitive (UMLClassDialog *prop_dialog, gboolean val)
 {
-  gtk_entry_set_text(prop_dialog->attr_name, attr->name);
-  gtk_entry_set_text(prop_dialog->attr_type, attr->type);
-  if (attr->value != NULL)
-    gtk_entry_set_text(prop_dialog->attr_value, attr->value);
-  else
-    gtk_entry_set_text(prop_dialog->attr_value, "");
+  gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attr_name), val);
+  gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attr_type), val);
+  gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attr_value), val);
+  gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attr_comment), val);
+  gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attr_visible), val);
+  gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attr_class_scope), val);
+}
 
-  if (attr->comment != NULL)
-    _class_set_comment(prop_dialog->attr_comment, attr->comment);
-  else
-    _class_set_comment(prop_dialog->attr_comment, "");
 
+static void
+attributes_set_values (UMLClassDialog *prop_dialog, UMLAttribute *attr)
+{
+  char *comment = NULL;
+
+  gtk_entry_set_text (prop_dialog->attr_name,
+                      attr->name? attr->name : "");
+  gtk_entry_set_text (prop_dialog->attr_type,
+                      attr->type? attr->type : "");
+  gtk_entry_set_text (prop_dialog->attr_value,
+                      attr->value? attr->value : "");
+
+  // So, this shouldn't need to have a strdup but weird stuff happens without
+  comment = g_strdup (attr->comment? attr->comment : "");
+  gtk_text_buffer_set_text (prop_dialog->attr_comment_buffer,
+                            comment,
+                            -1);
+  g_free (comment);
+
+  dia_option_menu_set_active (DIA_OPTION_MENU (prop_dialog->attr_visible),
+                              attr->visibility);
+  gtk_toggle_button_set_active (prop_dialog->attr_class_scope,
+                                attr->class_scope);
+}
 
-  dia_option_menu_set_active (DIA_OPTION_MENU (prop_dialog->attr_visible), attr->visibility);
-  gtk_toggle_button_set_active(prop_dialog->attr_class_scope, attr->class_scope);
+
+static void
+attributes_clear_values (UMLClassDialog *prop_dialog)
+{
+  gtk_entry_set_text (prop_dialog->attr_name, "");
+  gtk_entry_set_text (prop_dialog->attr_type, "");
+  gtk_entry_set_text (prop_dialog->attr_value, "");
+  gtk_text_buffer_set_text (prop_dialog->attr_comment_buffer, "", -1);
+  gtk_toggle_button_set_active (prop_dialog->attr_class_scope, FALSE);
 }
 
+
 static void
-attributes_clear_values(UMLClassDialog *prop_dialog)
+attributes_list_new_callback (GtkWidget *button,
+                              UMLClass  *umlclass)
 {
-  gtk_entry_set_text(prop_dialog->attr_name, "");
-  gtk_entry_set_text(prop_dialog->attr_type, "");
-  gtk_entry_set_text(prop_dialog->attr_value, "");
-  _class_set_comment(prop_dialog->attr_comment, "");
-  gtk_toggle_button_set_active(prop_dialog->attr_class_scope, FALSE);
+  UMLClassDialog *prop_dialog;
+  UMLAttribute *attr;
+  GtkTreeIter iter;
+  GtkTreeSelection *selection;
+
+  prop_dialog = umlclass->properties_dialog;
+
+  attr = uml_attribute_new ();
+
+  /* need to make the new ConnectionPoint valid and remember them */
+  uml_attribute_ensure_connection_points (attr, &umlclass->element.object);
+  prop_dialog->added_connections =
+    g_list_prepend (prop_dialog->added_connections, attr->left_connection);
+  prop_dialog->added_connections =
+    g_list_prepend (prop_dialog->added_connections, attr->right_connection);
+
+  gtk_list_store_append (prop_dialog->attributes_store, &iter);
+  update_attribute (prop_dialog, attr, &iter);
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->attributes));
+  gtk_tree_selection_select_iter (selection, &iter);
+
+  g_clear_pointer (&attr, uml_attribute_unref);
 }
 
+
 static void
-attributes_get_values (UMLClassDialog *prop_dialog, UMLAttribute *attr)
+attributes_list_delete_callback (GtkWidget *button,
+                                 UMLClass  *umlclass)
 {
-  g_free (attr->name);
-  g_free (attr->type);
-  if (attr->value != NULL)
-    g_free (attr->value);
+  UMLClassDialog *prop_dialog;
+  UMLAttribute *attr;
+  GtkTreeIter iter;
 
-  attr->name = g_strdup (gtk_entry_get_text (prop_dialog->attr_name));
-  attr->type = g_strdup (gtk_entry_get_text (prop_dialog->attr_type));
+  prop_dialog = umlclass->properties_dialog;
 
-  attr->value = g_strdup (gtk_entry_get_text(prop_dialog->attr_value));
-  attr->comment = g_strdup (_class_get_comment(prop_dialog->attr_comment));
+  if (get_current_attribute (prop_dialog, &attr, &iter)) {
+    if (attr->left_connection != NULL) {
+      prop_dialog->deleted_connections =
+        g_list_prepend (prop_dialog->deleted_connections,
+                        attr->left_connection);
+      prop_dialog->deleted_connections =
+        g_list_prepend (prop_dialog->deleted_connections,
+                        attr->right_connection);
+    }
 
-  attr->visibility = (UMLVisibility) dia_option_menu_get_active (DIA_OPTION_MENU 
(prop_dialog->attr_visible));
+    gtk_list_store_remove (prop_dialog->attributes_store, &iter);
 
-  attr->class_scope = gtk_toggle_button_get_active (prop_dialog->attr_class_scope);
+    g_clear_pointer (&attr, uml_attribute_unref);
+  }
 }
 
-void
-_attributes_get_current_values(UMLClassDialog *prop_dialog)
+
+static void
+attributes_list_move_up_callback (GtkWidget *button,
+                                  UMLClass  *umlclass)
 {
+  UMLClassDialog *prop_dialog;
   UMLAttribute *current_attr;
-  GtkLabel *label;
-  char *new_str;
-
-  if (prop_dialog != NULL && prop_dialog->current_attr != NULL) {
-    current_attr = (UMLAttribute *)
-      g_object_get_data(G_OBJECT(prop_dialog->current_attr), "user_data");
-    if (current_attr != NULL) {
-      attributes_get_values(prop_dialog, current_attr);
-      label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(prop_dialog->current_attr)));
-      new_str = uml_get_attribute_string(current_attr);
-      gtk_label_set_text (label, new_str);
-      g_free (new_str);
+  GtkTreeIter iter;
+
+  prop_dialog = umlclass->properties_dialog;
+
+  if (get_current_attribute (prop_dialog, &current_attr, &iter)) {
+    GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (prop_dialog->attributes_store),
+                                                 &iter);
+    GtkTreeSelection *selection;
+    GtkTreeIter prev;
+
+    if (path != NULL && gtk_tree_path_prev (path)
+        && gtk_tree_model_get_iter (GTK_TREE_MODEL (prop_dialog->attributes_store), &prev, path)) {
+      gtk_list_store_move_before (prop_dialog->attributes_store, &iter, &prev);
+    } else {
+      gtk_list_store_move_before (prop_dialog->attributes_store, &iter, NULL);
     }
+    gtk_tree_path_free (path);
+
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->attributes));
+    gtk_tree_selection_select_iter (selection, &iter);
+
+    g_clear_pointer (&current_attr, uml_attribute_unref);
   }
 }
 
+
 static void
-attribute_list_item_destroy_callback(GtkWidget *list_item,
-                                    gpointer data)
+attributes_list_move_down_callback (GtkWidget *button,
+                                    UMLClass  *umlclass)
 {
-  UMLAttribute *attr;
+  UMLClassDialog *prop_dialog;
+  UMLAttribute *current_attr;
+  GtkTreeIter iter;
+
+  prop_dialog = umlclass->properties_dialog;
+
+  if (get_current_attribute (prop_dialog, &current_attr, &iter)) {
+    GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (prop_dialog->attributes_store),
+                                                 &iter);
+    GtkTreeSelection *selection;
+    GtkTreeIter prev;
+
+    if (path != NULL) {
+      gtk_tree_path_next (path);
+      if (gtk_tree_model_get_iter (GTK_TREE_MODEL (prop_dialog->attributes_store), &prev, path)) {
+        gtk_list_store_move_after (prop_dialog->attributes_store, &iter, &prev);
+      } else {
+        gtk_list_store_move_after (prop_dialog->attributes_store, &iter, NULL);
+      }
+    } else {
+      gtk_list_store_move_after (prop_dialog->attributes_store, &iter, NULL);
+    }
+    gtk_tree_path_free (path);
 
-  attr = (UMLAttribute *) g_object_get_data(G_OBJECT(list_item), "user_data");
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->attributes));
+    gtk_tree_selection_select_iter (selection, &iter);
 
-  if (attr != NULL) {
-    uml_attribute_destroy(attr);
-    /*printf("Destroying list_item's user_data!\n");*/
+    g_clear_pointer (&current_attr, uml_attribute_unref);
   }
 }
 
+
 static void
-attributes_list_selection_changed_callback(GtkWidget *gtklist,
-                                          UMLClass *umlclass)
+name_changed (GtkWidget *entry, UMLClass *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
-  GObject *list_item;
   UMLAttribute *attr;
-
-  /* Due to GtkList oddities, this may get called during destroy.
-   * But it'll reference things that are already dead and crash.
-   * Thus, we stop it before it gets that bad.  See bug #156706 for
-   * one example.
-   */
-  if (umlclass->destroyed)
-    return;
+  GtkTreeIter iter;
 
   prop_dialog = umlclass->properties_dialog;
 
-  if (!prop_dialog)
-    return;
+  if (get_current_attribute (prop_dialog, &attr, &iter)) {
+    g_clear_pointer (&attr->name, g_free);
+    attr->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
 
-  _attributes_get_current_values(prop_dialog);
+    update_attribute (prop_dialog, attr, &iter);
 
-  list = GTK_LIST(gtklist)->selection;
-  if (!list && prop_dialog) { /* No selected */
-    attributes_set_sensitive(prop_dialog, FALSE);
-    attributes_clear_values(prop_dialog);
-    prop_dialog->current_attr = NULL;
-    return;
+    g_clear_pointer (&attr, uml_attribute_unref);
   }
-
-  list_item = G_OBJECT(list->data);
-  attr = (UMLAttribute *)g_object_get_data(G_OBJECT(list_item), "user_data");
-  attributes_set_values(prop_dialog, attr);
-  attributes_set_sensitive(prop_dialog, TRUE);
-
-  prop_dialog->current_attr = GTK_LIST_ITEM(list_item);
-  gtk_widget_grab_focus(GTK_WIDGET(prop_dialog->attr_name));
 }
 
+
 static void
-attributes_list_new_callback(GtkWidget *button,
-                            UMLClass *umlclass)
+type_changed (GtkWidget *entry, UMLClass *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
-  GtkWidget *list_item;
   UMLAttribute *attr;
-  char *utfstr;
+  GtkTreeIter iter;
+
   prop_dialog = umlclass->properties_dialog;
 
-  _attributes_get_current_values(prop_dialog);
+  if (get_current_attribute (prop_dialog, &attr, &iter)) {
+    g_clear_pointer (&attr->type, g_free);
+    attr->type = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+
+    update_attribute (prop_dialog, attr, &iter);
+
+    g_clear_pointer (&attr, uml_attribute_unref);
+  }
+}
 
-  attr = uml_attribute_new();
-  /* need to make the new ConnectionPoint valid and remember them */
-  uml_attribute_ensure_connection_points (attr, &umlclass->element.object);
-  prop_dialog->added_connections =
-    g_list_prepend(prop_dialog->added_connections, attr->left_connection);
-  prop_dialog->added_connections =
-    g_list_prepend(prop_dialog->added_connections, attr->right_connection);
 
-  utfstr = uml_get_attribute_string (attr);
-  list_item = gtk_list_item_new_with_label (utfstr);
-  gtk_widget_show (list_item);
-  g_free (utfstr);
+static void
+value_changed (GtkWidget *entry, UMLClass *umlclass)
+{
+  UMLClassDialog *prop_dialog;
+  UMLAttribute *attr;
+  GtkTreeIter iter;
+
+  prop_dialog = umlclass->properties_dialog;
 
-  g_object_set_data(G_OBJECT(list_item), "user_data", attr);
-  g_signal_connect (G_OBJECT (list_item), "destroy",
-                   G_CALLBACK (attribute_list_item_destroy_callback), NULL);
+  if (get_current_attribute (prop_dialog, &attr, &iter)) {
+    g_clear_pointer (&attr->value, g_free);
+    attr->value = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
 
-  list = g_list_append(NULL, list_item);
-  gtk_list_append_items(prop_dialog->attributes_list, list);
+    update_attribute (prop_dialog, attr, &iter);
 
-  if (prop_dialog->attributes_list->children != NULL)
-    gtk_list_unselect_child(prop_dialog->attributes_list,
-                           GTK_WIDGET(prop_dialog->attributes_list->children->data));
-  gtk_list_select_child(prop_dialog->attributes_list, list_item);
+    g_clear_pointer (&attr, uml_attribute_unref);
+  }
 }
 
+
 static void
-attributes_list_delete_callback(GtkWidget *button,
-                               UMLClass *umlclass)
+comment_changed (GtkTextBuffer *buffer, UMLClass *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
-  GtkList *gtklist;
   UMLAttribute *attr;
 
   prop_dialog = umlclass->properties_dialog;
-  gtklist = GTK_LIST(prop_dialog->attributes_list);
 
-  if (gtklist->selection != NULL) {
-    attr = (UMLAttribute *)
-      g_object_get_data(G_OBJECT(gtklist->selection->data), "user_data");
+  if (get_current_attribute (prop_dialog, &attr, NULL)) {
+    g_clear_pointer (&attr->comment, g_free);
+    attr->comment = buffer_get_text (prop_dialog->attr_comment_buffer);
 
-    if (attr->left_connection != NULL) {
-      prop_dialog->deleted_connections =
-       g_list_prepend(prop_dialog->deleted_connections,
-                      attr->left_connection);
-      prop_dialog->deleted_connections =
-       g_list_prepend(prop_dialog->deleted_connections,
-                      attr->right_connection);
-    }
-
-    list = g_list_prepend(NULL, gtklist->selection->data);
-    gtk_list_remove_items(gtklist, list);
-    g_list_free(list);
-    attributes_clear_values(prop_dialog);
-    attributes_set_sensitive(prop_dialog, FALSE);
+    g_clear_pointer (&attr, uml_attribute_unref);
   }
 }
 
+
 static void
-attributes_list_move_up_callback(GtkWidget *button,
-                                UMLClass *umlclass)
+visibility_changed (DiaOptionMenu *selector, UMLClass *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
-  GtkList *gtklist;
-  GtkWidget *list_item;
-  int i;
+  UMLAttribute *attr;
+  GtkTreeIter iter;
 
   prop_dialog = umlclass->properties_dialog;
-  gtklist = GTK_LIST(prop_dialog->attributes_list);
 
-  if (gtklist->selection != NULL) {
-    list_item = GTK_WIDGET(gtklist->selection->data);
+  if (get_current_attribute (prop_dialog, &attr, &iter)) {
+    attr->visibility = (UMLVisibility) dia_option_menu_get_active (selector);
 
-    i = gtk_list_child_position(gtklist, list_item);
-    if (i>0)
-      i--;
+    update_attribute (prop_dialog, attr, &iter);
 
-    g_object_ref(list_item);
-    list = g_list_prepend(NULL, list_item);
-    gtk_list_remove_items(gtklist, list);
-    gtk_list_insert_items(gtklist, list, i);
-    g_object_unref(list_item);
-
-    gtk_list_select_child(gtklist, list_item);
+    g_clear_pointer (&attr, uml_attribute_unref);
   }
 }
 
+
 static void
-attributes_list_move_down_callback(GtkWidget *button,
-                                  UMLClass *umlclass)
+scope_changed (GtkToggleButton *toggle, UMLClass *umlclass)
 {
-  GList *list;
   UMLClassDialog *prop_dialog;
-  GtkList *gtklist;
-  GtkWidget *list_item;
-  int i;
+  UMLAttribute *attr;
+  GtkTreeIter iter;
 
   prop_dialog = umlclass->properties_dialog;
-  gtklist = GTK_LIST(prop_dialog->attributes_list);
 
-  if (gtklist->selection != NULL) {
-    list_item = GTK_WIDGET(gtklist->selection->data);
+  if (get_current_attribute (prop_dialog, &attr, &iter)) {
+    attr->class_scope = gtk_toggle_button_get_active (toggle);
+
+    update_attribute (prop_dialog, attr, &iter);
+
+    g_clear_pointer (&attr, uml_attribute_unref);
+  }
+}
+
+
+struct AddAttrData {
+  UMLClass       *class;
+  UMLClassDialog *dialog;
+  int             connection_index;
+};
+
 
-    i = gtk_list_child_position(gtklist, list_item);
-    if (i<(g_list_length(gtklist->children)-1))
-      i++;
+static gboolean
+add_attr_to_list (GtkTreeModel *model,
+                  GtkTreePath  *path,
+                  GtkTreeIter  *iter,
+                  gpointer      udata)
+{
+  struct AddAttrData *data = udata;
+  UMLAttribute *attr = NULL;
+
+  // Don't free attr, transfering to the list
+  gtk_tree_model_get (model, iter, COL_ATTR_ATTR, &attr, -1);
+
+  data->class->attributes = g_list_append (data->class->attributes, attr);
 
+  if (attr->left_connection == NULL) {
+    uml_attribute_ensure_connection_points (attr, DIA_OBJECT (data->class));
 
-    g_object_ref(list_item);
-    list = g_list_prepend(NULL, list_item);
-    gtk_list_remove_items(gtklist, list);
-    gtk_list_insert_items(gtklist, list, i);
-    g_object_unref(list_item);
+    data->dialog->added_connections =
+      g_list_prepend (data->dialog->added_connections,
+                      attr->left_connection);
+    data->dialog->added_connections =
+      g_list_prepend (data->dialog->added_connections,
+                      attr->right_connection);
+  }
 
-    gtk_list_select_child(gtklist, list_item);
+  if (( gtk_toggle_button_get_active (data->dialog->attr_vis)) &&
+      (!gtk_toggle_button_get_active (data->dialog->attr_supp))) {
+    DIA_OBJECT (data->class)->connections[data->connection_index] = attr->left_connection;
+    data->connection_index++;
+    DIA_OBJECT (data->class)->connections[data->connection_index] = attr->right_connection;
+    data->connection_index++;
+  } else {
+    _umlclass_store_disconnects (data->dialog, attr->left_connection);
+    object_remove_connections_to (attr->left_connection);
+    _umlclass_store_disconnects (data->dialog, attr->right_connection);
+    object_remove_connections_to (attr->right_connection);
   }
+
+  return FALSE;
 }
 
+
 void
-_attributes_read_from_dialog(UMLClass *umlclass,
-                           UMLClassDialog *prop_dialog,
-                           int connection_index)
+_attributes_read_from_dialog (UMLClass       *umlclass,
+                              UMLClassDialog *prop_dialog,
+                              int             connection_index)
 {
-  GList *list;
-  UMLAttribute *attr;
-  GtkWidget *list_item;
-  GList *clear_list;
-  DiaObject *obj;
-
-  obj = &umlclass->element.object;
+  struct AddAttrData data;
 
-  /* if the currently select attribute is changed, update the state in the
-   * dialog info from widgets */
-  _attributes_get_current_values(prop_dialog);
   /* Free current attributes: */
-  list = umlclass->attributes;
-  while (list != NULL) {
-    attr = (UMLAttribute *)list->data;
-    uml_attribute_destroy(attr);
-    list = g_list_next(list);
-  }
-  g_list_free (umlclass->attributes);
+  g_list_free_full (umlclass->attributes, (GDestroyNotify) uml_attribute_unref);
   umlclass->attributes = NULL;
 
-  /* Insert new attributes and remove them from gtklist: */
-  list = GTK_LIST (prop_dialog->attributes_list)->children;
-  clear_list = NULL;
-  while (list != NULL) {
-    list_item = GTK_WIDGET(list->data);
-
-    clear_list = g_list_prepend (clear_list, list_item);
-    attr = (UMLAttribute *)
-      g_object_get_data(G_OBJECT(list_item), "user_data");
-    g_object_set_data(G_OBJECT(list_item), "user_data", NULL);
-    umlclass->attributes = g_list_append(umlclass->attributes, attr);
-
-    if (attr->left_connection == NULL) {
-      uml_attribute_ensure_connection_points (attr, obj);
-
-      prop_dialog->added_connections =
-       g_list_prepend(prop_dialog->added_connections,
-                      attr->left_connection);
-      prop_dialog->added_connections =
-       g_list_prepend(prop_dialog->added_connections,
-                      attr->right_connection);
-    }
+  data.class = umlclass;
+  data.dialog = prop_dialog;
+  data.connection_index = connection_index;
 
-    if ( (gtk_toggle_button_get_active (prop_dialog->attr_vis)) &&
-         (!gtk_toggle_button_get_active (prop_dialog->attr_supp)) ) {
-      obj->connections[connection_index] = attr->left_connection;
-      connection_index++;
-      obj->connections[connection_index] = attr->right_connection;
-      connection_index++;
-    } else {
-      _umlclass_store_disconnects(prop_dialog, attr->left_connection);
-      object_remove_connections_to(attr->left_connection);
-      _umlclass_store_disconnects(prop_dialog, attr->right_connection);
-      object_remove_connections_to(attr->right_connection);
-    }
-
-    list = g_list_next(list);
-  }
-  clear_list = g_list_reverse (clear_list);
-  gtk_list_remove_items (GTK_LIST (prop_dialog->attributes_list), clear_list);
-  g_list_free (clear_list);
+  gtk_tree_model_foreach (GTK_TREE_MODEL (prop_dialog->attributes_store),
+                          add_attr_to_list,
+                          &data);
+  gtk_list_store_clear (prop_dialog->attributes_store);
 
 #if 0 /* UMLClass is *known* to be in an incositent state here, check later or crash ... */
   umlclass_sanity_check(umlclass, "Read from dialog");
@@ -377,9 +448,8 @@ _attributes_fill_in_dialog(UMLClass *umlclass)
 {
   UMLClassDialog *prop_dialog;
   UMLAttribute *attr_copy;
-  GtkWidget *list_item;
+  GtkTreeIter iter;
   GList *list;
-  int i;
 
 #ifdef DEBUG
   umlclass_sanity_check(umlclass, "Filling in dialog");
@@ -387,50 +457,66 @@ _attributes_fill_in_dialog(UMLClass *umlclass)
 
   prop_dialog = umlclass->properties_dialog;
 
+  gtk_list_store_clear (prop_dialog->attributes_store);
+
   /* copy in new attributes: */
-  if (prop_dialog->attributes_list->children == NULL) {
-    i = 0;
-    list = umlclass->attributes;
-    while (list != NULL) {
-      UMLAttribute *attr = (UMLAttribute *)list->data;
-      gchar *attrstr = uml_get_attribute_string(attr);
-
-      list_item = gtk_list_item_new_with_label (attrstr);
-      attr_copy = uml_attribute_copy(attr);
-      /* looks wrong but required for complicated ConnectionPoint memory management */
-      attr_copy->left_connection = attr->left_connection;
-      attr_copy->right_connection = attr->right_connection;
-      g_object_set_data(G_OBJECT(list_item), "user_data", (gpointer) attr_copy);
-      g_signal_connect (G_OBJECT (list_item), "destroy",
-                       G_CALLBACK (attribute_list_item_destroy_callback), NULL);
-      gtk_container_add (GTK_CONTAINER (prop_dialog->attributes_list), list_item);
-      gtk_widget_show (list_item);
-
-      list = g_list_next(list); i++;
-      g_free (attrstr);
-    }
-    /* set attributes non-sensitive */
-    prop_dialog->current_attr = NULL;
-    attributes_set_sensitive(prop_dialog, FALSE);
-    attributes_clear_values(prop_dialog);
+  list = umlclass->attributes;
+  while (list != NULL) {
+    UMLAttribute *attr = (UMLAttribute *) list->data;
+
+    attr_copy = uml_attribute_copy (attr);
+
+    /* looks wrong but required for complicated ConnectionPoint memory management */
+    attr_copy->left_connection = attr->left_connection;
+    attr_copy->right_connection = attr->right_connection;
+
+    gtk_list_store_append (prop_dialog->attributes_store, &iter);
+    update_attribute (prop_dialog, attr_copy, &iter);
+
+    list = g_list_next(list);
+
+    g_clear_pointer (&attr_copy, uml_attribute_unref);
   }
+
+  /* set attributes non-sensitive */
+  attributes_set_sensitive (prop_dialog, FALSE);
+  attributes_clear_values (prop_dialog);
 }
 
+
 static void
-attributes_update(GtkWidget *widget, UMLClass *umlclass)
+attribute_selected (GtkTreeSelection *selection,
+                    UMLClass         *umlclass)
 {
-  _attributes_get_current_values(umlclass->properties_dialog);
-}
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  UMLAttribute *attr;
+  UMLClassDialog *prop_dialog;
 
-static int
-attributes_update_event(GtkWidget *widget, GdkEventFocus *ev, UMLClass *umlclass)
-{
-  _attributes_get_current_values(umlclass->properties_dialog);
-  return 0;
+  prop_dialog = umlclass->properties_dialog;
+
+  if (!prop_dialog) {
+    return; /* maybe hiding a bug elsewhere */
+  }
+
+  if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+    gtk_tree_model_get (model, &iter, COL_ATTR_ATTR, &attr, -1);
+
+    attributes_set_values (prop_dialog, attr);
+    attributes_set_sensitive (prop_dialog, TRUE);
+
+    g_clear_pointer (&attr, uml_attribute_unref);
+
+    gtk_widget_grab_focus (GTK_WIDGET (prop_dialog->attr_name));
+  } else {
+    attributes_set_sensitive (prop_dialog, FALSE);
+    attributes_clear_values (prop_dialog);
+  }
 }
 
+
 void
-_attributes_create_page(GtkNotebook *notebook,  UMLClass *umlclass)
+_attributes_create_page (GtkNotebook *notebook, UMLClass *umlclass)
 {
   UMLClassDialog *prop_dialog;
   GtkWidget *page_label;
@@ -444,120 +530,190 @@ _attributes_create_page(GtkNotebook *notebook,  UMLClass *umlclass)
   GtkWidget *checkbox;
   GtkWidget *scrolled_win;
   GtkWidget *button;
-  GtkWidget *list;
   GtkWidget *frame;
   GtkWidget *omenu;
   GtkWidget *scrolledwindow;
+  GtkWidget *image;
+  GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
+  GtkTreeSelection *select;
 
   prop_dialog = umlclass->properties_dialog;
 
   /* Attributes page: */
   page_label = gtk_label_new_with_mnemonic (_("_Attributes"));
 
-  vbox = gtk_vbox_new(FALSE, 5);
-  gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
+  vbox = gtk_vbox_new (FALSE, 6);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+  gtk_widget_show (vbox);
 
-  hbox = gtk_hbox_new(FALSE, 5);
+  hbox = gtk_hbox_new (FALSE, 6);
+  gtk_widget_show (hbox);
 
   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
+                                       GTK_SHADOW_IN);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
-                                 GTK_POLICY_AUTOMATIC,
-                                 GTK_POLICY_AUTOMATIC);
+                                  GTK_POLICY_AUTOMATIC,
+                                  GTK_POLICY_AUTOMATIC);
   gtk_box_pack_start (GTK_BOX (hbox), scrolled_win, TRUE, TRUE, 0);
   gtk_widget_show (scrolled_win);
 
-  list = gtk_list_new ();
-  prop_dialog->attributes_list = GTK_LIST(list);
-  gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_SINGLE);
-  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
-  gtk_container_set_focus_vadjustment (GTK_CONTAINER (list),
-                                      gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW 
(scrolled_win)));
-  gtk_widget_show (list);
-
-  g_signal_connect (G_OBJECT (list), "selection_changed",
-                   G_CALLBACK(attributes_list_selection_changed_callback), umlclass);
-
-  vbox2 = gtk_vbox_new(FALSE, 5);
-
-  button = gtk_button_new_from_stock (GTK_STOCK_NEW);
-  g_signal_connect (G_OBJECT (button), "clicked",
-                   G_CALLBACK(attributes_list_new_callback), umlclass);
-  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, TRUE, 0);
+  prop_dialog->attributes_store = gtk_list_store_new (N_PARAM_COLS,
+                                                      G_TYPE_STRING,
+                                                      DIA_UML_TYPE_PARAMETER);
+  prop_dialog->attributes = gtk_tree_view_new_with_model (GTK_TREE_MODEL (prop_dialog->attributes_store));
+  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (prop_dialog->attributes), FALSE);
+  gtk_container_set_focus_vadjustment (GTK_CONTAINER (prop_dialog->attributes),
+                                       gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW 
(scrolled_win)));
+  select = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->attributes));
+  g_signal_connect (G_OBJECT (select),
+                    "changed",
+                    G_CALLBACK (attribute_selected),
+                    umlclass);
+  gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
+
+  renderer = gtk_cell_renderer_text_new ();
+  g_object_set (renderer, "family", "monospace", NULL);
+  column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                     renderer,
+                                                     "text",
+                                                     COL_ATTR_TITLE,
+                                                     NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (prop_dialog->attributes),
+                               column);
+
+  gtk_container_add (GTK_CONTAINER (scrolled_win), prop_dialog->attributes);
+  gtk_widget_show (prop_dialog->attributes);
+
+
+  vbox2 = gtk_vbox_new (FALSE, 6);
+  gtk_widget_show (vbox2);
+
+  button = gtk_button_new ();
+  image = gtk_image_new_from_icon_name ("list-add",
+                                        GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_widget_show (image);
+  gtk_container_add (GTK_CONTAINER (button), image);
+  gtk_widget_set_tooltip_text (button, _("Add Attribute"));
+  g_signal_connect (G_OBJECT (button),
+                    "clicked",
+                    G_CALLBACK (attributes_list_new_callback),
+                    umlclass);
+  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
   gtk_widget_show (button);
-  button = gtk_button_new_from_stock (GTK_STOCK_DELETE);
-  g_signal_connect (G_OBJECT (button), "clicked",
-                   G_CALLBACK(attributes_list_delete_callback), umlclass);
-  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, TRUE, 0);
+
+  button = gtk_button_new ();
+  image = gtk_image_new_from_icon_name ("list-remove",
+                                        GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_widget_show (image);
+  gtk_container_add (GTK_CONTAINER (button), image);
+  gtk_widget_set_tooltip_text (button, _("Remove Attribute"));
+  g_signal_connect (G_OBJECT (button),
+                    "clicked",
+                    G_CALLBACK (attributes_list_delete_callback),
+                    umlclass);
+  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
   gtk_widget_show (button);
-  button = gtk_button_new_from_stock (GTK_STOCK_GO_UP);
-  g_signal_connect (G_OBJECT (button), "clicked",
-                   G_CALLBACK(attributes_list_move_up_callback), umlclass);
-  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, TRUE, 0);
+
+  button = gtk_button_new ();
+  image = gtk_image_new_from_icon_name ("go-up",
+                                        GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_widget_show (image);
+  gtk_container_add (GTK_CONTAINER (button), image);
+  gtk_widget_set_tooltip_text (button, _("Move Attribute Up"));
+  g_signal_connect (G_OBJECT (button),
+                    "clicked",
+                    G_CALLBACK (attributes_list_move_up_callback),
+                    umlclass);
+  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
   gtk_widget_show (button);
-  button = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN);
-  g_signal_connect (G_OBJECT (button), "clicked",
-                   G_CALLBACK(attributes_list_move_down_callback), umlclass);
-  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, TRUE, 0);
+
+  button = gtk_button_new ();
+  image = gtk_image_new_from_icon_name ("go-down",
+                                        GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_widget_show (image);
+  gtk_container_add (GTK_CONTAINER (button), image);
+  gtk_widget_set_tooltip_text (button, _("Move Attribute Down"));
+  g_signal_connect (G_OBJECT (button),
+                    "clicked",
+                    G_CALLBACK (attributes_list_move_down_callback),
+                    umlclass);
+  gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
   gtk_widget_show (button);
 
   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, TRUE, 0);
 
   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
 
-  frame = gtk_frame_new(_("Attribute data"));
-  vbox2 = gtk_vbox_new(FALSE, 5);
-  gtk_container_set_border_width (GTK_CONTAINER (vbox2), 10);
+  frame = gtk_frame_new (_("Attribute data"));
+  vbox2 = gtk_vbox_new (FALSE, 6);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox2), 6);
   gtk_container_add (GTK_CONTAINER (frame), vbox2);
-  gtk_widget_show(frame);
+  gtk_widget_show (frame);
   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+  gtk_widget_show (vbox2);
 
   table = gtk_table_new (5, 2, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
   gtk_box_pack_start (GTK_BOX (vbox2), table, FALSE, FALSE, 0);
-
-  label = gtk_label_new(_("Name:"));
-  entry = gtk_entry_new();
-  prop_dialog->attr_name = GTK_ENTRY(entry);
-  g_signal_connect (G_OBJECT (entry), "focus_out_event",
-                   G_CALLBACK (attributes_update_event), umlclass);
-  g_signal_connect (G_OBJECT (entry), "activate",
-                   G_CALLBACK (attributes_update), umlclass);
+  gtk_widget_show (table);
+
+  label = gtk_label_new (_("Name:"));
+  entry = gtk_entry_new ();
+  prop_dialog->attr_name = GTK_ENTRY (entry);
+  g_signal_connect (G_OBJECT (entry),
+                    "changed",
+                    G_CALLBACK (name_changed),
+                    umlclass);
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_table_attach (GTK_TABLE (table), label, 0,1,0,1, GTK_FILL,0, 0,0);
-  gtk_table_attach (GTK_TABLE (table), entry, 1,2,0,1, GTK_FILL | GTK_EXPAND,0, 0,2);
-
-  label = gtk_label_new(_("Type:"));
-  entry = gtk_entry_new();
-  prop_dialog->attr_type = GTK_ENTRY(entry);
-  g_signal_connect (G_OBJECT (entry), "focus_out_event",
-                   G_CALLBACK (attributes_update_event), umlclass);
-  g_signal_connect (G_OBJECT (entry), "activate",
-                   G_CALLBACK (attributes_update), umlclass);
+  gtk_table_attach (GTK_TABLE (table), label, 0,1,0,1, GTK_FILL, 0, 0, 0);
+  gtk_table_attach (GTK_TABLE (table), entry, 1,2,0,1, GTK_FILL | GTK_EXPAND, 0, 0, 2);
+  gtk_widget_show (label);
+  gtk_widget_show (entry);
+
+  label = gtk_label_new (_("Type:"));
+  entry = gtk_entry_new ();
+  prop_dialog->attr_type = GTK_ENTRY (entry);
+  g_signal_connect (G_OBJECT (entry),
+                    "changed",
+                    G_CALLBACK (type_changed),
+                    umlclass);
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_table_attach (GTK_TABLE (table), label, 0,1,1,2, GTK_FILL,0, 0,0);
-  gtk_table_attach (GTK_TABLE (table), entry, 1,2,1,2, GTK_FILL | GTK_EXPAND,0, 0,2);
-
-  label = gtk_label_new(_("Value:"));
-  entry = gtk_entry_new();
-  prop_dialog->attr_value = GTK_ENTRY(entry);
-  g_signal_connect (G_OBJECT (entry), "focus_out_event",
-                   G_CALLBACK (attributes_update_event), umlclass);
-  g_signal_connect (G_OBJECT (entry), "activate",
-                   G_CALLBACK (attributes_update), umlclass);
+  gtk_table_attach (GTK_TABLE (table), label, 0,1,1,2, GTK_FILL, 0, 0, 0);
+  gtk_table_attach (GTK_TABLE (table), entry, 1,2,1,2, GTK_FILL | GTK_EXPAND, 0, 0, 2);
+  gtk_widget_show (label);
+  gtk_widget_show (entry);
+
+  label = gtk_label_new (_("Value:"));
+  entry = gtk_entry_new ();
+  prop_dialog->attr_value = GTK_ENTRY (entry);
+  g_signal_connect (G_OBJECT (entry),
+                    "changed",
+                    G_CALLBACK (value_changed),
+                    umlclass);
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_table_attach (GTK_TABLE (table), label, 0,1,2,3, GTK_FILL,0, 0,0);
-  gtk_table_attach (GTK_TABLE (table), entry, 1,2,2,3, GTK_FILL | GTK_EXPAND,0, 0,2);
+  gtk_table_attach (GTK_TABLE (table), label, 0,1,2,3, GTK_FILL, 0, 0, 0);
+  gtk_table_attach (GTK_TABLE (table), entry, 1,2,2,3, GTK_FILL | GTK_EXPAND, 0, 0, 2);
+  gtk_widget_show (label);
+  gtk_widget_show (entry);
 
-  label = gtk_label_new(_("Comment:"));
+  label = gtk_label_new (_("Comment:"));
   scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
-                                      GTK_SHADOW_IN);
-  entry = gtk_text_view_new ();
-  prop_dialog->attr_comment = GTK_TEXT_VIEW(entry);
+                                       GTK_SHADOW_IN);
+
+  prop_dialog->attr_comment_buffer = gtk_text_buffer_new (NULL);
+  entry = gtk_text_view_new_with_buffer (prop_dialog->attr_comment_buffer);
+  prop_dialog->attr_comment = GTK_TEXT_VIEW (entry);
+  g_signal_connect (prop_dialog->attr_comment_buffer,
+                    "changed",
+                    G_CALLBACK (comment_changed),
+                    umlclass);
   gtk_container_add (GTK_CONTAINER (scrolledwindow), entry);
   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (entry), GTK_WRAP_WORD);
-  gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW (entry),TRUE);
-  g_signal_connect (G_OBJECT (entry), "focus_out_event",
-                   G_CALLBACK (attributes_update_event), umlclass);
+  gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (entry), TRUE);
+  gtk_widget_show (entry);
 #if 0 /* while the GtkEntry has a "activate" signal, GtkTextView does not.
        * Maybe we should connect to "set-focus-child" instead?
        */
@@ -565,39 +721,43 @@ _attributes_create_page(GtkNotebook *notebook,  UMLClass *umlclass)
                    G_CALLBACK (attributes_update), umlclass);
 #endif
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_table_attach (GTK_TABLE (table), label, 0,1,3,4, GTK_FILL,0, 0,0);
-  gtk_table_attach (GTK_TABLE (table), scrolledwindow, 1,2,3,4, GTK_FILL | GTK_EXPAND,0, 0,2);
+  gtk_table_attach (GTK_TABLE (table), label, 0,1,3,4, GTK_FILL, 0, 0, 0);
+  gtk_table_attach (GTK_TABLE (table), scrolledwindow, 1,2,3,4, GTK_FILL | GTK_EXPAND, 0, 0, 2);
+  gtk_widget_show (label);
+  gtk_widget_show (scrolledwindow);
 
 
-  label = gtk_label_new(_("Visibility:"));
-
+  label = gtk_label_new (_("Visibility:"));
   prop_dialog->attr_visible = omenu = dia_option_menu_new ();
-  g_signal_connect (G_OBJECT (omenu), "changed",
-                   G_CALLBACK (attributes_update), umlclass);
+  g_signal_connect (G_OBJECT (omenu),
+                    "changed",
+                    G_CALLBACK (visibility_changed),
+                    umlclass);
   dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Public"), UML_PUBLIC);
   dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Private"), UML_PRIVATE);
   dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Protected"), UML_PROTECTED);
   dia_option_menu_add_item (DIA_OPTION_MENU (omenu), _("Implementation"), UML_IMPLEMENTATION);
-
-  {
-    GtkWidget * align;
-    align = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
-    gtk_container_add(GTK_CONTAINER(align), omenu);
-    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-    gtk_table_attach (GTK_TABLE (table), label, 0,1,4,5, GTK_FILL,0, 0,3);
-    gtk_table_attach (GTK_TABLE (table), align, 1,2,4,5, GTK_FILL,0, 0,3);
-  }
-
-  hbox2 = gtk_hbox_new(FALSE, 5);
-  checkbox = gtk_check_button_new_with_label(_("Class scope"));
-  prop_dialog->attr_class_scope = GTK_TOGGLE_BUTTON(checkbox);
+  gtk_table_attach (GTK_TABLE (table), label, 0,1,4,5, GTK_FILL,0, 0,3);
+  gtk_widget_show (label);
+  gtk_widget_show (omenu);
+
+  hbox2 = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (hbox2), omenu, FALSE, TRUE, 0);
+  gtk_table_attach (GTK_TABLE (table), hbox2, 1,2,4,5, GTK_FILL,0, 0,3);
+  gtk_widget_show (hbox2);
+
+  hbox2 = gtk_hbox_new (FALSE, 6);
+  checkbox = gtk_check_button_new_with_label (_("Class scope"));
+  prop_dialog->attr_class_scope = GTK_TOGGLE_BUTTON (checkbox);
+  g_signal_connect (checkbox,
+                    "toggled",
+                    G_CALLBACK (scope_changed),
+                    umlclass);
   gtk_box_pack_start (GTK_BOX (hbox2), checkbox, TRUE, TRUE, 0);
   gtk_box_pack_start (GTK_BOX (vbox2), hbox2, FALSE, TRUE, 0);
+  gtk_widget_show (hbox2);
+  gtk_widget_show (checkbox);
 
-  gtk_widget_show(vbox2);
-
-  gtk_widget_show_all (vbox);
   gtk_widget_show (page_label);
-  gtk_notebook_append_page(notebook, vbox, page_label);
-
+  gtk_notebook_append_page (notebook, vbox, page_label);
 }
diff --git a/objects/UML/class_dialog.c b/objects/UML/class_dialog.c
index a1bca815..e6df964d 100644
--- a/objects/UML/class_dialog.c
+++ b/objects/UML/class_dialog.c
@@ -32,7 +32,6 @@
 #include <config.h>
 
 #include <assert.h>
-#undef GTK_DISABLE_DEPRECATED /* GtkList, ... */
 #include <gtk/gtk.h>
 #include <math.h>
 #include <string.h>
@@ -165,6 +164,32 @@ _umlclass_store_disconnects(UMLClassDialog *prop_dialog,
  ******************** CLASS *****************************
  ********************************************************/
 
+/*
+        get the contents of a comment text view.
+*/
+static gchar *
+_class_get_comment (GtkTextView *view)
+{
+  GtkTextBuffer * buffer = gtk_text_view_get_buffer(view);
+  GtkTextIter start;
+  GtkTextIter end;
+
+  gtk_text_buffer_get_start_iter (buffer, &start);
+  gtk_text_buffer_get_end_iter (buffer, &end);
+
+  return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+}
+
+
+static void
+_class_set_comment (GtkTextView *view, gchar *text)
+{
+  GtkTextBuffer * buffer = gtk_text_view_get_buffer (view);
+
+  gtk_text_buffer_set_text (buffer, text, -1);
+}
+
+
 static void
 class_read_from_dialog(UMLClass *umlclass, UMLClassDialog *prop_dialog)
 {
@@ -553,7 +578,6 @@ switch_page_callback(GtkNotebook *notebook,
   prop_dialog = umlclass->properties_dialog;
 
   if (prop_dialog != NULL) {
-    _attributes_get_current_values(prop_dialog);
     _templates_get_current_values(prop_dialog);
   }
 }
@@ -581,8 +605,9 @@ fill_in_dialog(UMLClass *umlclass)
   _templates_fill_in_dialog(umlclass);
 }
 
+
 ObjectChange *
-umlclass_apply_props_from_dialog(UMLClass *umlclass, GtkWidget *widget)
+umlclass_apply_props_from_dialog (UMLClass *umlclass, GtkWidget *widget)
 {
   UMLClassDialog *prop_dialog;
   DiaObject *obj;
@@ -602,7 +627,7 @@ umlclass_apply_props_from_dialog(UMLClass *umlclass, GtkWidget *widget)
   /* Allocate enought connection points for attributes and operations. */
   /* (two per op/attr) */
   if ( (gtk_toggle_button_get_active (prop_dialog->attr_vis)) && (!gtk_toggle_button_get_active 
(prop_dialog->attr_supp)))
-    num_attrib = g_list_length(prop_dialog->attributes_list->children);
+    num_attrib =gtk_tree_model_iter_n_children (GTK_TREE_MODEL (prop_dialog->attributes_store), NULL);
   else
     num_attrib = 0;
   if (gtk_toggle_button_get_active (prop_dialog->op_vis) &&
@@ -697,7 +722,6 @@ umlclass_get_properties(UMLClass *umlclass, gboolean is_default)
     g_object_ref_sink(vbox);
     prop_dialog->dialog = vbox;
 
-    prop_dialog->current_attr = NULL;
     prop_dialog->current_templ = NULL;
     prop_dialog->deleted_connections = NULL;
     prop_dialog->added_connections = NULL;
@@ -751,10 +775,10 @@ umlclass_free_state(UMLClassState *state)
 
   list = state->attributes;
   while (list) {
-    uml_attribute_destroy((UMLAttribute *) list->data);
-    list = g_list_next(list);
+    uml_attribute_unref ((UMLAttribute *) list->data);
+    list = g_list_next (list);
   }
-  g_list_free(state->attributes);
+  g_list_free (state->attributes);
 
   g_list_free_full (state->operations, (GDestroyNotify) uml_operation_unref);
 
@@ -902,8 +926,9 @@ umlclass_update_connectionpoints(UMLClass *umlclass)
     list = g_list_next(list);
   }
 
-  if (prop_dialog)
-    gtk_list_clear_items (GTK_LIST (prop_dialog->attributes_list), 0, -1);
+  if (prop_dialog) {
+    gtk_list_store_clear (prop_dialog->attributes_store);
+  }
 
   list = umlclass->operations;
   while (list != NULL) {
@@ -1087,21 +1112,6 @@ new_umlclass_change(UMLClass *obj, UMLClassState *saved_state,
 
   return (ObjectChange *)change;
 }
-/*
-        get the contents of a comment text view.
-*/
-gchar *
-_class_get_comment (GtkTextView *view)
-{
-  GtkTextBuffer * buffer = gtk_text_view_get_buffer(view);
-  GtkTextIter start;
-  GtkTextIter end;
-
-  gtk_text_buffer_get_start_iter (buffer, &start);
-  gtk_text_buffer_get_end_iter (buffer, &end);
-
-  return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
-}
 
 
 char *
@@ -1115,12 +1125,3 @@ buffer_get_text (GtkTextBuffer *buffer)
 
   return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
 }
-
-
-void
-_class_set_comment(GtkTextView *view, gchar *text)
-{
-  GtkTextBuffer * buffer = gtk_text_view_get_buffer (view);
-
-  gtk_text_buffer_set_text (buffer, text, -1);
-}
diff --git a/objects/UML/class_dialog.h b/objects/UML/class_dialog.h
index edb52ca2..9301fd6b 100644
--- a/objects/UML/class_dialog.h
+++ b/objects/UML/class_dialog.h
@@ -45,12 +45,13 @@ struct _UMLClassDialog {
   GList *added_connections;
   GList *deleted_connections;
 
-  GtkList *attributes_list;
-  GtkListItem *current_attr;
+  GtkWidget *attributes;
+  GtkListStore *attributes_store;
   GtkEntry *attr_name;
   GtkEntry *attr_type;
   GtkEntry *attr_value;
   GtkTextView *attr_comment;
+  GtkTextBuffer *attr_comment_buffer;
   GtkWidget *attr_visible;
   GtkToggleButton *attr_class_scope;
 
@@ -61,7 +62,6 @@ struct _UMLClassDialog {
   GtkEntry *op_stereotype;
   GtkTextView *op_comment;
   GtkTextBuffer *op_comment_buffer;
-
   GtkWidget *op_visible;
   GtkToggleButton *op_class_scope;
   GtkWidget *op_inheritance_type;
@@ -69,7 +69,6 @@ struct _UMLClassDialog {
 
   GtkWidget *parameters;
   GtkListStore *parameters_store;
-
   GtkEntry *param_name;
   GtkEntry *param_type;
   GtkEntry *param_value;
@@ -91,12 +90,8 @@ struct _UMLClassDialog {
 
 void _umlclass_store_disconnects(UMLClassDialog *prop_dialog, ConnectionPoint *cp);
 
-gchar *_class_get_comment(GtkTextView *);
-void _class_set_comment(GtkTextView *, gchar *);
 char *buffer_get_text (GtkTextBuffer *buffer);
 
-void _attributes_get_current_values(UMLClassDialog *prop_dialog);
-void _operations_get_current_values(UMLClassDialog *prop_dialog);
 void _templates_get_current_values(UMLClassDialog *prop_dialog);
 
 void _attributes_fill_in_dialog(UMLClass *umlclass);
diff --git a/objects/UML/class_operations_dialog.c b/objects/UML/class_operations_dialog.c
index 26fd74a1..834a396e 100644
--- a/objects/UML/class_operations_dialog.c
+++ b/objects/UML/class_operations_dialog.c
@@ -170,12 +170,16 @@ static void
 parameters_set_values (UMLClassDialog *prop_dialog,
                        UMLParameter   *param)
 {
+  char *comment;
+
   gtk_entry_set_text (prop_dialog->param_name, param->name? param->name : "");
   gtk_entry_set_text (prop_dialog->param_type, param->type? param->type : "");
   gtk_entry_set_text (prop_dialog->param_value, param->value? param->value : "");
+  comment = g_strdup (param->comment? param->comment : "");
   gtk_text_buffer_set_text (prop_dialog->param_comment_buffer,
-                            param->comment? g_strdup (param->comment) : "",
+                            comment,
                             -1);
+  g_free (comment);
 
   dia_option_menu_set_active (DIA_OPTION_MENU (prop_dialog->param_kind),
                               param->kind);
@@ -230,7 +234,6 @@ parameters_list_new_callback (GtkWidget *button,
   UMLClassDialog *prop_dialog;
   UMLOperation *current_op;
   UMLParameter *param;
-  char *utf;
   GtkTreeIter iter;
   GtkTreeSelection *selection;
 
@@ -242,8 +245,6 @@ parameters_list_new_callback (GtkWidget *button,
 
   param = uml_parameter_new ();
 
-  utf = uml_parameter_get_string (param);
-
   gtk_list_store_append (prop_dialog->parameters_store, &iter);
   update_parameter (prop_dialog, param, &iter);
 
@@ -253,7 +254,6 @@ parameters_list_new_callback (GtkWidget *button,
   sync_params_to_operation (GTK_TREE_MODEL (prop_dialog->parameters_store),
                             current_op);
 
-  g_clear_pointer (&utf, g_free);
   g_clear_pointer (&param, uml_parameter_unref);
   g_clear_pointer (&current_op, uml_operation_unref);
 }
@@ -409,13 +409,16 @@ operations_set_values (UMLClassDialog *prop_dialog, UMLOperation *op)
   UMLParameter *param;
   GtkTreeIter iter;
   gchar *str;
+  char *comment;
 
   gtk_entry_set_text (prop_dialog->op_name, op->name? op->name : "");
   gtk_entry_set_text (prop_dialog->op_type, op->type? op->type : "");
   gtk_entry_set_text (prop_dialog->op_stereotype, op->stereotype? op->stereotype : "");
+  comment = g_strdup (op->comment? op->comment : "");
   gtk_text_buffer_set_text (prop_dialog->op_comment_buffer,
-                            op->comment? g_strdup (op->comment) : "",
+                            comment,
                             -1);
+  g_free (comment);
 
   dia_option_menu_set_active (DIA_OPTION_MENU (prop_dialog->op_visible),
                               op->visibility);
@@ -449,7 +452,7 @@ operations_clear_values (UMLClassDialog *prop_dialog)
   gtk_entry_set_text (prop_dialog->op_name, "");
   gtk_entry_set_text (prop_dialog->op_type, "");
   gtk_entry_set_text (prop_dialog->op_stereotype, "");
-  _class_set_comment (prop_dialog->op_comment, "");
+  gtk_text_buffer_set_text (prop_dialog->op_comment_buffer, "", -1);
   gtk_toggle_button_set_active (prop_dialog->op_class_scope, FALSE);
   gtk_toggle_button_set_active (prop_dialog->op_query, FALSE);
 
@@ -1026,12 +1029,12 @@ operations_parameters_editor_create_vbox (UMLClass *umlclass)
 
   prop_dialog = umlclass->properties_dialog;
 
-  vbox2 = gtk_vbox_new(FALSE, 5);
+  vbox2 = gtk_vbox_new (FALSE, 6);
   /* Parameters list label */
-  hbox2 = gtk_hbox_new(FALSE, 5);
+  hbox2 = gtk_hbox_new (FALSE, 6);
 
-  label = gtk_label_new(_("Parameters:"));
-  gtk_box_pack_start( GTK_BOX(hbox2), label, FALSE, TRUE, 0);
+  label = gtk_label_new (_("Parameters:"));
+  gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
 
   gtk_box_pack_start (GTK_BOX (vbox2), hbox2, TRUE, TRUE, 0);
 
@@ -1039,7 +1042,8 @@ operations_parameters_editor_create_vbox (UMLClass *umlclass)
   hbox2 = gtk_hbox_new (FALSE, 6);
 
   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
-  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
+                                       GTK_SHADOW_IN);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
                                   GTK_POLICY_AUTOMATIC,
                                   GTK_POLICY_AUTOMATIC);
@@ -1051,6 +1055,8 @@ operations_parameters_editor_create_vbox (UMLClass *umlclass)
                                                       DIA_UML_TYPE_PARAMETER);
   prop_dialog->parameters = gtk_tree_view_new_with_model (GTK_TREE_MODEL (prop_dialog->parameters_store));
   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (prop_dialog->parameters), FALSE);
+  gtk_container_set_focus_vadjustment (GTK_CONTAINER (prop_dialog->parameters),
+                                       gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW 
(scrolled_win)));
   select = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_dialog->parameters));
   g_signal_connect (G_OBJECT (select),
                     "changed",
@@ -1068,9 +1074,7 @@ operations_parameters_editor_create_vbox (UMLClass *umlclass)
   gtk_tree_view_append_column (GTK_TREE_VIEW (prop_dialog->parameters),
                                column);
 
-  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), prop_dialog->parameters);
-  gtk_container_set_focus_vadjustment (GTK_CONTAINER (prop_dialog->parameters),
-                                       gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW 
(scrolled_win)));
+  gtk_container_add (GTK_CONTAINER (scrolled_win), prop_dialog->parameters);
   gtk_widget_show (prop_dialog->parameters);
 
 
@@ -1390,10 +1394,10 @@ _operations_create_page (GtkNotebook *notebook,  UMLClass *umlclass)
   /* Operations page: */
   page_label = gtk_label_new_with_mnemonic (_("_Operations"));
 
-  vbox = gtk_vbox_new(FALSE, 5);
-  gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
+  vbox = gtk_vbox_new (FALSE, 6);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
 
-  hbox = gtk_hbox_new(FALSE, 5);
+  hbox = gtk_hbox_new (FALSE, 6);
 
   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
@@ -1436,7 +1440,7 @@ _operations_create_page (GtkNotebook *notebook,  UMLClass *umlclass)
   gtk_tree_view_append_column (GTK_TREE_VIEW (prop_dialog->operations),
                                column);
 
-  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), prop_dialog->operations);
+  gtk_container_add (GTK_CONTAINER (scrolled_win), prop_dialog->operations);
   gtk_container_set_focus_vadjustment (GTK_CONTAINER (prop_dialog->operations),
                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW 
(scrolled_win)));
   gtk_widget_show (prop_dialog->operations);
@@ -1499,23 +1503,23 @@ _operations_create_page (GtkNotebook *notebook,  UMLClass *umlclass)
 
   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
 
-  frame = gtk_frame_new(_("Operation data"));
-  vbox2 = gtk_vbox_new(FALSE, 0);
+  frame = gtk_frame_new (_("Operation data"));
+  vbox2 = gtk_vbox_new (FALSE, 0);
   hbox = operations_data_create_hbox (umlclass);
   gtk_box_pack_start (GTK_BOX (vbox2), hbox, TRUE, TRUE, 0);
   gtk_container_add (GTK_CONTAINER (frame), vbox2);
-  gtk_widget_show(frame);
+  gtk_widget_show (frame);
   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
 
   /* parameter stuff below operation stuff */
-  hbox = gtk_hbox_new (FALSE, 5);
+  hbox = gtk_hbox_new (FALSE, 6);
   vbox3 = operations_parameters_editor_create_vbox (umlclass);
-  gtk_box_pack_start (GTK_BOX (hbox), vbox3, TRUE, TRUE, 5);
+  gtk_box_pack_start (GTK_BOX (hbox), vbox3, TRUE, TRUE, 6);
 
   vbox3 = operations_parameters_data_create_vbox (umlclass);
-  gtk_box_pack_start (GTK_BOX (hbox), vbox3, TRUE, TRUE, 5);
+  gtk_box_pack_start (GTK_BOX (hbox), vbox3, TRUE, TRUE, 6);
 
-  gtk_box_pack_start (GTK_BOX (vbox2), hbox, TRUE, TRUE, 5);
+  gtk_box_pack_start (GTK_BOX (vbox2), hbox, TRUE, TRUE, 6);
 
   gtk_widget_show_all (vbox);
   gtk_widget_show (page_label);
diff --git a/objects/UML/uml.h b/objects/UML/uml.h
index 6d63b408..0836eeef 100644
--- a/objects/UML/uml.h
+++ b/objects/UML/uml.h
@@ -125,9 +125,6 @@ struct _UMLFormalParameter {
 /** end stereotype symbol(like \xbb) for local locale */
 #define UML_STEREOTYPE_END _(">>")
 
-/** calculated the 'formated' representation */
-extern gchar *uml_get_attribute_string (UMLAttribute *attribute);
-
 
 
 #define DIA_UML_TYPE_PARAMETER uml_parameter_get_type ()
@@ -161,20 +158,30 @@ char         *uml_get_operation_string               (UMLOperation  *operation);
 
 
 
+#define DIA_UML_TYPE_ATTRIBUTE uml_attribute_get_type ()
+
+UMLAttribute *uml_attribute_new                      (void);
+GType         uml_attribute_get_type                 (void);
+UMLAttribute *uml_attribute_copy                     (UMLAttribute  *attr);
+void          uml_attribute_copy_into                (UMLAttribute  *srcattr,
+                                                      UMLAttribute  *destattr);
+UMLAttribute *uml_attribute_ref                      (UMLAttribute  *attribute);
+void          uml_attribute_unref                    (UMLAttribute  *attribute);
+void          uml_attribute_write                    (AttributeNode  attr_node,
+                                                      UMLAttribute  *attr,
+                                                      DiaContext    *ctx);
+void          uml_attribute_ensure_connection_points (UMLAttribute  *attr,
+                                                      DiaObject     *obj);
+/** calculated the 'formated' representation */
+char         *uml_attribute_get_string               (UMLAttribute  *attribute);
+
+
+
 /** 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_formalparameter_destroy(UMLFormalParameter *param);
-extern UMLAttribute *uml_attribute_new(void);
 extern UMLFormalParameter *uml_formalparameter_new(void);
-
-extern void uml_attribute_ensure_connection_points (UMLAttribute *attr, DiaObject* obj);
-
-extern void uml_attribute_write(AttributeNode attr_node, UMLAttribute *attr, DiaContext *ctx);
 extern void uml_formalparameter_write(AttributeNode attr_node, UMLFormalParameter *param, DiaContext *ctx);
 
 #endif /* UML_H */
diff --git a/objects/UML/umlattribute.c b/objects/UML/umlattribute.c
index ad98d5e0..af2da73e 100644
--- a/objects/UML/umlattribute.c
+++ b/objects/UML/umlattribute.c
@@ -64,23 +64,25 @@ static PropOffset umlattribute_offsets[] = {
 
 PropDescDArrayExtra umlattribute_extra = {
   { umlattribute_props, umlattribute_offsets, "umlattribute" },
-  (NewRecordFunc)uml_attribute_new,
-  (FreeRecordFunc)uml_attribute_destroy
+  (NewRecordFunc) uml_attribute_new,
+  (FreeRecordFunc) uml_attribute_unref
 };
 
+G_DEFINE_BOXED_TYPE (UMLAttribute, uml_attribute, uml_attribute_ref, uml_attribute_unref)
+
 
 UMLAttribute *
-uml_attribute_new(void)
+uml_attribute_new (void)
 {
   UMLAttribute *attr;
   static gint next_id = 1;
 
-  attr = g_new0(UMLAttribute, 1);
+  attr = g_rc_box_new0 (UMLAttribute);
   attr->internal_id = next_id++;
-  attr->name = g_strdup("");
-  attr->type = g_strdup("");
+  attr->name = NULL;
+  attr->type = NULL;
   attr->value = NULL;
-  attr->comment = g_strdup("");
+  attr->comment = NULL;
   attr->visibility = UML_PUBLIC;
   attr->abstract = FALSE;
   attr->class_scope = FALSE;
@@ -91,110 +93,126 @@ uml_attribute_new(void)
   return attr;
 }
 
+
 /** Copy the data of an attribute into another, but not the connections.
  * Frees up any strings in the attribute being copied into. */
 void
-uml_attribute_copy_into(UMLAttribute *attr, UMLAttribute *newattr)
+uml_attribute_copy_into (UMLAttribute *attr, UMLAttribute *newattr)
 {
   newattr->internal_id = attr->internal_id;
+
   if (newattr->name != NULL) {
-    g_free(newattr->name);
+    g_clear_pointer (&newattr->name, g_free);
   }
-  newattr->name = g_strdup(attr->name);
+  newattr->name = g_strdup (attr->name);
+
   if (newattr->type != NULL) {
-    g_free(newattr->type);
+    g_clear_pointer (&newattr->type, g_free);
   }
-  newattr->type = g_strdup(attr->type);
+  newattr->type = g_strdup (attr->type);
 
   if (newattr->value != NULL) {
-    g_free(newattr->value);
-  }
-  if (attr->value != NULL) {
-    newattr->value = g_strdup(attr->value);
-  } else {
-    newattr->value = NULL;
+     g_clear_pointer (&newattr->value, g_free);
   }
+  newattr->value = g_strdup (attr->value);
 
   if (newattr->comment != NULL) {
-    g_free(newattr->comment);
+    g_clear_pointer (&newattr->comment, g_free);
   }
-  if (attr->comment != NULL)
-    newattr->comment = g_strdup (attr->comment);
-  else
-    newattr->comment = NULL;
+  newattr->comment = g_strdup (attr->comment);
 
   newattr->visibility = attr->visibility;
   newattr->abstract = attr->abstract;
   newattr->class_scope = attr->class_scope;
 }
 
+
 /** Copy an attribute's content.
  */
 UMLAttribute *
-uml_attribute_copy(UMLAttribute *attr)
+uml_attribute_copy (UMLAttribute *attr)
 {
   UMLAttribute *newattr;
 
-  newattr = g_new0(UMLAttribute, 1);
+  newattr = uml_attribute_new ();
 
-  uml_attribute_copy_into(attr, newattr);
+  uml_attribute_copy_into (attr, newattr);
 
   return newattr;
 }
 
-void
-uml_attribute_destroy(UMLAttribute *attr)
+
+UMLAttribute *
+uml_attribute_ref (UMLAttribute *self)
+{
+  g_return_val_if_fail (self != NULL, NULL);
+
+  return g_rc_box_acquire (self);
+}
+
+
+static void
+attribute_destroy (UMLAttribute *attr)
 {
-  g_free(attr->name);
-  g_free(attr->type);
-  if (attr->value != NULL)
-    g_free(attr->value);
-  if (attr->comment != NULL)
-    g_free(attr->comment);
+  g_free (attr->name);
+  g_free (attr->type);
+  g_free (attr->value);
+  g_free (attr->comment);
 #if 0 /* free'd elsewhere */
   g_free(attr->left_connection);
   g_free(attr->right_connection);
 #endif
-  g_free(attr);
 }
 
+
 void
-uml_attribute_write(AttributeNode attr_node, UMLAttribute *attr, DiaContext *ctx)
+uml_attribute_unref (UMLAttribute *self)
+{
+  g_rc_box_release_full (self, (GDestroyNotify) attribute_destroy);
+}
+
+
+void
+uml_attribute_write (AttributeNode  attr_node,
+                     UMLAttribute  *attr,
+                     DiaContext    *ctx)
 {
   DataNode composite;
 
-  composite = data_add_composite(attr_node, "umlattribute", ctx);
-
-  data_add_string(composite_add_attribute(composite, "name"),
-                 attr->name, ctx);
-  data_add_string(composite_add_attribute(composite, "type"),
-                 attr->type, ctx);
-  data_add_string(composite_add_attribute(composite, "value"),
-                 attr->value, ctx);
-  data_add_string(composite_add_attribute(composite, "comment"),
-                 attr->comment, ctx);
-  data_add_enum(composite_add_attribute(composite, "visibility"),
-               attr->visibility, ctx);
-  data_add_boolean(composite_add_attribute(composite, "abstract"),
-                 attr->abstract, ctx);
-  data_add_boolean(composite_add_attribute(composite, "class_scope"),
-                 attr->class_scope, ctx);
+  composite = data_add_composite (attr_node, "umlattribute", ctx);
+
+  data_add_string (composite_add_attribute (composite, "name"),
+                   attr->name, ctx);
+  data_add_string (composite_add_attribute (composite, "type"),
+                   attr->type, ctx);
+  data_add_string (composite_add_attribute (composite, "value"),
+                   attr->value, ctx);
+  data_add_string (composite_add_attribute (composite, "comment"),
+                   attr->comment, ctx);
+  data_add_enum (composite_add_attribute (composite, "visibility"),
+                 attr->visibility, ctx);
+  data_add_boolean (composite_add_attribute (composite, "abstract"),
+                    attr->abstract, ctx);
+  data_add_boolean (composite_add_attribute (composite, "class_scope"),
+                    attr->class_scope, ctx);
 }
 
+
 /* Warning, the following *must* be strictly ASCII characters (or fix the
    following code for UTF-8 cleanliness */
 
 char visible_char[] = { '+', '-', '#', ' ' };
 
 char *
-uml_get_attribute_string (UMLAttribute *attribute)
+uml_attribute_get_string (UMLAttribute *attribute)
 {
   int len;
   char *str;
 
   len = 1 + (attribute->name ? strlen (attribute->name) : 0)
           + (attribute->type ? strlen (attribute->type) : 0);
-  if (attribute->name && attribute->name[0] && attribute->type && attribute->type[0]) {
+  if (attribute->name && attribute->name[0] &&
+      attribute->type && attribute->type[0]) {
     len += 2;
   }
   if (attribute->value != NULL && attribute->value[0] != '\0') {
@@ -207,7 +225,8 @@ uml_get_attribute_string (UMLAttribute *attribute)
   str[1] = 0;
 
   strcat (str, attribute->name ? attribute->name : "");
-  if (attribute->name && attribute->name[0] && attribute->type && attribute->type[0]) {
+  if (attribute->name && attribute->name[0] &&
+      attribute->type && attribute->type[0]) {
     strcat (str, ": ");
   }
   strcat (str, attribute->type ? attribute->type : "");
@@ -221,6 +240,7 @@ uml_get_attribute_string (UMLAttribute *attribute)
   return str;
 }
 
+
 /*!
  * The ownership of these connection points is quite complicated. Instead of being part of
  * the UMLAttribute as one may expect at first, they are somewhat in between the DiaObject


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