[dia] layer-dialog: drop usage of GtkOptionMenu



commit 6bb18acf6f1b5f5a052349eaad35a33e649d8a56
Author: Zander Brown <zbrown gnome org>
Date:   Wed Sep 25 18:04:59 2019 +0100

    layer-dialog: drop usage of GtkOptionMenu
    
    Uses a GtkComboBox (indirectly) backed by a list of open diagrams maintained by DiaApplication
    
    Unifies the layer editor design between integrated/classic

 app/app_procs.c             |  37 ++--
 app/commands.c              |  13 +-
 app/dia-application.c       | 154 +++++++++-----
 app/dia-application.h       |  24 ++-
 app/dia.def                 |   6 +-
 app/diagram.c               | 505 +++++++++++++++++++++++++-------------------
 app/diagram.h               |  13 +-
 app/diagram_tree_model.c    |  12 +-
 app/display.c               |  46 ++--
 app/filedlg.c               |  12 +-
 app/layer_dialog.c          | 447 ++++++++++++++++++++++-----------------
 app/layer_dialog.h          |   7 +-
 lib/layer.c                 |   8 +-
 plug-ins/python/diamodule.c |  23 +-
 14 files changed, 740 insertions(+), 567 deletions(-)
---
diff --git a/app/app_procs.c b/app/app_procs.c
index 4b8c7e65..f150dcfa 100644
--- a/app/app_procs.c
+++ b/app/app_procs.c
@@ -479,7 +479,11 @@ handle_initial_diagram (const char *in_file_name,
     if (g_file_test (in_file_name, G_FILE_TEST_EXISTS)) {
       diagram = diagram_load (in_file_name, NULL);
     } else {
-      diagram = new_diagram (in_file_name);
+      GFile *file = g_file_new_for_path (in_file_name);
+
+      diagram = dia_diagram_new (file);
+
+      g_clear_object (&file);
     }
 
     if (diagram != NULL) {
@@ -845,29 +849,16 @@ app_init (int argc, char **argv)
                                           output_directory);
 
   if (dia_is_interactive && files == NULL && !nonew) {
-    if (use_integrated_ui) {
-      GList * list;
+    GList * list;
 
-      file_new_callback (NULL);
-      list = dia_open_diagrams ();
-      if (list) {
-        Diagram * diagram = list->data;
-        diagram_update_extents (diagram);
-        diagram->is_default = TRUE;
-      }
-    } else {
-      gchar *filename = g_filename_from_utf8 (_("Diagram1.dia"), -1, NULL, NULL, NULL);
-      Diagram *diagram = new_diagram (filename);
-      g_free (filename);
-
-      if (diagram != NULL) {
-        diagram_update_extents (diagram);
-        diagram->is_default = TRUE;
-        /* I think this is done in diagram_init() with a call to
-         * layer_dialog_update_diagram_list() */
-        layer_dialog_set_diagram (diagram);
-        new_display (diagram);
-      }
+    file_new_callback (NULL);
+
+    list = dia_open_diagrams ();
+    if (list) {
+      Diagram * diagram = list->data;
+      diagram_update_extents (diagram);
+      diagram->is_default = TRUE;
+      layer_dialog_set_diagram (diagram);
     }
   }
   g_slist_free (files);
diff --git a/app/commands.c b/app/commands.c
index 5fdf9c9c..9d456ab1 100644
--- a/app/commands.c
+++ b/app/commands.c
@@ -156,15 +156,18 @@ file_new_callback (GtkAction *action)
 {
   Diagram *dia;
   static int untitled_nr = 1;
-  gchar *name, *filename;
+  gchar *name;
+  GFile *file;
 
   name = g_strdup_printf (_("Diagram%d.dia"), untitled_nr++);
-  filename = g_filename_from_utf8 (name, -1, NULL, NULL, NULL);
-  dia = new_diagram (filename);
+  file = g_file_new_for_path (name);
+
+  dia = dia_diagram_new (file);
+
   new_display (dia);
-  dia_diagram_add (dia); /* notify DiagramTree etc. */
+
   g_free (name);
-  g_free (filename);
+  g_clear_object (&file);
 }
 
 void
diff --git a/app/dia-application.c b/app/dia-application.c
index cc9e422d..ff860b09 100644
--- a/app/dia-application.c
+++ b/app/dia-application.c
@@ -17,30 +17,15 @@ enum {
   DIAGRAM_ADD,
   DIAGRAM_CHANGE,
   DIAGRAM_REMOVE,
-  
+
   DISPLAY_ADD,
   DISPLAY_CHANGE,
   DISPLAY_REMOVE,
-  
+
   LAST_SIGNAL
 };
 
-static guint _dia_application_signals[LAST_SIGNAL] = { 0, };
-
-typedef struct _DiaApplicationClass DiaApplicationClass;
-struct _DiaApplicationClass
-{
-  GObjectClass parent_class;
-  
-  /* signalsing global state changes */
-  void (*diagram_add)    (DiaApplication *app, Diagram *diagram);
-  void (*diagram_change) (DiaApplication *app, Diagram *diagram, guint flags);
-  void (*diagram_remove) (DiaApplication *app, Diagram *diagram);
-  
-  void (*display_add)    (DiaApplication *app, DDisplay *display);
-  void (*display_change) (DiaApplication *app, DDisplay *display, guint flags);
-  void (*display_remove) (DiaApplication *app, DDisplay *display);
-};
+static guint signals[LAST_SIGNAL] = { 0, };
 
 /**
  * The central place managing global state changes like (dis-)appearance of diagrams
@@ -48,84 +33,139 @@ struct _DiaApplicationClass
 struct _DiaApplication
 {
   GObject parent;
-};
 
-GType dia_application_get_type (void);
-#define DIA_TYPE_APPLICATION (dia_application_get_type ())
+  GListStore *diagrams;
+};
 
 G_DEFINE_TYPE (DiaApplication, dia_application, G_TYPE_OBJECT);
 
 static void
 dia_application_class_init (DiaApplicationClass *klass)
 {
-  G_GNUC_UNUSED GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  
-  _dia_application_signals[DIAGRAM_ADD] =
-    g_signal_new ("diagram_add",
+  signals[DIAGRAM_ADD] =
+    g_signal_new ("diagram-add",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_FIRST,
-                  G_STRUCT_OFFSET (DiaApplicationClass, diagram_add),
+                  0,
                   NULL, NULL,
                   dia_marshal_VOID__OBJECT,
-                  G_TYPE_NONE, 
+                  G_TYPE_NONE,
                   1,
-                 DIA_TYPE_DIAGRAM);
-  _dia_application_signals[DIAGRAM_CHANGE] =
-    g_signal_new ("diagram_change",
+                  DIA_TYPE_DIAGRAM);
+
+  signals[DIAGRAM_CHANGE] =
+    g_signal_new ("diagram-change",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_FIRST,
-                  G_STRUCT_OFFSET (DiaApplicationClass, diagram_change),
+                  0,
                   NULL, NULL,
                   dia_marshal_VOID__OBJECT_UINT_POINTER,
-                  G_TYPE_NONE, 
+                  G_TYPE_NONE,
                   3,
-                 DIA_TYPE_DIAGRAM, G_TYPE_UINT, G_TYPE_POINTER);
-  _dia_application_signals[DIAGRAM_REMOVE] =
-    g_signal_new ("diagram_remove",
+                  DIA_TYPE_DIAGRAM,
+                  G_TYPE_UINT,
+                  G_TYPE_POINTER);
+
+  signals[DIAGRAM_REMOVE] =
+    g_signal_new ("diagram-remove",
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_FIRST,
-                  G_STRUCT_OFFSET (DiaApplicationClass, diagram_remove),
+                  0,
                   NULL, NULL,
                   dia_marshal_VOID__OBJECT,
-                  G_TYPE_NONE, 
+                  G_TYPE_NONE,
                   1,
-                 DIA_TYPE_DIAGRAM);
+                  DIA_TYPE_DIAGRAM);
 }
 
-static void 
+static void
 dia_application_init (DiaApplication *app)
 {
+  app->diagrams = g_list_store_new (DIA_TYPE_DIAGRAM);
 }
 
-static DiaApplication *_app = NULL;
-
 /* ensure the singleton is available */
 DiaApplication *
-dia_application_get (void)
+dia_application_get_default (void)
 {
-  
-  if (!_app)
-    _app = g_object_new (DIA_TYPE_APPLICATION, NULL);
-  
-  return _app;
+  static DiaApplication *instance;
+
+  if (instance == NULL) {
+    instance = g_object_new (DIA_TYPE_APPLICATION, NULL);
+    g_object_add_weak_pointer (G_OBJECT (instance), (gpointer *) &instance);
+  }
+
+  return instance;
 }
 
 void
-dia_diagram_add (Diagram *dia)
+dia_application_diagram_add (DiaApplication *app,
+                             Diagram        *dia)
 {
-  if (_app)
-    g_signal_emit (_app, _dia_application_signals[DIAGRAM_ADD], 0, dia);
+  g_return_if_fail (DIA_IS_APPLICATION (app));
+  g_return_if_fail (DIA_IS_DIAGRAM (dia));
+
+  g_list_store_append (app->diagrams, dia);
+
+  g_signal_emit (app, signals[DIAGRAM_ADD], 0, dia);
 }
+
+
 void
-dia_diagram_remove (Diagram *dia)
+dia_application_diagram_remove (DiaApplication *app,
+                                Diagram        *dia)
+{
+  int i = 0;
+
+  g_return_if_fail (DIA_IS_APPLICATION (app));
+  g_return_if_fail (DIA_IS_DIAGRAM (dia));
+
+  i = dia_application_diagram_index (app, dia);
+  g_list_store_remove (app->diagrams, i);
+
+  g_signal_emit (app, signals[DIAGRAM_REMOVE], 0, dia);
+}
+
+
+int
+dia_application_diagram_index (DiaApplication *self,
+                               Diagram        *dia)
+{
+  Diagram *item = NULL;
+  int i = 0;
+
+  g_return_val_if_fail (DIA_IS_APPLICATION (self), -1);
+  g_return_val_if_fail (DIA_IS_DIAGRAM (dia), -1);
+
+  while ((item = g_list_model_get_item (G_LIST_MODEL (self->diagrams), i))) {
+    if (item == dia) {
+      g_clear_object (&item);
+
+      return i;
+    }
+
+    g_clear_object (&item);
+
+    i++;
+  }
+
+  return -1;
+}
+
+
+GListModel *
+dia_application_get_diagrams (DiaApplication *app)
 {
-  if (_app)
-    g_signal_emit (_app, _dia_application_signals[DIAGRAM_REMOVE], 0, dia);
+  g_return_val_if_fail (DIA_IS_APPLICATION (app), NULL);
+
+  return G_LIST_MODEL (app->diagrams);
 }
 
-void 
-dia_diagram_change (Diagram *dia, guint flags, gpointer object)
+void
+dia_application_diagram_change (DiaApplication *app,
+                                Diagram        *dia,
+                                guint           flags,
+                                gpointer        object)
 {
-  if (_app)
-    g_signal_emit (_app, _dia_application_signals[DIAGRAM_CHANGE], 0, dia, flags, object);
+  g_signal_emit (app, signals[DIAGRAM_CHANGE], 0, dia, flags, object);
 }
diff --git a/app/dia-application.h b/app/dia-application.h
index dbfdbc1f..6216bb67 100644
--- a/app/dia-application.h
+++ b/app/dia-application.h
@@ -1,6 +1,8 @@
+#pragma once
+
 #include "diagram.h"
 
-typedef struct _DiaApplication DiaApplication;
+G_BEGIN_DECLS
 
 enum {
   DIAGRAM_CHANGE_NAME   = (1<<0),
@@ -8,8 +10,20 @@ enum {
   DIAGRAM_CHANGE_OBJECT = (1<<2)
 };
 
-DiaApplication * dia_application_get (void);
+#define DIA_TYPE_APPLICATION (dia_application_get_type ())
+G_DECLARE_FINAL_TYPE (DiaApplication, dia_application, DIA, APPLICATION, GObject)
+
+DiaApplication *dia_application_get_default             (void);
+void            dia_application_diagram_add             (DiaApplication *self,
+                                                         Diagram        *dia);
+void            dia_application_diagram_remove          (DiaApplication *self,
+                                                         Diagram        *dia);
+int             dia_application_diagram_index           (DiaApplication *self,
+                                                         Diagram        *dia);
+void            dia_application_diagram_change          (DiaApplication *self,
+                                                         Diagram        *dia,
+                                                         guint           flags,
+                                                         gpointer        object);
+GListModel     *dia_application_get_diagrams            (DiaApplication *self);
 
-void dia_diagram_add    (Diagram *dia);
-void dia_diagram_change (Diagram *dia, guint flags, gpointer object);
-void dia_diagram_remove (Diagram *dia);
+G_END_DECLS
diff --git a/app/dia.def b/app/dia.def
index b94c1c1d..e42d7e89 100644
--- a/app/dia.def
+++ b/app/dia.def
@@ -1,4 +1,4 @@
-EXPORTS 
+EXPORTS
  ; all these exports are only required for pydia
  ddisplay_active
  ddisplay_add_update_all
@@ -27,7 +27,9 @@ EXPORTS
  diagram_is_modified
  diagram_is_selected
  diagram_load
- new_diagram
+ dia_diagram_new
+ dia_diagram_set_file
+ dia_diagram_get_file
  diagram_get_type
  diagram_remove_all_selected
  diagram_save
diff --git a/app/diagram.c b/app/diagram.c
index db272771..09971894 100644
--- a/app/diagram.c
+++ b/app/diagram.c
@@ -46,6 +46,22 @@
 #include "diacontext.h"
 #include "dia-layer.h"
 
+typedef struct _DiagramPrivate DiagramPrivate;
+struct _DiagramPrivate {
+  GFile *file;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (Diagram, dia_diagram, DIA_TYPE_DIAGRAM_DATA)
+
+enum {
+  PROP_0,
+  PROP_FILE,
+  LAST_PROP
+};
+
+static GParamSpec *pspecs[LAST_PROP] = { NULL, };
+
+
 static GList *open_diagrams = NULL;
 
 struct _ObjectExtent
@@ -59,114 +75,133 @@ typedef struct _ObjectExtent ObjectExtent;
 static gint diagram_parent_sort_cb(gconstpointer a, gconstpointer b);
 
 
-static void diagram_class_init (DiagramClass *klass);
-static gboolean diagram_init(Diagram *obj, const char *filename);
-static void diagram_update_for_filename(Diagram *dia);
-
 enum {
   REMOVED,
   LAST_SIGNAL
 };
 
 static guint diagram_signals[LAST_SIGNAL] = { 0, };
-static gpointer parent_class = NULL;
 
-GType
-diagram_get_type (void)
+static void
+dia_diagram_set_property (GObject      *object,
+                          guint         property_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
 {
-  static GType object_type = 0;
-
-  if (!object_type)
-    {
-      static const GTypeInfo object_info =
-      {
-        sizeof (DiagramClass),
-        (GBaseInitFunc) NULL,
-        (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) diagram_class_init,
-        NULL,           /* class_finalize */
-        NULL,           /* class_data */
-        sizeof (Diagram),
-        0,              /* n_preallocs */
-       NULL            /* init */
-      };
-
-      object_type = g_type_register_static (DIA_TYPE_DIAGRAM_DATA,
-                                            "Diagram",
-                                            &object_info, 0);
-    }
+  Diagram *self = DIA_DIAGRAM (object);
 
-  return object_type;
+  switch (property_id) {
+    case PROP_FILE:
+      dia_diagram_set_file (self, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
 }
 
+
 static void
-diagram_dispose (GObject *object)
+dia_diagram_get_property (GObject    *object,
+                          guint       property_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
 {
-  Diagram *dia = DIA_DIAGRAM(object);
+  Diagram *self = DIA_DIAGRAM (object);
 
-  assert(dia->displays==NULL);
+  switch (property_id) {
+    case PROP_FILE:
+      g_value_set_object (value, dia_diagram_get_file (self));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
 
-  if (g_list_index(open_diagrams, dia) >= 0) {
-    dia_diagram_remove(dia);
 
-    open_diagrams = g_list_remove(open_diagrams, dia);
-    layer_dialog_update_diagram_list();
+static void
+dia_diagram_dispose (GObject *object)
+{
+  Diagram *dia = DIA_DIAGRAM (object);
+
+  assert (dia->displays==NULL);
+
+  if (g_list_index (open_diagrams, dia) >= 0) {
+    open_diagrams = g_list_remove (open_diagrams, dia);
   }
 
   if (dia->undo)
-    undo_destroy(dia->undo);
+    undo_destroy (dia->undo);
   dia->undo = NULL;
 
-  diagram_cleanup_autosave(dia);
+  diagram_cleanup_autosave (dia);
 
-  G_OBJECT_CLASS (parent_class)->dispose (object);
+  G_OBJECT_CLASS (dia_diagram_parent_class)->dispose (object);
 }
+
+
 static void
-diagram_finalize(GObject *object)
+dia_diagram_finalize (GObject *object)
 {
-  Diagram *dia = DIA_DIAGRAM(object);
+  Diagram *dia = DIA_DIAGRAM (object);
+  DiagramPrivate *priv = dia_diagram_get_instance_private (dia);
+
+  assert (dia->displays==NULL);
 
-  assert(dia->displays==NULL);
+  g_clear_object (&priv->file);
 
   if (dia->filename)
-    g_free(dia->filename);
+    g_free (dia->filename);
   dia->filename = NULL;
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (dia_diagram_parent_class)->finalize (object);
 }
 
+
 static void
 _diagram_removed (Diagram* dia)
 {
 }
 
+
 static void
-diagram_class_init (DiagramClass *klass)
+dia_diagram_class_init (DiagramClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->set_property = dia_diagram_set_property;
+  object_class->get_property = dia_diagram_get_property;
+  object_class->dispose = dia_diagram_dispose;
+  object_class->finalize = dia_diagram_finalize;
+
+  /**
+   * DiaDiagram:file:
+   *
+   * Since: 0.98
+   */
+  pspecs[PROP_FILE] =
+    g_param_spec_object ("file",
+                         "File",
+                         "The file backing this diagram",
+                         G_TYPE_FILE,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (object_class, LAST_PROP, pspecs);
 
   diagram_signals[REMOVED] =
     g_signal_new ("removed",
-                 G_TYPE_FROM_CLASS (klass),
-                 G_SIGNAL_RUN_FIRST,
-                 G_STRUCT_OFFSET (DiagramClass, removed),
-                 NULL, NULL,
-                 dia_marshal_VOID__VOID,
-                 G_TYPE_NONE, 0);
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (DiagramClass, removed),
+                  NULL, NULL,
+                  dia_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
 
   klass->removed = _diagram_removed;
-
-  object_class->finalize = diagram_finalize;
-  object_class->dispose = diagram_dispose;
 }
 
-GList *
-dia_open_diagrams(void)
-{
-  return open_diagrams;
-}
 
 static void
 _object_add (Diagram   *dia,
@@ -179,6 +214,7 @@ _object_add (Diagram   *dia,
   }
 }
 
+
 static void
 _object_remove (Diagram   *dia,
                 DiaLayer  *layer,
@@ -190,131 +226,122 @@ _object_remove (Diagram   *dia,
   }
 }
 
-/** Initializes a diagram with standard info and sets it to be called
- * 'filename'.
- * Returns TRUE if everything went ok, FALSE otherwise.
- * Will return FALSE if filename is not a legal string in the current
- * encoding.
- */
-static gboolean
-diagram_init(Diagram *dia, const char *filename)
+
+static void
+dia_diagram_init (Diagram *self)
 {
-  gchar *newfilename = NULL;
-  GError *error = NULL;
-
-  dia->data = &dia->parent_instance; /* compatibility */
-
-  dia->pagebreak_color = prefs.new_diagram.pagebreak_color;
-
-  get_paper_info (&dia->data->paper, -1, &prefs.new_diagram);
-
-  dia->grid.width_x = prefs.grid.x;
-  dia->grid.width_y = prefs.grid.y;
-  dia->grid.width_w = prefs.grid.w;
-  dia->grid.hex_size = 1.0;
-  dia->grid.colour = prefs.new_diagram.grid_color;
-  dia->grid.hex = prefs.grid.hex;
-  dia->grid.visible_x = prefs.grid.vis_x;
-  dia->grid.visible_y = prefs.grid.vis_y;
-  dia->grid.dynamic = prefs.grid.dynamic;
-  dia->grid.major_lines = prefs.grid.major_lines;
-
-  dia->guides.nhguides = 0;
-  dia->guides.hguides = NULL;
-  dia->guides.nvguides = 0;
-  dia->guides.vguides = NULL;
-
-  if (dia->filename != NULL)
-    g_free(dia->filename);
-  /* Make sure the filename is absolute */
-  if (!g_path_is_absolute(filename)) {
-    gchar *pwd = g_get_current_dir();
-
-    newfilename = g_build_filename(pwd, filename, NULL);
-    g_free(pwd);
-    filename = newfilename;
-  }
-  /* All Diagram functions assumes filename in filesystem encoding */
-
-  dia->filename = g_filename_to_utf8(filename, -1, NULL, NULL, &error);
-  if (error != NULL) {
-    message_error(_("Couldn't convert filename '%s' to UTF-8: %s\n"),
-                 dia_message_filename(filename), error->message);
-    g_error_free(error);
-    dia->filename = g_strdup(_("Error"));
-    return FALSE;
-  }
+  self->data = &self->parent_instance; /* compatibility */
+                                       /* Sure, but it's also silly ZB */
 
-  dia->unsaved = TRUE;
-  dia->mollified = FALSE;
-  dia->autosavefilename = NULL;
+  self->pagebreak_color = prefs.new_diagram.pagebreak_color;
 
-  if (dia->undo)
-    undo_destroy(dia->undo);
-  dia->undo = new_undo_stack(dia);
+  get_paper_info (&self->data->paper, -1, &prefs.new_diagram);
+
+  self->grid.width_x = prefs.grid.x;
+  self->grid.width_y = prefs.grid.y;
+  self->grid.width_w = prefs.grid.w;
+  self->grid.hex_size = 1.0;
+  self->grid.colour = prefs.new_diagram.grid_color;
+  self->grid.hex = prefs.grid.hex;
+  self->grid.visible_x = prefs.grid.vis_x;
+  self->grid.visible_y = prefs.grid.vis_y;
+  self->grid.dynamic = prefs.grid.dynamic;
+  self->grid.major_lines = prefs.grid.major_lines;
+
+  self->guides.nhguides = 0;
+  self->guides.hguides = NULL;
+  self->guides.nvguides = 0;
+  self->guides.vguides = NULL;
 
-  if (!g_list_find(open_diagrams, dia))
-    open_diagrams = g_list_prepend(open_diagrams, dia);
+  self->filename = NULL;
 
-  if (app_is_interactive())
-    layer_dialog_update_diagram_list();
+  self->unsaved = TRUE;
+  self->mollified = FALSE;
+  self->autosavefilename = NULL;
+
+  if (self->undo) {
+    undo_destroy (self->undo);
+  }
+  self->undo = new_undo_stack (self);
+
+  if (!g_list_find (open_diagrams, self)) {
+    open_diagrams = g_list_prepend (open_diagrams, self);
+  }
 
-  g_free(newfilename);
+  g_signal_connect (G_OBJECT (self), "object_add", G_CALLBACK (_object_add), self);
+  g_signal_connect (G_OBJECT (self), "object_remove", G_CALLBACK (_object_remove), self);
+}
 
-  g_signal_connect (G_OBJECT(dia), "object_add", G_CALLBACK(_object_add), dia);
-  g_signal_connect (G_OBJECT(dia), "object_remove", G_CALLBACK(_object_remove), dia);
 
-  return TRUE;
+GList *
+dia_open_diagrams (void)
+{
+  return open_diagrams;
 }
 
+
 int
-diagram_load_into(Diagram         *diagram,
-                 const char      *filename,
-                 DiaImportFilter *ifilter)
+diagram_load_into (Diagram         *diagram,
+                   const char      *filename,
+                   DiaImportFilter *ifilter)
 {
   /* ToDo: move context further up in the callstack and to sth useful with it's content */
-  DiaContext *ctx = dia_context_new(_("Load Into"));
+  DiaContext *ctx = dia_context_new (_("Load Into"));
 
   gboolean was_default = diagram->is_default;
-  if (!ifilter)
-    ifilter = filter_guess_import_filter(filename);
+  if (!ifilter) {
+    ifilter = filter_guess_import_filter (filename);
+  }
+
   /* slightly hacked to avoid 'Not a Dia File' for .shape */
-  if (!ifilter && g_str_has_suffix (filename, ".shape"))
+  if (!ifilter && g_str_has_suffix (filename, ".shape")) {
     ifilter = filter_import_get_by_name ("dia-svg");
-  if (!ifilter)  /* default to native format */
+  }
+
+  if (!ifilter) {
+    /* default to native format */
     ifilter = &dia_import_filter;
+  }
 
   dia_context_set_filename (ctx, filename);
-  if (ifilter->import_func(filename, diagram->data, ctx, ifilter->user_data)) {
+  if (ifilter->import_func (filename, diagram->data, ctx, ifilter->user_data)) {
     if (ifilter != &dia_import_filter) {
       /* When loading non-Dia files, change filename to reflect that saving
        * will produce a Dia file. See bug #440093 */
       if (strcmp (diagram->filename, filename) == 0) {
-       /* not a real load into but initial load */
-       gchar *old_filename = g_strdup (diagram->filename);
-        gchar *suffix_offset = g_utf8_strrchr(old_filename, -1, (gunichar)'.');
+        /* not a real load into but initial load */
+        gchar *old_filename = g_strdup (diagram->filename);
+        gchar *suffix_offset = g_utf8_strrchr (old_filename, -1, (gunichar) '.');
         gchar *new_filename;
+        GFile *file;
+
         if (suffix_offset != NULL) {
-         new_filename = g_strndup(old_filename, suffix_offset - old_filename);
-         g_free(old_filename);
-       } else {
-         new_filename = old_filename;
-       }
-        old_filename = g_strconcat(new_filename, ".dia", NULL);
-        g_free(new_filename);
-        diagram_set_filename(diagram, old_filename);
-        g_free(old_filename);
+          new_filename = g_strndup (old_filename, suffix_offset - old_filename);
+          g_free (old_filename);
+        } else {
+          new_filename = old_filename;
+        }
+        old_filename = g_strconcat (new_filename, ".dia", NULL);
+        g_free (new_filename);
+
+        file = g_file_new_for_path (old_filename);
+        dia_diagram_set_file (diagram, file);
+
+        g_free (old_filename);
+
         diagram->unsaved = TRUE;
-       diagram_update_for_filename (diagram);
-       diagram_modified(diagram);
+
+        diagram_modified (diagram);
       }
     } else {
       /* the initial diagram should have confirmed filename  */
       diagram->unsaved =
-         strcmp(filename, diagram->filename) == 0 ? FALSE : was_default;
+        strcmp (filename, diagram->filename) == 0 ? FALSE : was_default;
     }
-    diagram_set_modified(diagram, TRUE);
-    dia_context_release(ctx);
+
+    diagram_set_modified (diagram, TRUE);
+    dia_context_release (ctx);
+
     return TRUE;
   } else {
     dia_context_release(ctx);
@@ -340,51 +367,58 @@ diagram_load(const char *filename, DiaImportFilter *ifilter)
 
   /* TODO: Make diagram not be initialized twice */
   if (diagram == NULL) {
-    diagram = new_diagram(filename);
+    GFile *file = g_file_new_for_path (filename);
+
+    diagram = dia_diagram_new (file);
+
+    g_clear_object (&file);
   }
+
   if (diagram == NULL) return NULL;
 
-  if (   !diagram_init(diagram, filename)
-      || !diagram_load_into (diagram, filename, ifilter)) {
+  if (!diagram_load_into (diagram, filename, ifilter)) {
     if (!was_default) /* don't kill the default diagram on import failure */
       diagram_destroy(diagram);
     diagram = NULL;
   } else {
     /* not modifying 'diagram->unsaved' the state depends on the import filter used */
-    diagram_set_modified(diagram, FALSE);
-    if (app_is_interactive()) {
-      recent_file_history_add(filename);
-      if (was_default) /* replacing it is like first remove than add */
-        dia_diagram_remove(diagram);
-      dia_diagram_add(diagram);
+    diagram_set_modified (diagram, FALSE);
+    if (app_is_interactive ()) {
+      recent_file_history_add (filename);
+      if (was_default) {
+        dia_application_diagram_remove (dia_application_get_default (),
+                                        diagram);
+        dia_application_diagram_add (dia_application_get_default (),
+                                     diagram);
+      }
     }
   }
 
   if (diagram != NULL && was_default && app_is_interactive()) {
-    diagram_update_for_filename(diagram);
     diagram->is_default = FALSE;
-    if ( g_slist_length(diagram->displays) == 1 )
+
+    if (g_slist_length(diagram->displays) == 1) {
       display_set_active (diagram->displays->data);
+    }
   }
 
   return diagram;
 }
 
-/** Create a new diagram with the given filename.
- * If the diagram could not be created, e.g. because the filename is not
- * a legal string in the current encoding, return NULL.
+/**
+ * dia_diagram_new:
+ * @file: the #GFile backing this diagram
+ *
+ * Create a new diagram with the given file.
  */
 Diagram *
-new_diagram(const char *filename)  /* Note: filename is copied */
+dia_diagram_new (GFile *file)
 {
-  Diagram *dia = g_object_new(DIA_TYPE_DIAGRAM, NULL);
+  Diagram *dia = g_object_new (DIA_TYPE_DIAGRAM,
+                               "file", file,
+                               NULL);
 
-  if (diagram_init(dia, filename)) {
-    return dia;
-  } else {
-    g_object_unref(dia);
-    return NULL;
-  }
+  return dia;
 }
 
 void
@@ -660,18 +694,29 @@ diagram_update_menu_sensitivity (Diagram *dia)
 
 
 void
-diagram_add_ddisplay(Diagram *dia, DDisplay *ddisp)
+diagram_add_ddisplay (Diagram *dia, DDisplay *ddisp)
 {
-  dia->displays = g_slist_prepend(dia->displays, ddisp);
+  if (dia->displays == NULL) {
+    // If the diagram wasn't already open in the UI
+    dia_application_diagram_add (dia_application_get_default (),
+                                ddisp->diagram);
+  }
+
+  dia->displays = g_slist_prepend (dia->displays, ddisp);
 }
 
 void
-diagram_remove_ddisplay(Diagram *dia, DDisplay *ddisp)
+diagram_remove_ddisplay (Diagram *dia, DDisplay *ddisp)
 {
   dia->displays = g_slist_remove(dia->displays, ddisp);
 
-  if (g_slist_length(dia->displays) == 0)
-    diagram_destroy(dia);
+  if (g_slist_length (dia->displays) == 0) {
+    // Remove the diagram from the UI
+    dia_application_diagram_remove (dia_application_get_default (),
+                                    ddisp->diagram);
+
+    diagram_destroy (dia);
+  }
 }
 
 void
@@ -1472,45 +1517,6 @@ diagram_place_down_selected (Diagram *dia)
   undo_set_transactionpoint(dia->undo);
 }
 
-void
-diagram_set_filename(Diagram *dia, const char *filename)
-{
-  g_free(dia->filename);
-  dia->filename = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
-
-  diagram_update_for_filename(dia);
-}
-
-/** Update the various areas that require updating when changing filename
- * This will ensure that all places that use the filename are updated:
- * Window titles, layer dialog, recent files, diagram tree.
- * @param dia The diagram whose filename has changed.
- */
-static void
-diagram_update_for_filename(Diagram *dia)
-{
-  GSList *l;
-  DDisplay *ddisp;
-  char *title;
-
-  title = diagram_get_name(dia);
-
-  l = dia->displays;
-  while (l!=NULL) {
-    ddisp = (DDisplay *) l->data;
-
-    ddisplay_set_title(ddisp, title);
-
-    l = g_slist_next(l);
-  }
-
-  g_free(title);
-
-  layer_dialog_update_diagram_list();
-
-  /* signal about the change */
-  dia_diagram_change (dia, DIAGRAM_CHANGE_NAME, NULL);
-}
 
 /** Returns a string with a 'sensible' (human-readable) name for the
  * diagram.  The string should be freed after use.
@@ -1544,5 +1550,64 @@ void
 diagram_object_modified(Diagram *dia, DiaObject *object)
 {
   /* signal about the change */
-  dia_diagram_change (dia, DIAGRAM_CHANGE_OBJECT, object);
+  dia_application_diagram_change (dia_application_get_default (),
+                                  dia,
+                                  DIAGRAM_CHANGE_OBJECT,
+                                  object);
+}
+
+void
+dia_diagram_set_file (Diagram *self,
+                      GFile   *file)
+{
+  DiagramPrivate *priv;
+  GSList *l;
+  DDisplay *ddisp;
+  char *title;
+
+  g_return_if_fail (DIA_IS_DIAGRAM (self));
+  g_return_if_fail (file && G_IS_FILE (file));
+
+  priv = dia_diagram_get_instance_private (self);
+
+  if (priv->file == file) {
+    return;
+  }
+
+  g_clear_object (&priv->file);
+  priv->file = g_object_ref (file);
+
+  g_clear_pointer (&self->filename, g_free);
+  self->filename = g_file_get_path (file);
+
+  title = diagram_get_name (self);
+
+  l = self->displays;
+  while (l != NULL) {
+    ddisp = (DDisplay *) l->data;
+
+    ddisplay_set_title (ddisp, title);
+
+    l = g_slist_next (l);
+  }
+
+  g_free (title);
+
+  /* signal about the change */
+  dia_application_diagram_change (dia_application_get_default (),
+                                  self,
+                                  DIAGRAM_CHANGE_NAME,
+                                  NULL);
+
+  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_FILE]);
+}
+
+GFile *
+dia_diagram_get_file (Diagram *self)
+{
+  DiagramPrivate *priv;
+
+  priv = dia_diagram_get_instance_private (self);
+
+  return priv->file;
 }
diff --git a/app/diagram.h b/app/diagram.h
index 9e679708..e2546f3b 100644
--- a/app/diagram.h
+++ b/app/diagram.h
@@ -29,9 +29,9 @@ typedef struct _Diagram Diagram;
 
 G_BEGIN_DECLS
 
-GType diagram_get_type (void) G_GNUC_CONST;
+GType dia_diagram_get_type (void) G_GNUC_CONST;
 
-#define DIA_TYPE_DIAGRAM           (diagram_get_type ())
+#define DIA_TYPE_DIAGRAM           (dia_diagram_get_type ())
 #define DIA_DIAGRAM(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), DIA_TYPE_DIAGRAM, Diagram))
 #define DIA_DIAGRAM_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), DIA_TYPE_DIAGRAM, DiagramClass))
 #define DIA_IS_DIAGRAM(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DIA_TYPE_DIAGRAM))
@@ -46,7 +46,7 @@ struct _Diagram {
   int mollified;
   gboolean autosaved;     /* True if the diagram is autosaved since last mod */
   char *autosavefilename;     /* Holds the name of the current autosave file
-                              * for this diagram, or NULL.  */
+                               * for this diagram, or NULL.  */
 
   Color pagebreak_color; /*!< just to show page breaks */
   DiaGrid     grid;      /*!< the display grid */
@@ -77,7 +77,6 @@ GList *dia_open_diagrams(void); /* Read only! */
 
 Diagram *diagram_load(const char *filename, DiaImportFilter *ifilter);
 int diagram_load_into (Diagram *dest, const char *filename, DiaImportFilter *ifilter);
-Diagram *new_diagram(const char *filename); /*Note: filename is copied*/
 void diagram_destroy(Diagram *dia);
 gboolean diagram_is_modified(Diagram *dia);
 void diagram_modified(Diagram *dia);
@@ -129,7 +128,6 @@ void diagram_unparent_selected(Diagram *dia);
 void diagram_unparent_children_selected(Diagram *dia);
 
 gboolean object_within_parent(DiaObject *obj, DiaObject *parent);
-void diagram_set_filename(Diagram *dia, const char *filename);
 gchar *diagram_get_name(Diagram *dia);
 
 int diagram_modified_exists(void);
@@ -138,6 +136,11 @@ void diagram_redraw_all(void);
 
 void diagram_object_modified(Diagram *dia, DiaObject *object);
 
+Diagram *dia_diagram_new      (GFile   *file);
+void     dia_diagram_set_file (Diagram *self,
+                               GFile   *file);
+GFile   *dia_diagram_get_file (Diagram *self);
+
 G_END_DECLS
 
 #endif /* DIAGRAM_H */
diff --git a/app/diagram_tree_model.c b/app/diagram_tree_model.c
index b2f19b79..25aa63d4 100644
--- a/app/diagram_tree_model.c
+++ b/app/diagram_tree_model.c
@@ -546,11 +546,11 @@ static void
 _dtm_init (DiagramTreeModel *dtm)
 {
   /* connect to intersting state changes */
-  g_signal_connect (G_OBJECT (dia_application_get ()),
+  g_signal_connect (G_OBJECT (dia_application_get_default ()),
                     "diagram_add", G_CALLBACK (_diagram_add), dtm);
-  g_signal_connect (G_OBJECT (dia_application_get ()),
+  g_signal_connect (G_OBJECT (dia_application_get_default ()),
                     "diagram_change", G_CALLBACK (_diagram_change), dtm);
-  g_signal_connect (G_OBJECT(dia_application_get ()),
+  g_signal_connect (G_OBJECT(dia_application_get_default ()),
                     "diagram_remove", G_CALLBACK (_diagram_remove), dtm);
   /* also connect to every already existing diagram */
   {
@@ -568,9 +568,9 @@ _dtm_finalize (GObject *object)
 {
   DiagramTreeModel *dtm = (DiagramTreeModel *)object;
 
-  g_signal_handlers_disconnect_by_func (G_OBJECT (dia_application_get ()), _diagram_add, dtm);
-  g_signal_handlers_disconnect_by_func (G_OBJECT (dia_application_get ()), _diagram_change, dtm);
-  g_signal_handlers_disconnect_by_func (G_OBJECT (dia_application_get ()), _diagram_remove, dtm);
+  g_signal_handlers_disconnect_by_func (G_OBJECT (dia_application_get_default ()), _diagram_add, dtm);
+  g_signal_handlers_disconnect_by_func (G_OBJECT (dia_application_get_default ()), _diagram_change, dtm);
+  g_signal_handlers_disconnect_by_func (G_OBJECT (dia_application_get_default ()), _diagram_remove, dtm);
 
   G_OBJECT_CLASS(_dtm_parent_class)->finalize (object);
 }
diff --git a/app/display.c b/app/display.c
index 6d05efde..cbed7681 100644
--- a/app/display.c
+++ b/app/display.c
@@ -54,35 +54,26 @@ GdkCursor *default_cursor = NULL;
 
 static DDisplay *active_display = NULL;
 
-
-typedef struct _IRectangle {
-  int top, bottom;
-  int left,right;
-} IRectangle;
-
 static void
-update_zoom_status(DDisplay *ddisp)
+update_zoom_status (DDisplay *ddisp)
 {
   gchar* zoom_text;
 
-  if (is_integrated_ui ())
-  {
-    zoom_text = g_strdup_printf("%.0f%%",
-          ddisp->zoom_factor * 100.0 / DDISPLAY_NORMAL_ZOOM);
+  if (is_integrated_ui ()) {
+    zoom_text = g_strdup_printf ("%.0f%%",
+                                 ddisp->zoom_factor * 100.0 / DDISPLAY_NORMAL_ZOOM);
 
     integrated_ui_toolbar_set_zoom_text (ddisp->common_toolbar, zoom_text);
-  }
-  else
-  {
+  } else {
     GtkWidget *zoomcombo;
-    zoom_text = g_strdup_printf("%.1f%%",
-            ddisp->zoom_factor * 100.0 / DDISPLAY_NORMAL_ZOOM);
+    zoom_text = g_strdup_printf ("%.1f%%",
+                                 ddisp->zoom_factor * 100.0 / DDISPLAY_NORMAL_ZOOM);
     zoomcombo = ddisp->zoom_status;
-    gtk_entry_set_text(GTK_ENTRY (g_object_get_data (G_OBJECT(zoomcombo), "user_data")),
-                      zoom_text);
+    gtk_entry_set_text (GTK_ENTRY (g_object_get_data (G_OBJECT(zoomcombo), "user_data")),
+                        zoom_text);
   }
 
-  g_free(zoom_text); /* Copied by gtk_entry_set_text */
+  g_free (zoom_text); /* Copied by gtk_entry_set_text */
 }
 
 static void
@@ -223,11 +214,10 @@ new_display(Diagram *dia)
   DiaRectangle visible;
   int preset;
 
-  ddisp = g_new0(DDisplay,1);
+  ddisp = g_new0 (DDisplay,1);
 
-  ddisp->diagram = dia;
   /* Every display has it's own reference */
-  g_object_ref(dia);
+  ddisp->diagram = g_object_ref (dia);
 
   ddisp->grid.visible = prefs.grid.visible;
   preset = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(dia), "show-grid"));
@@ -258,7 +248,7 @@ new_display(Diagram *dia)
 
   ddisp->clicked_position.x = ddisp->clicked_position.y = 0.0;
 
-  diagram_add_ddisplay(dia, ddisp);
+  diagram_add_ddisplay (dia, ddisp);
   g_signal_connect (dia, "selection_changed", G_CALLBACK(selection_changed), ddisp);
   ddisp->origo.x = 0.0;
   ddisp->origo.y = 0.0;
@@ -1102,7 +1092,7 @@ are_you_sure_close_dialog_respond(GtkWidget *widget, /* the dialog */
 }
 
 void
-ddisplay_close(DDisplay *ddisp)
+ddisplay_close (DDisplay *ddisp)
 {
   Diagram *dia;
   GtkWidget *dialog, *button;
@@ -1213,14 +1203,12 @@ ddisplay_really_destroy(DDisplay *ddisp)
     display_set_active(NULL);
 
   if (ddisp->diagram) {
-    diagram_remove_ddisplay(ddisp->diagram, ddisp);
+    diagram_remove_ddisplay (ddisp->diagram, ddisp);
     /* if we are the last user of the diagram it will be unref'ed */
-    g_object_unref(ddisp->diagram);
-    ddisp->diagram = NULL;
+    g_clear_object (&ddisp->diagram);
   }
 
-  g_object_unref (ddisp->renderer);
-  ddisp->renderer = NULL;
+  g_clear_object (&ddisp->renderer);
 
   /* Free update_areas list: */
   ddisplay_free_update_areas(ddisp);
diff --git a/app/filedlg.c b/app/filedlg.c
index 3fbd9fec..0c6fb8af 100644
--- a/app/filedlg.c
+++ b/app/filedlg.c
@@ -407,11 +407,17 @@ file_save_as_response_callback(GtkWidget *fs,
 
     {
       DiaContext *ctx = dia_context_new (_("Save as"));
-      diagram_set_filename(dia, filename);
+      GFile *file = g_file_new_for_path (filename);
+
+      dia_diagram_set_file (dia, file);
       dia_context_set_filename (ctx, filename);
-      if (diagram_save(dia, filename, ctx))
-       recent_file_history_add(filename);
+
+      if (diagram_save (dia, filename, ctx)) {
+        recent_file_history_add (filename);
+      }
+
       dia_context_release (ctx);
+      g_clear_object (&file);
     }
     g_free (filename);
   }
diff --git a/app/layer_dialog.c b/app/layer_dialog.c
index a105f9d2..5ef10fbd 100644
--- a/app/layer_dialog.c
+++ b/app/layer_dialog.c
@@ -88,9 +88,18 @@ struct _DiaLayerWidgetClass
 
 GType dia_layer_widget_get_type(void);
 
+enum {
+  COL_FILENAME,
+  COL_DIAGRAM
+};
+
 struct LayerDialog {
   GtkWidget *dialog;
-  GtkWidget *diagram_omenu;
+
+  GtkListStore *diagrams_store;
+  GtkWidget    *diagrams_combo;
+
+  gboolean setting_active;
 
   GtkWidget *layer_list;
 
@@ -102,7 +111,7 @@ static struct LayerDialog *layer_dialog = NULL;
 typedef struct _ButtonData ButtonData;
 
 struct _ButtonData {
-  gchar *stock_name;
+  gchar *icon_name;
   gpointer callback;
   char *tooltip;
 };
@@ -160,62 +169,41 @@ static void layer_dialog_delete_callback(GtkWidget *widget, gpointer gdata);
 static void layer_dialog_edit_layer(DiaLayerWidget *layer_widget, Diagram *dia, DiaLayer *layer);
 
 static ButtonData buttons[] = {
-  { GTK_STOCK_ADD, layer_dialog_new_callback, N_("New Layer") },
-  { GTK_STOCK_EDIT, layer_dialog_rename_callback, N_("Rename Layer") },
-  { GTK_STOCK_GO_UP, layer_dialog_raise_callback, N_("Raise Layer") },
-  { GTK_STOCK_GO_DOWN, layer_dialog_lower_callback, N_("Lower Layer") },
-  { GTK_STOCK_DELETE, layer_dialog_delete_callback, N_("Delete Layer") },
+  { "list-add", layer_dialog_new_callback, N_("New Layer") },
+  { "list-remove", layer_dialog_delete_callback, N_("Delete Layer") },
+  { "document-properties", layer_dialog_rename_callback, N_("Rename Layer") },
+  { "go-up", layer_dialog_raise_callback, N_("Raise Layer") },
+  { "go-down", layer_dialog_lower_callback, N_("Lower Layer") },
 };
 
-enum {
-  BUTTON_NEW = 0,
-  BUTTON_RAISE,
-  BUTTON_LOWER,
-  BUTTON_DELETE
-};
-
-#define BUTTON_EVENT_MASK  GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | \
-                           GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-
 static int num_buttons = sizeof(buttons)/sizeof(ButtonData);
 
-#define NORMAL 0
-#define SELECTED 1
-#define INSENSITIVE 2
-
 static GtkWidget *
-create_button_box(GtkWidget *parent, gboolean show_labels)
+create_button_box (GtkWidget *parent)
 {
   GtkWidget *button;
   GtkWidget *button_box;
   int i;
 
-  button_box = gtk_hbox_new (TRUE, 1);
+  button_box = gtk_hbox_new (FALSE, 0);
 
-  for (i=0;i<num_buttons;i++) {
-    if (show_labels == TRUE)
-    {
-    button = gtk_button_new_from_stock(buttons[i].stock_name);
-    }
-    else
-    {
-      GtkWidget * image;
+  for (i = 0; i < num_buttons; i++) {
+    GtkWidget * image;
 
-      button = gtk_button_new ();
+    button = gtk_button_new ();
 
-      image = gtk_image_new_from_stock (buttons[i].stock_name,
-                                        GTK_ICON_SIZE_BUTTON);
+    image = gtk_image_new_from_icon_name (buttons[i].icon_name,
+                                          GTK_ICON_SIZE_BUTTON);
 
-      gtk_button_set_image (GTK_BUTTON (button), image);
-    }
+    gtk_button_set_image (GTK_BUTTON (button), image);
 
     g_signal_connect_swapped (G_OBJECT (button), "clicked",
-                             G_CALLBACK(buttons[i].callback),
-                             G_OBJECT (parent));
+                              G_CALLBACK (buttons[i].callback),
+                              G_OBJECT (parent));
 
     gtk_widget_set_tooltip_text (button, gettext(buttons[i].tooltip));
 
-    gtk_box_pack_start (GTK_BOX(button_box), button, TRUE, TRUE, 0);
+    gtk_box_pack_start (GTK_BOX (button_box), button, TRUE, TRUE, 0);
 
     gtk_widget_show (button);
   }
@@ -286,16 +274,20 @@ GtkWidget * create_layer_view_widget (void)
   GtkRcStyle *rcstyle;    /* For hide_button */
   GtkWidget  *image;      /* For hide_button */
   GtkWidget  *list;
-  GtkWidget  *separator;
   GtkWidget  *scrolled_win;
   GtkWidget  *button_box;
 
   /* if layer_dialog were renamed to layer_view_data this would make
    * more sense.
    */
-  layer_dialog = g_new (struct LayerDialog, 1);
+  layer_dialog = g_new0 (struct LayerDialog, 1);
 
   layer_dialog->diagram = NULL;
+  /* Not used in integrated UI */
+  layer_dialog->diagrams_store = gtk_list_store_new (2,
+                                                     G_TYPE_STRING,
+                                                     DIA_TYPE_DIAGRAM);
+  layer_dialog->diagrams_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL 
(layer_dialog->diagrams_store));
 
   layer_dialog->dialog = vbox = gtk_vbox_new (FALSE, 1);
 
@@ -305,8 +297,6 @@ GtkWidget * create_layer_view_widget (void)
   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2);
   gtk_widget_show (label);
 
-  layer_dialog->diagram_omenu = NULL;
-
   /* Hide Button */
   hide_button = gtk_button_new ();
   gtk_button_set_relief (GTK_BUTTON (hide_button), GTK_RELIEF_NONE);
@@ -325,24 +315,17 @@ GtkWidget * create_layer_view_widget (void)
   g_signal_connect (G_OBJECT (hide_button), "clicked",
                     G_CALLBACK (layer_view_hide_button_clicked), NULL);
 
-  gtk_box_pack_start (GTK_BOX (hbox), hide_button, FALSE, FALSE, 2);
+  gtk_box_pack_end (GTK_BOX (hbox), hide_button, FALSE, FALSE, 2);
 
   gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
   gtk_widget_show_all (hbox);
 
-  button_box = create_button_box(vbox, FALSE);
-
-  gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 2);
-  gtk_widget_show (button_box);
-
-  separator = gtk_hseparator_new();
-  gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 2);
-  gtk_widget_show (separator);
-
   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
+                                       GTK_SHADOW_ETCHED_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 (vbox), scrolled_win, TRUE, TRUE, 2);
 
   layer_dialog->layer_list = list = gtk_list_new();
@@ -357,27 +340,132 @@ GtkWidget * create_layer_view_widget (void)
   g_signal_connect (G_OBJECT (list), "event",
                    G_CALLBACK (layer_list_events), NULL);
 
+  button_box = create_button_box(vbox);
+  gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 2);
+  gtk_widget_show (button_box);
+
   return vbox;
 }
 
+
+static void
+diagrams_changed (GListModel *diagrams,
+                  guint       position,
+                  guint       removed,
+                  guint       added,
+                  gpointer    user_data)
+{
+  Diagram *dia;
+  int i;
+  int current_nr;
+  GtkTreeIter iter;
+  char *basename = NULL;
+
+  if (layer_dialog == NULL || layer_dialog->dialog == NULL) {
+    if (g_list_model_get_n_items (diagrams) < 1)
+      return; /* shortcut; maybe session end w/o this dialog */
+    else
+      layer_dialog_create ();
+  }
+  g_assert (layer_dialog != NULL); /* must be valid now */
+
+  if (layer_dialog->diagrams_store == NULL) {
+    return;
+  }
+
+  current_nr = -1;
+
+  gtk_list_store_clear (layer_dialog->diagrams_store);
+
+  if (g_list_model_get_n_items (diagrams) < 1) {
+    gtk_widget_set_sensitive (layer_dialog->dialog, FALSE);
+
+    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (layer_dialog->diagrams_combo),
+                                   NULL);
+
+    return;
+  }
+
+  gtk_widget_set_sensitive (layer_dialog->dialog, TRUE);
+
+  i = 0;
+  while ((dia = DIA_DIAGRAM (g_list_model_get_item (diagrams, i)))) {
+    basename = g_path_get_basename (dia->filename);
+
+    gtk_list_store_append (layer_dialog->diagrams_store, &iter);
+    gtk_list_store_set (layer_dialog->diagrams_store,
+                        &iter,
+                        COL_FILENAME,
+                        basename,
+                        COL_DIAGRAM,
+                        dia,
+                        -1);
+
+    if (dia == layer_dialog->diagram) {
+      current_nr = i;
+      gtk_combo_box_set_active_iter (GTK_COMBO_BOX (layer_dialog->diagrams_combo),
+                                     &iter);
+    }
+
+    i++;
+
+    g_free (basename);
+    g_clear_object (&dia);
+  }
+
+  if (current_nr == -1) {
+    dia = NULL;
+    if (g_list_model_get_n_items (diagrams) > 0) {
+      dia = g_list_model_get_item (diagrams, i);
+    }
+
+    layer_dialog_set_diagram (dia);
+
+    g_clear_object (&dia);
+  }
+}
+
+
+static void
+diagram_changed (GtkComboBox *widget,
+                 gpointer     data)
+{
+  GtkTreeIter iter;
+  Diagram *diagram = NULL;
+
+  if (layer_dialog->setting_active) {
+    return;
+  }
+
+  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (layer_dialog->diagrams_combo),
+                                     &iter)) {
+    gtk_tree_model_get (GTK_TREE_MODEL (layer_dialog->diagrams_store),
+                        &iter,
+                        COL_DIAGRAM,
+                        &diagram,
+                        -1);
+  }
+
+  layer_dialog_set_diagram (diagram);
+}
+
+
 void
-layer_dialog_create(void)
+layer_dialog_create (void)
 {
   GtkWidget *dialog;
   GtkWidget *vbox;
   GtkWidget *hbox;
-  GtkWidget *label;
-  GtkWidget *omenu;
-  GtkWidget *menu;
   GtkWidget *list;
-  GtkWidget *separator;
   GtkWidget *scrolled_win;
   GtkWidget *button_box;
   GtkWidget *button;
+  GtkCellRenderer *renderer;
 
-  layer_dialog = g_new(struct LayerDialog, 1);
+  layer_dialog = g_new0(struct LayerDialog, 1);
 
   layer_dialog->diagram = NULL;
+  layer_dialog->diagrams_store = NULL;
 
   layer_dialog->dialog = dialog = gtk_dialog_new ();
   gtk_window_set_title (GTK_WINDOW (dialog), _("Layers"));
@@ -394,28 +482,43 @@ layer_dialog_create(void)
 
   hbox = gtk_hbox_new(FALSE, 1);
 
-  label = gtk_label_new(_("Diagram:"));
-  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
-  gtk_widget_show (label);
+  layer_dialog->diagrams_store = gtk_list_store_new (2,
+                                                     G_TYPE_STRING,
+                                                     DIA_TYPE_DIAGRAM);
+  layer_dialog->diagrams_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL 
(layer_dialog->diagrams_store));
 
-  layer_dialog->diagram_omenu = omenu = gtk_option_menu_new();
-  gtk_box_pack_start(GTK_BOX(hbox), omenu, TRUE, TRUE, 2);
-  gtk_widget_show (omenu);
+  g_signal_connect (dia_application_get_diagrams (dia_application_get_default ()),
+                    "items-changed",
+                    G_CALLBACK (diagrams_changed),
+                    NULL);
 
-  menu = gtk_menu_new();
-  gtk_option_menu_set_menu(GTK_OPTION_MENU(omenu), menu);
+  g_signal_connect (layer_dialog->diagrams_combo,
+                    "changed",
+                    G_CALLBACK (diagram_changed),
+                    NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (layer_dialog->diagrams_combo),
+                              renderer,
+                              TRUE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (layer_dialog->diagrams_combo),
+                                  renderer,
+                                  "text", COL_FILENAME,
+                                  NULL);
+
+
+  gtk_box_pack_start (GTK_BOX (hbox), layer_dialog->diagrams_combo, TRUE, TRUE, 2);
+  gtk_widget_show (layer_dialog->diagrams_combo);
 
   gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
   gtk_widget_show (hbox);
 
-  separator = gtk_hseparator_new();
-  gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 2);
-  gtk_widget_show (separator);
-
   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
+                                       GTK_SHADOW_ETCHED_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 (vbox), scrolled_win, TRUE, TRUE, 2);
 
   layer_dialog->layer_list = list = gtk_list_new();
@@ -430,7 +533,7 @@ layer_dialog_create(void)
   g_signal_connect (G_OBJECT (list), "event",
                    G_CALLBACK (layer_list_events), NULL);
 
-  button_box = create_button_box(dialog, TRUE);
+  button_box = create_button_box(dialog);
 
   gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 2);
   gtk_widget_show (button_box);
@@ -448,9 +551,7 @@ layer_dialog_create(void)
 
   gtk_widget_show (button);
 
-  persistence_register_window(GTK_WINDOW(dialog));
-
-  layer_dialog_update_diagram_list();
+  persistence_register_window (GTK_WINDOW (dialog));
 }
 
 static void
@@ -538,12 +639,18 @@ layer_dialog_new_callback(GtkWidget *widget, gpointer gdata)
 }
 
 static void
-layer_dialog_rename_callback(GtkWidget *widget, gpointer gdata)
+layer_dialog_rename_callback (GtkWidget *widget, gpointer gdata)
 {
   GtkWidget *selected;
   Diagram *dia;
   DiaLayer *layer;
+
   dia = layer_dialog->diagram;
+
+  if (dia == NULL) {
+    return;
+  }
+
   selected = GTK_LIST(layer_dialog->layer_list)->selection->data;
   layer = dia->data->active_layer;
   layer_dialog_edit_layer (DIA_LAYER_WIDGET (selected), dia, layer);
@@ -673,95 +780,6 @@ layer_dialog_lower_callback(GtkWidget *widget, gpointer gdata)
   }
 }
 
-
-static void
-layer_dialog_select_diagram_callback(GtkWidget *widget, gpointer gdata)
-{
-  Diagram *dia = (Diagram *) gdata;
-
-  layer_dialog_set_diagram(dia);
-}
-
-void
-layer_dialog_update_diagram_list(void)
-{
-  GtkWidget *new_menu;
-  GtkWidget *menu_item;
-  GList *dia_list;
-  Diagram *dia;
-  char *filename;
-  int i;
-  int current_nr;
-
-  if (layer_dialog == NULL || layer_dialog->dialog == NULL) {
-    if (!dia_open_diagrams())
-      return; /* shortcut; maybe session end w/o this dialog */
-    else
-      layer_dialog_create();
-  }
-  g_assert(layer_dialog != NULL); /* must be valid now */
-  /* oh this options: here integrated UI ;( */
-  if (!layer_dialog->diagram_omenu)
-    return;
-
-  new_menu = gtk_menu_new();
-
-  current_nr = -1;
-
-  i = 0;
-  dia_list = dia_open_diagrams();
-  while (dia_list != NULL) {
-    dia = (Diagram *) dia_list->data;
-
-    if (dia == layer_dialog->diagram) {
-      current_nr = i;
-    }
-
-    filename = strrchr(dia->filename, G_DIR_SEPARATOR);
-    if (filename==NULL) {
-      filename = dia->filename;
-    } else {
-      filename++;
-    }
-
-    menu_item = gtk_menu_item_new_with_label(filename);
-
-    g_signal_connect (G_OBJECT (menu_item), "activate",
-                     G_CALLBACK (layer_dialog_select_diagram_callback), dia);
-
-    gtk_menu_append( GTK_MENU(new_menu), menu_item);
-    gtk_widget_show (menu_item);
-
-    dia_list = g_list_next(dia_list);
-    i++;
-  }
-
-  if (dia_open_diagrams()==NULL) {
-    menu_item = gtk_menu_item_new_with_label (_("none"));
-    g_signal_connect (G_OBJECT (menu_item), "activate",
-                     G_CALLBACK (layer_dialog_select_diagram_callback), NULL);
-    gtk_menu_append( GTK_MENU(new_menu), menu_item);
-    gtk_widget_show (menu_item);
-  }
-
-  gtk_option_menu_remove_menu(GTK_OPTION_MENU(layer_dialog->diagram_omenu));
-
-  gtk_option_menu_set_menu(GTK_OPTION_MENU(layer_dialog->diagram_omenu),
-                          new_menu);
-
-  gtk_option_menu_set_history(GTK_OPTION_MENU(layer_dialog->diagram_omenu),
-                             current_nr);
-  gtk_menu_set_active(GTK_MENU(new_menu), current_nr);
-
-  if (current_nr == -1) {
-    dia = NULL;
-    if (dia_open_diagrams()!=NULL) {
-      dia = (Diagram *) dia_open_diagrams()->data;
-    }
-    layer_dialog_set_diagram(dia);
-  }
-}
-
 void
 layer_dialog_show()
 {
@@ -787,8 +805,32 @@ _layer_widget_clear_layer (GtkWidget *widget, gpointer user_data)
   lw->layer = NULL;
 }
 
+gboolean
+find_diagram (GtkTreeModel *model,
+              GtkTreePath  *path,
+              GtkTreeIter  *iter,
+              gpointer      dia)
+{
+  Diagram *diagram = NULL;
+
+  gtk_tree_model_get (model, iter, COL_DIAGRAM, &diagram, -1);
+
+  if (diagram == dia) {
+    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (layer_dialog->diagrams_combo),
+                                   iter);
+
+    g_clear_object (&diagram);
+
+    return TRUE;
+  }
+
+  g_clear_object (&diagram);
+
+  return FALSE;
+}
+
 void
-layer_dialog_set_diagram(Diagram *dia)
+layer_dialog_set_diagram (Diagram *dia)
 {
   DiagramData *data;
   GtkWidget *layer_widget;
@@ -797,39 +839,51 @@ layer_dialog_set_diagram(Diagram *dia)
   int sel_pos;
   int i,j;
 
-  if (dia!=NULL)
+  if (dia != NULL)
     active_layer = dia->data->active_layer;
 
-  if (layer_dialog == NULL || layer_dialog->dialog == NULL)
-    layer_dialog_create(); /* May have been destroyed */
-  g_assert(layer_dialog != NULL); /* must be valid now */
+  if (layer_dialog == NULL || layer_dialog->dialog == NULL) {
+    layer_dialog_create (); /* May have been destroyed */
+  }
 
-  gtk_container_foreach (GTK_CONTAINER(layer_dialog->layer_list),
+  g_assert (layer_dialog != NULL); /* must be valid now */
+
+  gtk_container_foreach (GTK_CONTAINER (layer_dialog->layer_list),
                          _layer_widget_clear_layer, NULL);
-  gtk_list_clear_items(GTK_LIST(layer_dialog->layer_list), 0, -1);
+  gtk_list_clear_items (GTK_LIST (layer_dialog->layer_list), 0, -1);
   layer_dialog->diagram = dia;
-  if (dia != NULL) {
-    i = g_list_index(dia_open_diagrams(), dia);
-    if (i >= 0 && layer_dialog->diagram_omenu != NULL)
-      gtk_option_menu_set_history(GTK_OPTION_MENU(layer_dialog->diagram_omenu),
-                                 i);
+
+  if (dia == NULL) {
+    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (layer_dialog->diagrams_combo),
+                                   NULL);
+
+    return;
   }
 
-  if (dia != NULL) {
-    data = dia->data;
-
-    sel_pos = 0;
-    for (i=data->layers->len-1,j=0;i>=0;i--,j++) {
-      layer = (DiaLayer *) g_ptr_array_index(data->layers, i);
-      layer_widget = dia_layer_widget_new(dia, layer);
-      gtk_widget_show(layer_widget);
-      gtk_container_add(GTK_CONTAINER(layer_dialog->layer_list), layer_widget);
-      if (layer == active_layer) {
-        sel_pos = j;
-      }
+  layer_dialog->setting_active = TRUE;
+  gtk_tree_model_foreach (GTK_TREE_MODEL (layer_dialog->diagrams_store),
+                          find_diagram,
+                          dia);
+  layer_dialog->setting_active = FALSE;
+
+  data = dia->data;
+
+  sel_pos = 0;
+  for (i = data->layers->len - 1, j = 0; i >= 0; i--, j++) {
+    layer = DIA_LAYER (g_ptr_array_index (data->layers, i));
+
+    layer_widget = dia_layer_widget_new (dia, layer);
+    gtk_widget_show (layer_widget);
+
+    gtk_container_add (GTK_CONTAINER (layer_dialog->layer_list),
+                        layer_widget);
+
+    if (layer == active_layer) {
+      sel_pos = j;
     }
-    gtk_list_select_item(GTK_LIST(layer_dialog->layer_list), sel_pos);
   }
+
+  gtk_list_select_item (GTK_LIST (layer_dialog->layer_list), sel_pos);
 }
 
 
@@ -1123,7 +1177,10 @@ edit_layer_ok_callback (GtkWidget *w, gpointer client_data)
                 "name", gtk_entry_get_text (GTK_ENTRY (dialog->name_entry)),
                 NULL);
   /* reflect name change on listeners */
-  dia_diagram_change (dialog->layer_widget->dia, DIAGRAM_CHANGE_LAYER, layer);
+  dia_application_diagram_change (dia_application_get_default (),
+                                  dialog->layer_widget->dia,
+                                  DIAGRAM_CHANGE_LAYER,
+                                  layer);
 
   diagram_add_update_all (dialog->layer_widget->dia);
   diagram_flush (dialog->layer_widget->dia);
diff --git a/app/layer_dialog.h b/app/layer_dialog.h
index 30ed682e..0702cb8a 100644
--- a/app/layer_dialog.h
+++ b/app/layer_dialog.h
@@ -22,10 +22,9 @@
 #include "diagram.h"
 
 
-void layer_dialog_create(void);
-void layer_dialog_update_diagram_list(void);
-void layer_dialog_show(void);
-void layer_dialog_set_diagram(Diagram *dia);
+void layer_dialog_create      (void);
+void layer_dialog_show        (void);
+void layer_dialog_set_diagram (Diagram *dia);
 
 /* Integrated UI component */
 GtkWidget * create_layer_view_widget (void);
diff --git a/lib/layer.c b/lib/layer.c
index c5777cae..eaa32edb 100644
--- a/lib/layer.c
+++ b/lib/layer.c
@@ -42,6 +42,8 @@ struct _DiaLayerPrivate {
                                   to. The selected layer is by default
                                   connectable */
 
+  /* NOTE: THIS IS A _WEAK_ REF */
+  /* This avoids ref cycles with diagram */
   DiagramData *parent_diagram; /* Back-pointer to the diagram. This
                                   must only be set by functions internal
                                   to the diagram, and accessed via
@@ -80,7 +82,7 @@ dia_layer_finalize (GObject *object)
   g_clear_pointer (&priv->name, g_free);
   destroy_object_list (priv->objects);
 
-  g_clear_object (&priv->parent_diagram);
+  g_clear_weak_pointer (&priv->parent_diagram);
 
   G_OBJECT_CLASS (dia_layer_parent_class)->finalize (object);
 }
@@ -1032,8 +1034,8 @@ dia_layer_set_parent_diagram (DiaLayer    *layer,
 
   priv = dia_layer_get_instance_private (layer);
 
-  g_clear_object (&priv->parent_diagram);
-  priv->parent_diagram = g_object_ref (diagram);
+  g_clear_weak_pointer (&priv->parent_diagram);
+  g_set_weak_pointer (&priv->parent_diagram, diagram);
 
   g_object_notify_by_pspec (G_OBJECT (layer), pspecs[PROP_PARENT_DIAGRAM]);
 }
diff --git a/plug-ins/python/diamodule.c b/plug-ins/python/diamodule.c
index b431d291..a6373505 100644
--- a/plug-ins/python/diamodule.c
+++ b/plug-ins/python/diamodule.c
@@ -122,19 +122,22 @@ PyDia_Load(PyObject *self, PyObject *args)
 }
 
 static PyObject *
-PyDia_New(PyObject *self, PyObject *args)
+PyDia_New (PyObject *self, PyObject *args)
 {
-    Diagram *dia;
-    gchar *filename;
+  Diagram *dia;
+  gchar *filename;
 
-    if (!PyArg_ParseTuple(args, "s:dia.new", &filename))
-       return NULL;
-
-    dia = new_diagram(filename);
-    if (dia)
-       return PyDiaDiagram_New(dia);
-    PyErr_SetString(PyExc_IOError, "could not create diagram");
+  if (!PyArg_ParseTuple (args, "s:dia.new", &filename))
     return NULL;
+
+  dia = dia_diagram_new (filename);
+  if (dia) {
+    return PyDiaDiagram_New (dia);
+  }
+
+  PyErr_SetString (PyExc_IOError, "could not create diagram");
+
+  return NULL;
 }
 
 static PyObject *


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