[dia] layer-dialog: split into seperate files for each class



commit 6c7f9784eace3767171b22c7ac10807bab8a487f
Author: Zander Brown <zbrown gnome org>
Date:   Fri Sep 27 23:34:13 2019 +0100

    layer-dialog: split into seperate files for each class
    
    makes things slightly more managable

 app/app_procs.c                            |    2 +-
 app/commands.c                             |    2 +-
 app/diagram.c                              |    2 +-
 app/display.c                              |    2 +-
 app/filedlg.c                              |    2 +-
 app/interface.c                            |    2 +-
 app/layer-editor/dia-layer-editor-dialog.c |  373 +++++
 app/layer-editor/dia-layer-editor-dialog.h |   41 +
 app/layer-editor/dia-layer-editor.c        |  572 ++++++++
 app/layer-editor/dia-layer-editor.h        |   41 +
 app/layer-editor/dia-layer-properties.c    |  331 +++++
 app/layer-editor/dia-layer-properties.h    |   43 +
 app/layer-editor/dia-layer-widget.c        |  539 +++++++
 app/layer-editor/dia-layer-widget.h        |   50 +
 app/layer-editor/layer_dialog.c            |  353 +++++
 app/layer-editor/layer_dialog.h            |   70 +
 app/layer_dialog.c                         | 2113 ----------------------------
 app/layer_dialog.h                         |  110 --
 app/meson.build                            |   13 +-
 app/recent_files.c                         |    2 +-
 lib/dia-layer.h                            |    1 +
 21 files changed, 2433 insertions(+), 2231 deletions(-)
---
diff --git a/app/app_procs.c b/app/app_procs.c
index f150dcfa..a53e4af4 100644
--- a/app/app_procs.c
+++ b/app/app_procs.c
@@ -47,7 +47,7 @@
 #include "group.h"
 #include "message.h"
 #include "display.h"
-#include "layer_dialog.h"
+#include "layer-editor/layer_dialog.h"
 #include "load_save.h"
 #include "preferences.h"
 #include "dia_dirs.h"
diff --git a/app/commands.c b/app/commands.c
index 88ecbdeb..03f6baa5 100644
--- a/app/commands.c
+++ b/app/commands.c
@@ -76,7 +76,7 @@ ShellExecuteA (long        hwnd,
 #include "properties-dialog.h"
 #include "propinternals.h"
 #include "preferences.h"
-#include "layer_dialog.h"
+#include "layer-editor/layer_dialog.h"
 #include "connectionpoint_ops.h"
 #include "undo.h"
 #include "pagesetup.h"
diff --git a/app/diagram.c b/app/diagram.c
index 09971894..fe8ec8c7 100644
--- a/app/diagram.c
+++ b/app/diagram.c
@@ -32,7 +32,7 @@
 #include "preferences.h"
 #include "properties-dialog.h"
 #include "cut_n_paste.h"
-#include "layer_dialog.h"
+#include "layer-editor/layer_dialog.h"
 #include "app_procs.h"
 #include "dia_dirs.h"
 #include "load_save.h"
diff --git a/app/display.c b/app/display.c
index 940f4cbd..8f1eb140 100644
--- a/app/display.c
+++ b/app/display.c
@@ -39,7 +39,7 @@
 #include "message.h"
 #include "preferences.h"
 #include "app_procs.h"
-#include "layer_dialog.h"
+#include "layer-editor/layer_dialog.h"
 #include "load_save.h"
 #include "dia-props.h"
 #include "renderer/diacairo.h"
diff --git a/app/filedlg.c b/app/filedlg.c
index 0c6fb8af..9646cd6d 100644
--- a/app/filedlg.c
+++ b/app/filedlg.c
@@ -37,7 +37,7 @@
 #include "persistence.h"
 #include "display.h"
 #include "message.h"
-#include "layer_dialog.h"
+#include "layer-editor/layer_dialog.h"
 #include "load_save.h"
 #include "preferences.h"
 #include "interface.h"
diff --git a/app/interface.c b/app/interface.c
index fbb6f0c9..377efb68 100644
--- a/app/interface.c
+++ b/app/interface.c
@@ -32,7 +32,7 @@
 
 #include "diagram.h"
 #include "object.h"
-#include "layer_dialog.h"
+#include "layer-editor/layer_dialog.h"
 #include "interface.h"
 #include "display.h"
 #include "disp_callbacks.h"
diff --git a/app/layer-editor/dia-layer-editor-dialog.c b/app/layer-editor/dia-layer-editor-dialog.c
new file mode 100644
index 00000000..402caf8f
--- /dev/null
+++ b/app/layer-editor/dia-layer-editor-dialog.c
@@ -0,0 +1,373 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+
+#include "intl.h"
+
+#include "persistence.h"
+#include "dia-application.h"
+#include "dia-layer-editor.h"
+#include "dia-layer-editor-dialog.h"
+#include "layer_dialog.h"
+
+enum {
+  COL_FILENAME,
+  COL_DIAGRAM
+};
+
+typedef struct _DiaLayerEditorDialogPrivate DiaLayerEditorDialogPrivate;
+struct _DiaLayerEditorDialogPrivate {
+  Diagram      *diagram;
+
+  GtkListStore *store;
+
+  GtkWidget    *combo;
+  GtkWidget    *editor;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (DiaLayerEditorDialog, dia_layer_editor_dialog, GTK_TYPE_DIALOG)
+
+enum {
+  DLG_PROP_0,
+  DLG_PROP_DIAGRAM,
+  LAST_DLG_PROP
+};
+
+static GParamSpec *dlg_pspecs[LAST_DLG_PROP] = { NULL, };
+
+
+static void
+dia_layer_editor_dialog_set_property (GObject      *object,
+                                      guint         property_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  DiaLayerEditorDialog *self = DIA_LAYER_EDITOR_DIALOG (object);
+
+  switch (property_id) {
+    case DLG_PROP_DIAGRAM:
+      dia_layer_editor_dialog_set_diagram (self, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_layer_editor_dialog_get_property (GObject    *object,
+                                      guint       property_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  DiaLayerEditorDialog *self = DIA_LAYER_EDITOR_DIALOG (object);
+
+
+  switch (property_id) {
+    case DLG_PROP_DIAGRAM:
+      g_value_set_object (value, dia_layer_editor_dialog_get_diagram (self));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_layer_editor_dialog_finalize (GObject *object)
+{
+  DiaLayerEditorDialog *self = DIA_LAYER_EDITOR_DIALOG (object);
+  DiaLayerEditorDialogPrivate *priv = dia_layer_editor_dialog_get_instance_private (self);
+
+  g_clear_object (&priv->diagram);
+
+  G_OBJECT_CLASS (dia_layer_editor_dialog_parent_class)->finalize (object);
+}
+
+
+static gboolean
+dia_layer_editor_dialog_delete_event (GtkWidget *widget, GdkEventAny *event)
+{
+  gtk_widget_hide (widget);
+
+  /* We're caching, so don't destroy */
+  return TRUE;
+}
+
+
+static void
+dia_layer_editor_dialog_class_init (DiaLayerEditorDialogClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->set_property = dia_layer_editor_dialog_set_property;
+  object_class->get_property = dia_layer_editor_dialog_get_property;
+  object_class->finalize = dia_layer_editor_dialog_finalize;
+
+  widget_class->delete_event = dia_layer_editor_dialog_delete_event;
+
+  /**
+   * DiaLayerEditorDialog:diagram:
+   *
+   * Since: 0.98
+   */
+  dlg_pspecs[DLG_PROP_DIAGRAM] =
+    g_param_spec_object ("diagram",
+                         "Diagram",
+                         "The current diagram",
+                         DIA_TYPE_DIAGRAM,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (object_class, LAST_DLG_PROP, dlg_pspecs);
+}
+
+
+static void
+diagrams_changed (GListModel *diagrams,
+                  guint       position,
+                  guint       removed,
+                  guint       added,
+                  gpointer    self)
+{
+  DiaLayerEditorDialogPrivate *priv = dia_layer_editor_dialog_get_instance_private (self);
+  Diagram *dia;
+  int i;
+  int current_nr;
+  GtkTreeIter iter;
+  char *basename = NULL;
+
+  g_return_if_fail (DIA_IS_LAYER_EDITOR_DIALOG (self));
+
+  current_nr = -1;
+
+  gtk_list_store_clear (priv->store);
+
+  if (g_list_model_get_n_items (diagrams) < 1) {
+    gtk_widget_set_sensitive (self, FALSE);
+
+    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combo),
+                                   NULL);
+
+    return;
+  }
+
+  gtk_widget_set_sensitive (self, 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 (priv->store, &iter);
+    gtk_list_store_set (priv->store,
+                        &iter,
+                        COL_FILENAME,
+                        basename,
+                        COL_DIAGRAM,
+                        dia,
+                        -1);
+
+    if (dia == priv->diagram) {
+      current_nr = i;
+      gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->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     self)
+{
+  DiaLayerEditorDialogPrivate *priv = dia_layer_editor_dialog_get_instance_private (self);
+  GtkTreeIter iter;
+  Diagram *diagram = NULL;
+
+  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->combo),
+                                     &iter)) {
+    gtk_tree_model_get (GTK_TREE_MODEL (priv->store),
+                        &iter,
+                        COL_DIAGRAM,
+                        &diagram,
+                        -1);
+  }
+
+  layer_dialog_set_diagram (diagram);
+
+  g_clear_object (&diagram);
+}
+
+
+static void
+dia_layer_editor_dialog_init (DiaLayerEditorDialog *self)
+{
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GtkCellRenderer *renderer;
+  DiaLayerEditorDialogPrivate *priv = dia_layer_editor_dialog_get_instance_private (self);
+
+  priv->diagram = NULL;
+
+  gtk_window_set_title (GTK_WINDOW (self), _("Layers"));
+  gtk_window_set_role (GTK_WINDOW (self), "layer_window");
+  gtk_window_set_resizable (GTK_WINDOW (self), TRUE);
+
+  g_signal_connect (G_OBJECT (self), "destroy",
+                    G_CALLBACK (gtk_widget_destroyed),
+                    self);
+
+  vbox = gtk_dialog_get_content_area (GTK_DIALOG (self));
+
+  hbox = gtk_hbox_new (FALSE, 1);
+
+  priv->store = gtk_list_store_new (2,
+                                    G_TYPE_STRING,
+                                    DIA_TYPE_DIAGRAM);
+  priv->combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->store));
+
+  g_signal_connect (dia_application_get_diagrams (dia_application_get_default ()),
+                    "items-changed",
+                    G_CALLBACK (diagrams_changed),
+                    self);
+
+  g_signal_connect (priv->combo,
+                    "changed",
+                    G_CALLBACK (diagram_changed),
+                    self);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->combo),
+                              renderer,
+                              TRUE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->combo),
+                                  renderer,
+                                  "text", COL_FILENAME,
+                                  NULL);
+
+
+  gtk_box_pack_start (GTK_BOX (hbox), priv->combo, TRUE, TRUE, 2);
+  gtk_widget_show (priv->combo);
+
+  gtk_box_pack_start(GTK_BOX (vbox), hbox, FALSE, FALSE, 2);
+  gtk_widget_show (hbox);
+
+  priv->editor = dia_layer_editor_new ();
+  g_object_bind_property (self, "diagram",
+                          priv->editor, "diagram",
+                          G_BINDING_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (vbox), priv->editor, TRUE, TRUE, 2);
+  gtk_widget_show (priv->editor);
+
+  persistence_register_window (GTK_WINDOW (self));
+}
+
+
+GtkWidget *
+dia_layer_editor_dialog_new (void)
+{
+  return g_object_new (DIA_TYPE_LAYER_EDITOR_DIALOG, NULL);
+}
+
+
+gboolean
+find_diagram (GtkTreeModel *model,
+              GtkTreePath  *path,
+              GtkTreeIter  *iter,
+              gpointer      self)
+{
+  DiaLayerEditorDialogPrivate *priv = dia_layer_editor_dialog_get_instance_private (self);
+  Diagram *diagram = NULL;
+
+  gtk_tree_model_get (model, iter, COL_DIAGRAM, &diagram, -1);
+
+  if (diagram == priv->diagram) {
+    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combo),
+                                   iter);
+
+    g_clear_object (&diagram);
+
+    return TRUE;
+  }
+
+  g_clear_object (&diagram);
+
+  return FALSE;
+}
+
+
+void
+dia_layer_editor_dialog_set_diagram (DiaLayerEditorDialog *self,
+                                     Diagram              *dia)
+{
+  DiaLayerEditorDialogPrivate *priv = dia_layer_editor_dialog_get_instance_private (self);
+
+  g_return_if_fail (DIA_IS_LAYER_EDITOR_DIALOG (self));
+
+  priv = dia_layer_editor_dialog_get_instance_private (self);
+
+  g_clear_object (&priv->diagram);
+  if (dia) {
+    priv->diagram = g_object_ref (dia);
+
+    g_signal_handlers_block_by_func (priv->combo, diagram_changed, self);
+    gtk_tree_model_foreach (GTK_TREE_MODEL (priv->store),
+                            find_diagram,
+                            self);
+    g_signal_handlers_unblock_by_func (priv->combo, diagram_changed, self);
+  } else {
+    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combo),
+                                   NULL);
+  }
+
+  g_object_notify_by_pspec (G_OBJECT (self), dlg_pspecs[DLG_PROP_DIAGRAM]);
+}
+
+
+Diagram *
+dia_layer_editor_dialog_get_diagram (DiaLayerEditorDialog *self)
+{
+  DiaLayerEditorDialogPrivate *priv;
+
+  g_return_val_if_fail (DIA_IS_LAYER_EDITOR_DIALOG (self), NULL);
+
+  priv = dia_layer_editor_dialog_get_instance_private (self);
+
+  return priv->diagram;
+}
diff --git a/app/layer-editor/dia-layer-editor-dialog.h b/app/layer-editor/dia-layer-editor-dialog.h
new file mode 100644
index 00000000..b5c22e05
--- /dev/null
+++ b/app/layer-editor/dia-layer-editor-dialog.h
@@ -0,0 +1,41 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "diagram.h"
+
+G_BEGIN_DECLS
+
+#define DIA_TYPE_LAYER_EDITOR_DIALOG dia_layer_editor_dialog_get_type ()
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkDialog, g_object_unref)
+
+G_DECLARE_DERIVABLE_TYPE (DiaLayerEditorDialog, dia_layer_editor_dialog, DIA, LAYER_EDITOR_DIALOG, GtkDialog)
+
+struct _DiaLayerEditorDialogClass {
+  GtkDialogClass parent;
+};
+
+GtkWidget *dia_layer_editor_dialog_new         (void);
+void       dia_layer_editor_dialog_set_diagram (DiaLayerEditorDialog *self,
+                                                Diagram              *dia);
+Diagram   *dia_layer_editor_dialog_get_diagram (DiaLayerEditorDialog *self);
+
+G_END_DECLS
diff --git a/app/layer-editor/dia-layer-editor.c b/app/layer-editor/dia-layer-editor.c
new file mode 100644
index 00000000..fe07f71a
--- /dev/null
+++ b/app/layer-editor/dia-layer-editor.c
@@ -0,0 +1,572 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "intl.h"
+
+#include "dia-layer-widget.h"
+#include "dia-layer-editor.h"
+#include "dia-layer-properties.h"
+#include "dia-layer.h"
+#include "layer_dialog.h"
+
+typedef struct _ButtonData ButtonData;
+
+struct _ButtonData {
+  gchar *icon_name;
+  gpointer callback;
+  char *tooltip;
+};
+
+typedef struct _DiaLayerEditorPrivate DiaLayerEditorPrivate;
+struct _DiaLayerEditorPrivate {
+  GtkWidget *list;
+  Diagram   *diagram;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (DiaLayerEditor, dia_layer_editor, GTK_TYPE_VBOX)
+
+enum {
+  PROP_0,
+  PROP_DIAGRAM,
+  LAST_PROP
+};
+
+static GParamSpec *pspecs[LAST_PROP] = { NULL, };
+
+
+static void
+dia_layer_editor_set_property (GObject      *object,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  DiaLayerEditor *self = DIA_LAYER_EDITOR (object);
+
+  switch (property_id) {
+    case PROP_DIAGRAM:
+      dia_layer_editor_set_diagram (self, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_layer_editor_get_property (GObject    *object,
+                               guint       property_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  DiaLayerEditor *self = DIA_LAYER_EDITOR (object);
+
+  switch (property_id) {
+    case PROP_DIAGRAM:
+      g_value_set_object (value, dia_layer_editor_get_diagram (self));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_layer_editor_finalize (GObject *object)
+{
+  DiaLayerEditor *self = DIA_LAYER_EDITOR (object);
+  DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
+
+  g_clear_object (&priv->diagram);
+
+  G_OBJECT_CLASS (dia_layer_editor_parent_class)->finalize (object);
+}
+
+
+static void
+dia_layer_editor_class_init (DiaLayerEditorClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = dia_layer_editor_set_property;
+  object_class->get_property = dia_layer_editor_get_property;
+  object_class->finalize = dia_layer_editor_finalize;
+
+  /**
+   * DiaLayerEditor:diagram:
+   *
+   * Since: 0.98
+   */
+  pspecs[PROP_DIAGRAM] =
+    g_param_spec_object ("diagram",
+                         "Diagram",
+                         "The current diagram",
+                         DIA_TYPE_DIAGRAM,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (object_class, LAST_PROP, pspecs);
+}
+
+
+static void rename_layer (GtkWidget *widget, DiaLayerEditor *self);
+
+static gint
+list_event (GtkWidget      *widget,
+            GdkEvent       *event,
+            DiaLayerEditor *self)
+{
+  GdkEventKey *kevent;
+  GtkWidget *event_widget;
+  DiaLayerWidget *layer_widget;
+
+  event_widget = gtk_get_event_widget (event);
+
+  if (GTK_IS_LIST_ITEM (event_widget)) {
+    layer_widget = DIA_LAYER_WIDGET (event_widget);
+
+    switch (event->type) {
+      case GDK_2BUTTON_PRESS:
+        rename_layer (GTK_WIDGET (layer_widget), self);
+        return TRUE;
+
+      case GDK_KEY_PRESS:
+        kevent = (GdkEventKey *) event;
+        switch (kevent->keyval) {
+          case GDK_Up:
+            /* printf ("up arrow\n"); */
+            break;
+          case GDK_Down:
+            /* printf ("down arrow\n"); */
+            break;
+          default:
+            return FALSE;
+        }
+        return TRUE;
+
+      default:
+        break;
+    }
+  }
+
+  return FALSE;
+}
+
+
+static void
+exclusive_connectable (DiaLayerWidget *layer_row,
+                       DiaLayerEditor *self)
+{
+  DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
+  GList *list;
+  DiaLayerWidget *lw;
+  DiaLayer *layer;
+  int connectable = FALSE;
+  int i;
+
+  /*  First determine if _any_ other layer widgets are set to connectable  */
+  for (i = 0; i < data_layer_count (DIA_DIAGRAM_DATA (priv->diagram)); i++) {
+    layer = data_layer_get_nth (DIA_DIAGRAM_DATA (priv->diagram), i);
+
+    if (dia_layer_widget_get_layer (DIA_LAYER_WIDGET (layer_row)) != layer) {
+      connectable |= dia_layer_is_connectable (layer);
+    }
+  }
+
+  /*  Now, toggle the connectability for all layers except the specified one  */
+  list = GTK_LIST (priv->list)->children;
+  while (list) {
+    lw = DIA_LAYER_WIDGET (list->data);
+    if (lw != layer_row) {
+      dia_layer_widget_set_connectable (lw, !connectable);
+    } else {
+      dia_layer_widget_set_connectable (lw, TRUE);
+    }
+    gtk_widget_queue_draw (GTK_WIDGET (lw));
+
+    list = g_list_next (list);
+  }
+}
+
+
+static void
+new_layer (GtkWidget *widget, DiaLayerEditor *self)
+{
+  DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
+  DiaLayer *layer;
+  Diagram *dia;
+  GtkWidget *selected;
+  GList *list = NULL;
+  GtkWidget *layer_widget;
+  int pos;
+  static int next_layer_num = 1;
+
+  dia = priv->diagram;
+
+  if (dia != NULL) {
+    gchar* new_layer_name = g_strdup_printf (_("New layer %d"),
+                                             next_layer_num++);
+    layer = dia_layer_new (new_layer_name, dia->data);
+
+    g_assert (GTK_LIST (priv->list)->selection != NULL);
+    selected = GTK_LIST (priv->list)->selection->data;
+    pos = gtk_list_child_position (GTK_LIST (priv->list), selected);
+
+    data_add_layer_at (dia->data, layer, dia->data->layers->len - pos);
+
+    diagram_add_update_all (dia);
+    diagram_flush (dia);
+
+    layer_widget = dia_layer_widget_new (layer, self);
+    g_signal_connect (layer_widget,
+                      "exclusive",
+                      G_CALLBACK (exclusive_connectable),
+                      self);
+    gtk_widget_show (layer_widget);
+
+    list = g_list_prepend (list, layer_widget);
+
+    gtk_list_insert_items (GTK_LIST (priv->list), list, pos);
+
+    gtk_list_select_item (GTK_LIST (priv->list), pos);
+
+    undo_layer (dia, layer, TYPE_ADD_LAYER, dia->data->layers->len - pos);
+    undo_set_transactionpoint (dia->undo);
+
+    g_free (new_layer_name);
+  }
+}
+
+
+static void
+rename_layer (GtkWidget *widget, DiaLayerEditor *self)
+{
+  DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
+  Diagram *dia;
+  DiaLayer *layer;
+  GtkWidget *dlg;
+
+  dia = priv->diagram;
+
+  if (dia == NULL) {
+    return;
+  }
+
+  layer = dia->data->active_layer;
+
+  dlg = g_object_new (DIA_TYPE_LAYER_PROPERTIES,
+                     "layer", layer,
+                     "visible", TRUE,
+                     NULL);
+  gtk_widget_show (dlg);
+}
+
+
+static void
+delete_layer (GtkWidget *widget, DiaLayerEditor *self)
+{
+  DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
+  Diagram *dia;
+  GtkWidget *selected;
+  DiaLayer *layer;
+  int pos;
+
+  dia = priv->diagram;
+
+  if ((dia != NULL) && (dia->data->layers->len > 1)) {
+    g_assert (GTK_LIST (priv->list)->selection != NULL);
+    selected = GTK_LIST (priv->list)->selection->data;
+
+    layer = dia->data->active_layer;
+
+    data_remove_layer (dia->data, layer);
+    diagram_add_update_all (dia);
+    diagram_flush (dia);
+
+    pos = gtk_list_child_position (GTK_LIST (priv->list), selected);
+    gtk_container_remove (GTK_CONTAINER (priv->list), selected);
+
+    undo_layer (dia, layer, TYPE_DELETE_LAYER,
+                dia->data->layers->len - pos);
+    undo_set_transactionpoint (dia->undo);
+
+    if (--pos < 0) {
+      pos = 0;
+    }
+
+    gtk_list_select_item (GTK_LIST (priv->list), pos);
+  }
+}
+
+
+static void
+raise_layer (GtkWidget *widget, DiaLayerEditor *self)
+{
+  DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
+  DiaLayer *layer;
+  Diagram *dia;
+  GtkWidget *selected;
+  GList *list = NULL;
+  int pos;
+
+  dia = priv->diagram;
+
+  if ((dia != NULL) && (dia->data->layers->len > 1)) {
+    g_assert (GTK_LIST (priv->list)->selection != NULL);
+    selected = GTK_LIST (priv->list)->selection->data;
+
+    pos = gtk_list_child_position (GTK_LIST (priv->list), selected);
+
+    if (pos > 0) {
+      layer = dia_layer_widget_get_layer (DIA_LAYER_WIDGET (selected));
+      data_raise_layer (dia->data, layer);
+
+      list = g_list_prepend (list, selected);
+
+      g_object_ref (selected);
+
+      gtk_list_remove_items (GTK_LIST (priv->list),
+                             list);
+
+      gtk_list_insert_items (GTK_LIST (priv->list),
+                             list, pos - 1);
+
+      g_object_unref (selected);
+
+      gtk_list_select_item (GTK_LIST (priv->list), pos-1);
+
+      diagram_add_update_all (dia);
+      diagram_flush (dia);
+
+      undo_layer (dia, layer, TYPE_RAISE_LAYER, 0);
+      undo_set_transactionpoint (dia->undo);
+    }
+  }
+}
+
+
+static void
+lower_layer (GtkWidget *widget, DiaLayerEditor *self)
+{
+  DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
+  DiaLayer *layer;
+  Diagram *dia;
+  GtkWidget *selected;
+  GList *list = NULL;
+  int pos;
+
+  dia = priv->diagram;
+
+  if ((dia != NULL) && (dia->data->layers->len > 1)) {
+    g_assert (GTK_LIST (priv->list)->selection != NULL);
+    selected = GTK_LIST (priv->list)->selection->data;
+
+    pos = gtk_list_child_position (GTK_LIST (priv->list), selected);
+
+    if (pos < dia->data->layers->len-1) {
+      layer = dia_layer_widget_get_layer (DIA_LAYER_WIDGET (selected));
+      data_lower_layer (dia->data, layer);
+
+      list = g_list_prepend (list, selected);
+
+      g_object_ref (selected);
+
+      gtk_list_remove_items (GTK_LIST (priv->list),
+                             list);
+
+      gtk_list_insert_items (GTK_LIST (priv->list),
+                             list, pos + 1);
+
+      g_object_unref (selected);
+
+      gtk_list_select_item (GTK_LIST (priv->list), pos+1);
+
+      diagram_add_update_all (dia);
+      diagram_flush (dia);
+
+      undo_layer (dia, layer, TYPE_LOWER_LAYER, 0);
+      undo_set_transactionpoint (dia->undo);
+    }
+  }
+}
+
+
+static ButtonData editor_buttons[] = {
+  { "list-add", new_layer, N_("New Layer") },
+  { "list-remove", delete_layer, N_("Delete Layer") },
+  { "document-properties", rename_layer, N_("Rename Layer") },
+  { "go-up", raise_layer, N_("Raise Layer") },
+  { "go-down", lower_layer, N_("Lower Layer") },
+};
+
+
+static void
+dia_layer_editor_init (DiaLayerEditor *self)
+{
+  GtkWidget *scrolled_win;
+  GtkWidget *button_box;
+  GtkWidget *button;
+  DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
+
+  gtk_container_set_border_width (GTK_CONTAINER (self), 6);
+  g_object_set (self, "width-request", 250, NULL);
+
+  priv->diagram = NULL;
+
+  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_show (scrolled_win);
+  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_box_pack_start (GTK_BOX (self), scrolled_win, TRUE, TRUE, 2);
+
+  priv->list = gtk_list_new ();
+  gtk_widget_show (priv->list);
+  gtk_list_set_selection_mode (GTK_LIST (priv->list), GTK_SELECTION_BROWSE);
+  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), priv->list);
+  gtk_container_set_focus_vadjustment (GTK_CONTAINER (priv->list),
+                                       gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW 
(scrolled_win)));
+
+  g_signal_connect (G_OBJECT (priv->list),
+                    "event",
+                    G_CALLBACK (list_event),
+                    self);
+
+  // inline-toolbar
+  button_box = gtk_hbox_new (FALSE, 0);
+
+  for (int i = 0; i < G_N_ELEMENTS (editor_buttons); i++) {
+    GtkWidget * image;
+
+    button = gtk_button_new ();
+
+    image = gtk_image_new_from_icon_name (editor_buttons[i].icon_name,
+                                          GTK_ICON_SIZE_BUTTON);
+
+    gtk_button_set_image (GTK_BUTTON (button), image);
+
+    g_signal_connect (G_OBJECT (button),
+                      "clicked",
+                      G_CALLBACK (editor_buttons[i].callback),
+                      self);
+
+    gtk_widget_set_tooltip_text (button, gettext (editor_buttons[i].tooltip));
+
+    gtk_box_pack_start (GTK_BOX (button_box), button, TRUE, TRUE, 0);
+
+    gtk_widget_show (button);
+  }
+
+  gtk_box_pack_start (GTK_BOX (self), button_box, FALSE, FALSE, 2);
+  gtk_widget_show (button_box);
+}
+
+
+GtkWidget *
+dia_layer_editor_new (void)
+{
+  return g_object_new (DIA_TYPE_LAYER_EDITOR,
+                       NULL);
+}
+
+
+/*
+ * Used to avoid writing to possibly already deleted layer in
+ * dia_layer_widget_connectable_toggled(). Must be called before
+ * e.g. gtk_list_clear_items() cause that will emit the toggled
+ * signal to last focus widget. See bug #329096
+ */
+static void
+_layer_widget_clear_layer (GtkWidget *widget, gpointer user_data)
+{
+  DiaLayerWidget *lw = DIA_LAYER_WIDGET (widget);
+
+  dia_layer_widget_set_layer (lw, NULL);
+}
+
+
+void
+dia_layer_editor_set_diagram (DiaLayerEditor *self,
+                              Diagram        *dia)
+{
+  DiaLayerEditorPrivate *priv;
+  GtkWidget *layer_widget;
+  DiaLayer *layer;
+  DiaLayer *active_layer = NULL;
+  int sel_pos;
+  int i,j;
+
+  g_return_if_fail (DIA_IS_LAYER_EDITOR (self));
+
+  priv = dia_layer_editor_get_instance_private (self);
+
+  g_clear_object (&priv->diagram);
+
+  if (dia == NULL) {
+    g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_DIAGRAM]);
+
+    return;
+  }
+
+  priv->diagram = g_object_ref (dia);
+
+  active_layer = DIA_DIAGRAM_DATA (dia)->active_layer;
+
+  gtk_container_foreach (GTK_CONTAINER (priv->list),
+                         _layer_widget_clear_layer, NULL);
+  gtk_list_clear_items (GTK_LIST (priv->list), 0, -1);
+
+  sel_pos = 0;
+  for (i = data_layer_count (DIA_DIAGRAM_DATA (dia)) - 1, j = 0; i >= 0; i--, j++) {
+    layer = data_layer_get_nth (DIA_DIAGRAM_DATA (dia), i);
+
+    layer_widget = dia_layer_widget_new (layer, self);
+    gtk_widget_show (layer_widget);
+
+    gtk_container_add (GTK_CONTAINER (priv->list),
+                       layer_widget);
+
+    if (layer == active_layer) {
+      sel_pos = j;
+    }
+  }
+
+  gtk_list_select_item (GTK_LIST (priv->list), sel_pos);
+
+  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_DIAGRAM]);
+}
+
+
+Diagram *
+dia_layer_editor_get_diagram (DiaLayerEditor *self)
+{
+  DiaLayerEditorPrivate *priv;
+
+  g_return_val_if_fail (DIA_IS_LAYER_EDITOR (self), NULL);
+
+  priv = dia_layer_editor_get_instance_private (self);
+
+  return priv->diagram;
+}
diff --git a/app/layer-editor/dia-layer-editor.h b/app/layer-editor/dia-layer-editor.h
new file mode 100644
index 00000000..fa048a59
--- /dev/null
+++ b/app/layer-editor/dia-layer-editor.h
@@ -0,0 +1,41 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "diagram.h"
+
+G_BEGIN_DECLS
+
+#define DIA_TYPE_LAYER_EDITOR dia_layer_editor_get_type ()
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkVBox, g_object_unref)
+
+G_DECLARE_DERIVABLE_TYPE (DiaLayerEditor, dia_layer_editor, DIA, LAYER_EDITOR, GtkVBox)
+
+struct _DiaLayerEditorClass {
+  GtkVBoxClass parent;
+};
+
+GtkWidget *dia_layer_editor_new         (void);
+void       dia_layer_editor_set_diagram (DiaLayerEditor *self,
+                                         Diagram        *dia);
+Diagram   *dia_layer_editor_get_diagram (DiaLayerEditor *self);
+
+G_END_DECLS
diff --git a/app/layer-editor/dia-layer-properties.c b/app/layer-editor/dia-layer-properties.c
new file mode 100644
index 00000000..311d8e3a
--- /dev/null
+++ b/app/layer-editor/dia-layer-properties.c
@@ -0,0 +1,331 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+
+#include "intl.h"
+
+#include "dia-application.h"
+#include "dia-layer.h"
+#include "dia-layer-properties.h"
+#include "layer_dialog.h"
+
+typedef struct _DiaLayerPropertiesPrivate DiaLayerPropertiesPrivate;
+struct _DiaLayerPropertiesPrivate {
+  GtkWidget *entry;
+
+  DiaLayer  *layer;
+  Diagram   *diagram;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (DiaLayerProperties, dia_layer_properties, GTK_TYPE_DIALOG)
+
+enum {
+  LP_PROP_0,
+  LP_PROP_LAYER,
+  LP_PROP_DIAGRAM,
+  LAST_LP_PROP
+};
+
+static GParamSpec *lp_pspecs[LAST_LP_PROP] = { NULL, };
+
+
+static void
+dia_layer_properties_set_property (GObject      *object,
+                                   guint         property_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  DiaLayerProperties *self = DIA_LAYER_PROPERTIES (object);
+
+  switch (property_id) {
+    case LP_PROP_LAYER:
+      dia_layer_properties_set_layer (self, g_value_get_object (value));
+      break;
+    case LP_PROP_DIAGRAM:
+      dia_layer_properties_set_diagram (self, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_layer_properties_get_property (GObject    *object,
+                                   guint       property_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  DiaLayerProperties *self = DIA_LAYER_PROPERTIES (object);
+
+  switch (property_id) {
+    case LP_PROP_LAYER:
+      g_value_set_object (value, dia_layer_properties_get_layer (self));
+      break;
+    case LP_PROP_DIAGRAM:
+      g_value_set_object (value, dia_layer_properties_get_diagram (self));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_layer_properties_finalize (GObject *object)
+{
+  DiaLayerProperties *self = DIA_LAYER_PROPERTIES (object);
+  DiaLayerPropertiesPrivate *priv = dia_layer_properties_get_instance_private (self);
+
+  g_clear_object (&priv->layer);
+  g_clear_object (&priv->diagram);
+
+  G_OBJECT_CLASS (dia_layer_properties_parent_class)->finalize (object);
+}
+
+
+static void
+dia_layer_properties_response (GtkDialog *dialog,
+                               int        response)
+{
+  DiaLayerProperties *self = DIA_LAYER_PROPERTIES (dialog);
+  DiaLayerPropertiesPrivate *priv = dia_layer_properties_get_instance_private (self);
+
+  if (response != GTK_RESPONSE_OK) {
+    gtk_widget_destroy (GTK_WIDGET (dialog));
+
+    return;
+  }
+
+  if (priv->layer) {
+    Diagram *dia = DIA_DIAGRAM (dia_layer_get_parent_diagram (priv->layer));
+
+    g_object_set (priv->layer,
+                  "name", gtk_entry_get_text (GTK_ENTRY (priv->entry)),
+                  NULL);
+
+    diagram_add_update_all (dia);
+    diagram_flush (dia);
+    /* FIXME: undo handling */
+
+    /* reflect name change on listeners */
+    /* TODO, is this defunt with notfy::name? */
+    dia_application_diagram_change (dia_application_get_default (),
+                                    dia,
+                                    DIAGRAM_CHANGE_LAYER,
+                                    priv->layer);
+  } else if (priv->diagram) {
+    DiaLayer *layer;
+    int pos = data_layer_get_index (DIA_DIAGRAM_DATA (priv->diagram),
+                                    DIA_DIAGRAM_DATA (priv->diagram)->active_layer) + 1;
+
+    layer = dia_layer_new (gtk_entry_get_text (GTK_ENTRY (priv->entry)),
+                           DIA_DIAGRAM_DATA (priv->diagram));
+    data_add_layer_at (DIA_DIAGRAM_DATA (priv->diagram), layer, pos);
+    data_set_active_layer (DIA_DIAGRAM_DATA (priv->diagram), layer);
+
+    diagram_add_update_all (priv->diagram);
+    diagram_flush (priv->diagram);
+
+    undo_layer (priv->diagram, layer, TYPE_ADD_LAYER, pos);
+    undo_set_transactionpoint (priv->diagram->undo);
+  } else {
+    g_critical ("Huh, no layer or diagram");
+  }
+
+  gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+
+static void
+dia_layer_properties_class_init (DiaLayerPropertiesClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
+
+  object_class->set_property = dia_layer_properties_set_property;
+  object_class->get_property = dia_layer_properties_get_property;
+  object_class->finalize = dia_layer_properties_finalize;
+
+  dialog_class->response = dia_layer_properties_response;
+
+  /**
+   * DiaLayerProperties:layer:
+   *
+   * #DiaLayer to rename
+   *
+   * Overrides #DiaLayerProperties:diagram
+   *
+   * Since: 0.98
+   */
+  lp_pspecs[LP_PROP_LAYER] =
+    g_param_spec_object ("layer",
+                         "Layer",
+                         "The layer",
+                         DIA_TYPE_LAYER,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * DiaLayerProperties:diagram:
+   *
+   * #Diagram to add a #DiaLayer to
+   *
+   * Overrides #DiaLayerProperties:layer
+   *
+   * Since: 0.98
+   */
+  lp_pspecs[LP_PROP_DIAGRAM] =
+    g_param_spec_object ("diagram",
+                         "Diagram",
+                         "The diagram",
+                         DIA_TYPE_DIAGRAM,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (object_class, LAST_LP_PROP, lp_pspecs);
+}
+
+
+static void
+dia_layer_properties_init (DiaLayerProperties *self)
+{
+  DiaLayerPropertiesPrivate *priv = dia_layer_properties_get_instance_private (self);
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GtkWidget *label;
+
+  gtk_window_set_role (GTK_WINDOW (self), "edit_layer_attrributes");
+  gtk_window_set_title (GTK_WINDOW (self), _("Edit Layer"));
+  gtk_window_set_position (GTK_WINDOW (self), GTK_WIN_POS_MOUSE);
+
+  /*  the main vbox  */
+  vbox = gtk_vbox_new (FALSE, 1);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
+  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))),
+                      vbox,
+                      TRUE,
+                      TRUE,
+                      0);
+
+  /*  the name entry hbox, label and entry  */
+  hbox = gtk_hbox_new (FALSE, 1);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  label = gtk_label_new (_("Layer name:"));
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+  priv->entry = gtk_entry_new ();
+  gtk_entry_set_activates_default (GTK_ENTRY (priv->entry), TRUE);
+  gtk_box_pack_start (GTK_BOX (hbox), priv->entry, TRUE, TRUE, 0);
+
+  gtk_widget_show (priv->entry);
+  gtk_widget_show (hbox);
+
+  gtk_dialog_add_buttons (GTK_DIALOG (self),
+                         _("_OK"), GTK_RESPONSE_OK,
+                         _("_Cancel"), GTK_RESPONSE_CANCEL,
+                         NULL);
+
+  gtk_widget_show (vbox);
+}
+
+
+void
+dia_layer_properties_set_layer (DiaLayerProperties *self,
+                                DiaLayer           *layer)
+{
+  DiaLayerPropertiesPrivate *priv;
+
+  g_return_if_fail (DIA_IS_LAYER_PROPERTIES (self));
+
+  priv = dia_layer_properties_get_instance_private (self);
+
+  g_clear_object (&priv->diagram);
+  g_object_notify_by_pspec (G_OBJECT (self), lp_pspecs[LP_PROP_DIAGRAM]);
+
+  gtk_window_set_title (GTK_WINDOW (self), _("Edit Layer"));
+
+  g_clear_object (&priv->layer);
+  if (layer) {
+    priv->layer = g_object_ref (layer);
+
+    gtk_entry_set_text (GTK_ENTRY (priv->entry),
+                        dia_layer_get_name (priv->layer));
+  }
+
+  g_object_notify_by_pspec (G_OBJECT (self), lp_pspecs[LP_PROP_LAYER]);
+}
+
+
+DiaLayer *
+dia_layer_properties_get_layer (DiaLayerProperties *self)
+{
+  DiaLayerPropertiesPrivate *priv;
+
+  g_return_val_if_fail (DIA_IS_LAYER_PROPERTIES (self), NULL);
+
+  priv = dia_layer_properties_get_instance_private (self);
+
+  return priv->layer;
+}
+
+
+void
+dia_layer_properties_set_diagram (DiaLayerProperties *self,
+                                  Diagram            *dia)
+{
+  DiaLayerPropertiesPrivate *priv;
+
+  g_return_if_fail (DIA_IS_LAYER_PROPERTIES (self));
+
+  priv = dia_layer_properties_get_instance_private (self);
+
+  g_clear_object (&priv->layer);
+  g_object_notify_by_pspec (G_OBJECT (self), lp_pspecs[LP_PROP_LAYER]);
+
+  gtk_window_set_title (GTK_WINDOW (self), _("Add Layer"));
+
+  g_clear_object (&priv->diagram);
+  if (dia) {
+    char *name;
+
+    priv->diagram = g_object_ref (dia);
+
+    name = g_strdup_printf (_("New layer %d"),
+                            data_layer_count (DIA_DIAGRAM_DATA (dia)));
+    gtk_entry_set_text (GTK_ENTRY (priv->entry), name);
+
+    g_free (name);
+  }
+
+  g_object_notify_by_pspec (G_OBJECT (self), lp_pspecs[LP_PROP_DIAGRAM]);
+}
+
+
+Diagram *
+dia_layer_properties_get_diagram (DiaLayerProperties *self)
+{
+  DiaLayerPropertiesPrivate *priv;
+
+  g_return_val_if_fail (DIA_IS_LAYER_PROPERTIES (self), NULL);
+
+  priv = dia_layer_properties_get_instance_private (self);
+
+  return priv->diagram;
+}
diff --git a/app/layer-editor/dia-layer-properties.h b/app/layer-editor/dia-layer-properties.h
new file mode 100644
index 00000000..8034aaca
--- /dev/null
+++ b/app/layer-editor/dia-layer-properties.h
@@ -0,0 +1,43 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "diagram.h"
+#include "dia-layer-editor-dialog.h"
+
+G_BEGIN_DECLS
+
+#define DIA_TYPE_LAYER_PROPERTIES dia_layer_properties_get_type ()
+
+G_DECLARE_DERIVABLE_TYPE (DiaLayerProperties, dia_layer_properties, DIA, LAYER_PROPERTIES, GtkDialog)
+
+struct _DiaLayerPropertiesClass {
+  GtkDialogClass parent;
+};
+
+GtkWidget *dia_layer_properties_new         (void);
+void       dia_layer_properties_set_layer   (DiaLayerProperties *self,
+                                             DiaLayer           *layer);
+DiaLayer  *dia_layer_properties_get_layer   (DiaLayerProperties *self);
+void       dia_layer_properties_set_diagram (DiaLayerProperties *self,
+                                             Diagram            *dia);
+Diagram   *dia_layer_properties_get_diagram (DiaLayerProperties *self);
+
+G_END_DECLS
diff --git a/app/layer-editor/dia-layer-widget.c b/app/layer-editor/dia-layer-widget.c
new file mode 100644
index 00000000..c0fd6f76
--- /dev/null
+++ b/app/layer-editor/dia-layer-widget.c
@@ -0,0 +1,539 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+
+#include "intl.h"
+
+#include "widgets.h"
+#include "dia-layer-widget.h"
+
+/* The connectability buttons don't quite behave the way they should.
+ * The shift-click behavior messes up the active layer.
+ * To fix this, we need to rework the code so that the setting of
+ * connect_on and connect_off is not tied to the button toggling,
+ * but determined by what caused it (creation, user selection,
+ * shift-selection).
+ */
+
+typedef struct _DiaLayerWidgetPrivate DiaLayerWidgetPrivate;
+struct _DiaLayerWidgetPrivate
+{
+  DiaLayer *layer;
+
+  GBinding *name_binding;
+
+  GtkWidget *visible;
+  GtkWidget *connectable;
+  GtkWidget *label;
+
+  /* If true, the user has set this layers connectivity to on
+   * while it was not selected.
+   */
+  gboolean connect_on;
+  /* If true, the user has set this layers connectivity to off
+   * while it was selected.
+   */
+  gboolean connect_off;
+
+  DiaLayerEditor *editor;
+
+  /* If TRUE, we're in the middle of a internal call to
+   * dia_layer_widget_*_toggled and should not make undo, update diagram etc.
+   *
+   * If these calls were not done by simulating button presses, we could avoid
+   * this hack.
+   */
+  gboolean internal_call;
+
+  gboolean shifted;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (DiaLayerWidget, dia_layer_widget, GTK_TYPE_LIST_ITEM)
+
+enum {
+  EXCLUSIVE,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+enum {
+  LW_PROP_0,
+  LW_PROP_LAYER,
+  LW_PROP_EDITOR,
+  LW_PROP_CONNECTABLE,
+  LAST_LW_PROP
+};
+
+static GParamSpec *lw_pspecs[LAST_LW_PROP] = { NULL, };
+
+
+static void
+dia_layer_widget_set_property (GObject      *object,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  DiaLayerWidget *self = DIA_LAYER_WIDGET (object);
+
+  switch (property_id) {
+    case LW_PROP_LAYER:
+      dia_layer_widget_set_layer (self, g_value_get_object (value));
+      break;
+    case LW_PROP_EDITOR:
+      dia_layer_widget_set_editor (self, g_value_get_object (value));
+      break;
+    case LW_PROP_CONNECTABLE:
+      dia_layer_widget_set_connectable (self, g_value_get_boolean (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_layer_widget_get_property (GObject    *object,
+                               guint       property_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  DiaLayerWidget *self = DIA_LAYER_WIDGET (object);
+
+  switch (property_id) {
+    case LW_PROP_LAYER:
+      g_value_set_object (value, dia_layer_widget_get_layer (self));
+      break;
+    case LW_PROP_EDITOR:
+      g_value_set_object (value, dia_layer_widget_get_editor (self));
+      break;
+    case LW_PROP_CONNECTABLE:
+      g_value_set_boolean (value, dia_layer_widget_get_connectable (self));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_layer_widget_finalize (GObject *object)
+{
+  DiaLayerWidget *self = DIA_LAYER_WIDGET (object);
+  DiaLayerWidgetPrivate *priv = dia_layer_widget_get_instance_private (self);
+
+  g_clear_object (&priv->layer);
+  g_clear_object (&priv->editor);
+
+  G_OBJECT_CLASS (dia_layer_widget_parent_class)->finalize (object);
+}
+
+
+static void
+dia_layer_widget_class_init (DiaLayerWidgetClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = dia_layer_widget_set_property;
+  object_class->get_property = dia_layer_widget_get_property;
+  object_class->finalize = dia_layer_widget_finalize;
+
+  signals[EXCLUSIVE] =
+    g_signal_new ("exclusive",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  0,
+                  NULL,
+                  NULL,
+                  NULL,
+                  G_TYPE_NONE, 0);
+
+  /**
+   * DiaLayerWidget:layer:
+   *
+   * #DiaLayer to control
+   *
+   * Since: 0.98
+   */
+  lw_pspecs[LW_PROP_LAYER] =
+    g_param_spec_object ("layer",
+                         "Layer",
+                         "The layer",
+                         DIA_TYPE_LAYER,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * DiaLayerWidget:editor:
+   *
+   * The #DiaLayerEditor this is for
+   *
+   * Since: 0.98
+   */
+  lw_pspecs[LW_PROP_EDITOR] =
+    g_param_spec_object ("editor",
+                         "Editor",
+                         "The editor",
+                         DIA_TYPE_LAYER_EDITOR,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * DiaLayerWidget:connectable:
+   *
+   * Is the layer connectable
+   *
+   * Since: 0.98
+   */
+  lw_pspecs[LW_PROP_CONNECTABLE] =
+    g_param_spec_boolean ("connectable",
+                          "Connectable",
+                          "Is the layer connectable",
+                          TRUE,
+                          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (object_class, LAST_LW_PROP, lw_pspecs);
+}
+
+
+static gboolean
+button_event (GtkWidget      *widget,
+              GdkEventButton *event,
+              gpointer        userdata)
+{
+  DiaLayerWidget *self = DIA_LAYER_WIDGET (userdata);
+  DiaLayerWidgetPrivate *priv = dia_layer_widget_get_instance_private (self);
+
+  priv->shifted = event->state & GDK_SHIFT_MASK;
+
+  priv->internal_call = FALSE;
+  /* Redraw the label? */
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+
+  return FALSE;
+}
+
+static void
+connectable_toggled (GtkToggleButton *widget,
+                     gpointer         userdata)
+{
+  DiaLayerWidget *self = DIA_LAYER_WIDGET (userdata);
+  DiaLayerWidgetPrivate *priv = dia_layer_widget_get_instance_private (self);
+
+  if (!priv->layer)
+    return;
+
+  if (priv->shifted) {
+    priv->shifted = FALSE;
+    priv->internal_call = TRUE;
+    g_signal_emit (self, signals[EXCLUSIVE], 0);
+    priv->internal_call = FALSE;
+  } else {
+    dia_layer_set_connectable (priv->layer,
+                               gtk_toggle_button_get_active (widget));
+  }
+
+  if (priv->layer == dia_layer_get_parent_diagram (priv->layer)->active_layer) {
+    priv->connect_off = !gtk_toggle_button_get_active (widget);
+    if (priv->connect_off) {
+      priv->connect_on = FALSE;
+    }
+  } else {
+    priv->connect_on = gtk_toggle_button_get_active (widget);
+    if (priv->connect_on) {
+      priv->connect_off = FALSE;
+    }
+  }
+
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+
+  if (!priv->internal_call) {
+    Diagram *diagram = DIA_DIAGRAM (dia_layer_get_parent_diagram (priv->layer));
+
+    diagram_add_update_all (diagram);
+    diagram_flush (diagram);
+  }
+}
+
+static void
+visible_clicked (GtkToggleButton *widget,
+                 gpointer         userdata)
+{
+  DiaLayerWidget *self = DIA_LAYER_WIDGET (userdata);
+  DiaLayerWidgetPrivate *priv = dia_layer_widget_get_instance_private (self);
+  struct LayerVisibilityChange *change;
+
+  /* Have to use this internal_call hack 'cause there's no way to switch
+   * a toggle button without causing the 'clicked' event:(
+   */
+  if (!priv->internal_call) {
+    Diagram *dia = DIA_DIAGRAM (dia_layer_get_parent_diagram (priv->layer));
+    change = undo_layer_visibility (dia, priv->layer, priv->shifted);
+    /** This apply kills 'lw', thus we have to hold onto 'lw->dia' */
+    layer_visibility_change_apply (change, dia);
+    undo_set_transactionpoint (dia->undo);
+  }
+}
+
+static void
+select_callback (GtkWidget *widget, gpointer data)
+{
+  DiaLayerWidget *self = DIA_LAYER_WIDGET (widget);
+  DiaLayerWidgetPrivate *priv = dia_layer_widget_get_instance_private (self);
+  DiagramData *diagram;
+
+  g_return_if_fail (priv->layer != NULL);
+
+  diagram = dia_layer_get_parent_diagram (priv->layer);
+
+  /* Don't deselect if we're selected the active layer.  This can happen
+   * if the window has been defocused. */
+  if (diagram->active_layer != priv->layer) {
+    diagram_remove_all_selected (DIA_DIAGRAM (diagram), TRUE);
+  }
+  diagram_update_extents (DIA_DIAGRAM (diagram));
+  data_set_active_layer (diagram, priv->layer);
+  diagram_add_update_all (DIA_DIAGRAM (diagram));
+  diagram_flush (DIA_DIAGRAM (diagram));
+
+  priv->internal_call = TRUE;
+  if (priv->connect_off) { /* If the user wants this off, it becomes so */
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->connectable), FALSE);
+  } else {
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->connectable), TRUE);
+  }
+  priv->internal_call = FALSE;
+}
+
+static void
+deselect_callback (GtkWidget *widget, gpointer data)
+{
+  DiaLayerWidget *self = DIA_LAYER_WIDGET (widget);
+  DiaLayerWidgetPrivate *priv = dia_layer_widget_get_instance_private (self);
+
+  priv->internal_call = TRUE;
+  /** Set to on if the user has requested so. */
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->connectable),
+                                priv->connect_on);
+  priv->internal_call = FALSE;
+}
+
+static void
+dia_layer_widget_init (DiaLayerWidget *self)
+{
+  DiaLayerWidgetPrivate *priv = dia_layer_widget_get_instance_private (self);
+  GtkWidget *hbox;
+
+  hbox = gtk_hbox_new (FALSE, 0);
+
+  priv->internal_call = FALSE;
+  priv->shifted = FALSE;
+
+  priv->layer = NULL;
+
+  priv->connect_on = FALSE;
+  priv->connect_off = FALSE;
+
+  priv->visible = dia_toggle_button_new_with_icon_names ("dia-visible",
+                                                         "dia-visible-empty");
+
+  priv->editor = NULL;
+
+  g_signal_connect (G_OBJECT (priv->visible),
+                    "button-release-event",
+                    G_CALLBACK (button_event),
+                    self);
+  g_signal_connect (G_OBJECT (priv->visible),
+                    "button-press-event",
+                    G_CALLBACK (button_event),
+                    self);
+  g_signal_connect (G_OBJECT (priv->visible),
+                    "clicked",
+                    G_CALLBACK (visible_clicked),
+                    self);
+  gtk_box_pack_start (GTK_BOX (hbox), priv->visible, FALSE, TRUE, 2);
+  gtk_widget_show (priv->visible);
+
+  /*gtk_image_new_from_stock(GTK_STOCK_CONNECT,
+                           GTK_ICON_SIZE_BUTTON), */
+  priv->connectable =
+    dia_toggle_button_new_with_icon_names ("dia-connectable",
+                                           "dia-connectable-empty");
+
+  g_signal_connect (G_OBJECT (priv->connectable),
+                    "button-release-event",
+                    G_CALLBACK (button_event),
+                    self);
+  g_signal_connect (G_OBJECT (priv->connectable),
+                    "button-press-event",
+                    G_CALLBACK (button_event),
+                    self);
+  g_signal_connect (G_OBJECT (priv->connectable),
+                    "clicked",
+                    G_CALLBACK (connectable_toggled),
+                    self);
+
+  gtk_box_pack_start (GTK_BOX (hbox), priv->connectable, FALSE, TRUE, 2);
+  gtk_widget_show (priv->connectable);
+
+  priv->label = gtk_label_new ("layer_default_label");
+  gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT);
+  gtk_box_pack_start (GTK_BOX (hbox), priv->label, FALSE, TRUE, 0);
+  gtk_widget_show (priv->label);
+
+  gtk_widget_show (hbox);
+
+  gtk_container_add (GTK_CONTAINER (self), hbox);
+
+  g_signal_connect (G_OBJECT (self),
+                    "select",
+                    G_CALLBACK (select_callback),
+                    NULL);
+  g_signal_connect (G_OBJECT (self),
+                    "deselect",
+                    G_CALLBACK (deselect_callback),
+                    NULL);
+}
+
+
+void
+dia_layer_widget_set_layer (DiaLayerWidget *self,
+                            DiaLayer       *layer)
+{
+  DiaLayerWidgetPrivate *priv;
+
+  g_return_if_fail (DIA_IS_LAYER_WIDGET (self));
+
+  priv = dia_layer_widget_get_instance_private (self);
+
+  g_clear_object (&priv->layer);
+  if (layer) {
+    priv->layer = g_object_ref (layer);
+
+    g_clear_object (&priv->name_binding);
+    priv->name_binding = g_object_bind_property (layer, "name",
+                                                priv->label, "label",
+                                                G_BINDING_SYNC_CREATE);
+
+    priv->internal_call = TRUE;
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->visible),
+                                  dia_layer_is_visible (priv->layer));
+
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->connectable),
+                                  dia_layer_is_connectable (priv->layer));
+    priv->internal_call = FALSE;
+
+    /* These may get toggled when the button is set without the widget being
+    * selected first.
+    * The connect_on state gets also used to restore with just a deselect
+    * of the active layer.
+    */
+    priv->connect_on = dia_layer_is_connectable (layer);
+    priv->connect_off = FALSE;
+
+    gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
+  } else {
+    gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+  }
+
+  g_object_notify_by_pspec (G_OBJECT (self), lw_pspecs[LW_PROP_LAYER]);
+}
+
+
+DiaLayer *
+dia_layer_widget_get_layer (DiaLayerWidget *self)
+{
+  DiaLayerWidgetPrivate *priv;
+
+  g_return_val_if_fail (DIA_IS_LAYER_WIDGET (self), NULL);
+
+  priv = dia_layer_widget_get_instance_private (self);
+
+  return priv->layer;
+}
+
+
+void
+dia_layer_widget_set_editor (DiaLayerWidget *self,
+                             DiaLayerEditor *editor)
+{
+  DiaLayerWidgetPrivate *priv;
+
+  g_return_if_fail (DIA_IS_LAYER_WIDGET (self));
+
+  priv = dia_layer_widget_get_instance_private (self);
+
+  g_clear_object (&priv->editor);
+  if (editor) {
+    priv->editor = g_object_ref (editor);
+  }
+
+  g_object_notify_by_pspec (G_OBJECT (self), lw_pspecs[LW_PROP_EDITOR]);
+}
+
+
+DiaLayerEditor *
+dia_layer_widget_get_editor (DiaLayerWidget *self)
+{
+  DiaLayerWidgetPrivate *priv;
+
+  g_return_val_if_fail (DIA_IS_LAYER_WIDGET (self), NULL);
+
+  priv = dia_layer_widget_get_instance_private (self);
+
+  return priv->editor;
+}
+
+
+void
+dia_layer_widget_set_connectable (DiaLayerWidget *self, gboolean on)
+{
+  DiaLayerWidgetPrivate *priv;
+
+  g_return_if_fail (DIA_IS_LAYER_WIDGET (self));
+
+  priv = dia_layer_widget_get_instance_private (self);
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->connectable), on);
+
+  g_object_notify_by_pspec (G_OBJECT (self), lw_pspecs[LW_PROP_CONNECTABLE]);
+}
+
+
+gboolean
+dia_layer_widget_get_connectable (DiaLayerWidget *self)
+{
+  DiaLayerWidgetPrivate *priv;
+
+  g_return_val_if_fail (DIA_IS_LAYER_WIDGET (self), FALSE);
+
+  priv = dia_layer_widget_get_instance_private (self);
+
+  return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->connectable));
+}
+
+
+GtkWidget *
+dia_layer_widget_new (DiaLayer *layer, DiaLayerEditor *editor)
+{
+  return g_object_new (DIA_TYPE_LAYER_WIDGET,
+                       "layer", layer,
+                       "editor", editor,
+                       NULL);
+}
diff --git a/app/layer-editor/dia-layer-widget.h b/app/layer-editor/dia-layer-widget.h
new file mode 100644
index 00000000..f6f4dff4
--- /dev/null
+++ b/app/layer-editor/dia-layer-widget.h
@@ -0,0 +1,50 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "dia-layer.h"
+#include "dia-layer-editor.h"
+
+G_BEGIN_DECLS
+
+#define DIA_TYPE_LAYER_WIDGET dia_layer_widget_get_type ()
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkListItem, g_object_unref)
+
+G_DECLARE_DERIVABLE_TYPE (DiaLayerWidget, dia_layer_widget, DIA, LAYER_WIDGET, GtkListItem)
+
+struct _DiaLayerWidgetClass {
+  GtkListItemClass parent;
+};
+
+GtkWidget      *dia_layer_widget_new             (DiaLayer       *layer,
+                                                  DiaLayerEditor *editor);
+void            dia_layer_widget_set_layer       (DiaLayerWidget *self,
+                                                  DiaLayer       *layer);
+DiaLayer       *dia_layer_widget_get_layer       (DiaLayerWidget *self);
+void            dia_layer_widget_set_editor      (DiaLayerWidget *self,
+                                                  DiaLayerEditor *editor);
+DiaLayerEditor *dia_layer_widget_get_editor      (DiaLayerWidget *self);
+void            dia_layer_widget_set_connectable (DiaLayerWidget *self,
+                                                  gboolean        on);
+gboolean        dia_layer_widget_get_connectable (DiaLayerWidget *self);
+
+G_END_DECLS
diff --git a/app/layer-editor/layer_dialog.c b/app/layer-editor/layer_dialog.c
new file mode 100644
index 00000000..1f5ecbb5
--- /dev/null
+++ b/app/layer-editor/layer_dialog.c
@@ -0,0 +1,353 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+
+#include "intl.h"
+
+#include "dia-layer.h"
+#include "dia-layer-editor.h"
+#include "dia-layer-properties.h"
+#include "dia-layer-widget.h"
+#include "layer_dialog.h"
+#include "interface.h"
+
+struct LayerDialog {
+  GtkWidget *dialog;
+
+  GtkWidget *layer_editor;
+};
+
+static struct LayerDialog *layer_dialog = NULL;
+
+
+static void
+layer_view_hide_button_clicked (void * not_used)
+{
+  integrated_ui_layer_view_show (FALSE);
+}
+
+GtkWidget * create_layer_view_widget (void)
+{
+  GtkWidget  *vbox;
+  GtkWidget  *hbox;
+  GtkWidget  *label;
+  GtkWidget  *hide_button;
+  GtkRcStyle *rcstyle;    /* For hide_button */
+  GtkWidget  *image;      /* For hide_button */
+
+  /* if layer_dialog were renamed to layer_view_data this would make
+   * more sense.
+   */
+  layer_dialog = g_new0 (struct LayerDialog, 1);
+
+  layer_dialog->dialog = vbox = gtk_vbox_new (FALSE, 1);
+
+  hbox = gtk_hbox_new (FALSE, 1);
+
+  label = gtk_label_new (_ ("Layers"));
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2);
+  gtk_widget_show (label);
+
+  /* Hide Button */
+  hide_button = gtk_button_new ();
+  gtk_button_set_relief (GTK_BUTTON (hide_button), GTK_RELIEF_NONE);
+  gtk_button_set_focus_on_click (GTK_BUTTON (hide_button), FALSE);
+  gtk_widget_set_tooltip_text (hide_button, _("Close Layer pane"));
+
+  /* make it as small as possible */
+  rcstyle = gtk_rc_style_new ();
+  rcstyle->xthickness = rcstyle->ythickness = 0;
+  gtk_widget_modify_style (hide_button, rcstyle);
+  g_object_unref (rcstyle);
+
+  image = gtk_image_new_from_icon_name ("window-close-symbolic",
+                                        GTK_ICON_SIZE_MENU);
+
+  gtk_container_add (GTK_CONTAINER (hide_button), image);
+  g_signal_connect (G_OBJECT (hide_button), "clicked",
+                    G_CALLBACK (layer_view_hide_button_clicked), NULL);
+
+  gtk_box_pack_end (GTK_BOX (hbox), hide_button, FALSE, FALSE, 2);
+  gtk_widget_show_all (hbox);
+
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2);
+
+  layer_dialog->layer_editor = dia_layer_editor_new ();
+  gtk_widget_show (layer_dialog->layer_editor);
+  gtk_box_pack_start (GTK_BOX (vbox), layer_dialog->layer_editor, TRUE, TRUE, 0);
+
+  return vbox;
+}
+
+
+void
+layer_dialog_create (void)
+{
+  layer_dialog = g_new0(struct LayerDialog, 1);
+
+  layer_dialog->dialog = dia_layer_editor_dialog_new ();
+  gtk_widget_show (layer_dialog->dialog);
+}
+
+
+void
+layer_dialog_show()
+{
+  if (is_integrated_ui () == FALSE)
+  {
+  if (layer_dialog == NULL || layer_dialog->dialog == NULL)
+    layer_dialog_create();
+  g_assert(layer_dialog != NULL); /* must be valid now */
+  gtk_window_present(GTK_WINDOW(layer_dialog->dialog));
+  }
+}
+
+
+void
+layer_dialog_set_diagram (Diagram *dia)
+{
+  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 (DIA_IS_LAYER_EDITOR_DIALOG (layer_dialog->dialog)) {
+    dia_layer_editor_dialog_set_diagram (DIA_LAYER_EDITOR_DIALOG (layer_dialog->dialog),
+                                         dia);
+  } else {
+    dia_layer_editor_set_diagram (DIA_LAYER_EDITOR (layer_dialog->layer_editor),
+                                  dia);
+  }
+}
+
+
+static void
+layer_dialog_edit_layer (Diagram *dia, DiaLayer *layer)
+{
+  GtkWidget *dlg;
+
+  g_return_if_fail (dia || layer);
+
+  if (layer) {
+    dlg = g_object_new (DIA_TYPE_LAYER_PROPERTIES,
+                        "layer", layer,
+                        "visible", TRUE,
+                        NULL);
+  } else {
+    dlg = g_object_new (DIA_TYPE_LAYER_PROPERTIES,
+                        "diagram", dia,
+                        "visible", TRUE,
+                        NULL);
+  }
+
+  gtk_widget_show (dlg);
+}
+
+
+/******** layer changes: */
+
+static void
+layer_change_apply(struct LayerChange *change, Diagram *dia)
+{
+  change->applied = 1;
+
+  switch (change->type) {
+  case TYPE_DELETE_LAYER:
+    data_remove_layer(dia->data, change->layer);
+    break;
+  case TYPE_ADD_LAYER:
+    data_add_layer_at(dia->data, change->layer, change->index);
+    break;
+  case TYPE_RAISE_LAYER:
+    data_raise_layer(dia->data, change->layer);
+    break;
+  case TYPE_LOWER_LAYER:
+    data_lower_layer(dia->data, change->layer);
+    break;
+  }
+
+  diagram_add_update_all(dia);
+}
+
+static void
+layer_change_revert(struct LayerChange *change, Diagram *dia)
+{
+  switch (change->type) {
+  case TYPE_DELETE_LAYER:
+    data_add_layer_at(dia->data, change->layer, change->index);
+    break;
+  case TYPE_ADD_LAYER:
+    data_remove_layer(dia->data, change->layer);
+    break;
+  case TYPE_RAISE_LAYER:
+    data_lower_layer(dia->data, change->layer);
+    break;
+  case TYPE_LOWER_LAYER:
+    data_raise_layer(dia->data, change->layer);
+    break;
+  }
+
+  diagram_add_update_all(dia);
+
+  change->applied = 0;
+}
+
+static void
+layer_change_free (struct LayerChange *change)
+{
+  switch (change->type) {
+    case TYPE_DELETE_LAYER:
+      if (change->applied) {
+        g_clear_object (&change->layer);
+      }
+      break;
+    case TYPE_ADD_LAYER:
+      if (!change->applied) {
+        g_clear_object (&change->layer);
+      }
+      break;
+    case TYPE_RAISE_LAYER:
+      break;
+    case TYPE_LOWER_LAYER:
+      break;
+  }
+}
+
+Change *
+undo_layer(Diagram *dia, DiaLayer *layer, enum LayerChangeType type, int index)
+{
+  struct LayerChange *change;
+
+  change = g_new0(struct LayerChange, 1);
+
+  change->change.apply = (UndoApplyFunc) layer_change_apply;
+  change->change.revert = (UndoRevertFunc) layer_change_revert;
+  change->change.free = (UndoFreeFunc) layer_change_free;
+
+  change->type = type;
+  change->layer = layer;
+  change->index = index;
+  change->applied = 1;
+
+  undo_push_change(dia->undo, (Change *) change);
+  return (Change *)change;
+}
+
+void
+layer_visibility_change_apply(struct LayerVisibilityChange *change,
+                             Diagram *dia)
+{
+  GPtrArray *layers;
+  DiaLayer *layer = change->layer;
+  int visible = FALSE;
+  int i;
+
+  if (change->is_exclusive) {
+    /*  First determine if _any_ other layer widgets are set to visible.
+     *  If there is, exclusive switching turns all off.  */
+    for (i=0;i<dia->data->layers->len;i++) {
+      DiaLayer *temp_layer = g_ptr_array_index(dia->data->layers, i);
+      if (temp_layer != layer) {
+        visible |= dia_layer_is_visible (temp_layer);
+      }
+    }
+
+    /*  Now, toggle the visibility for all layers except the specified one  */
+    layers = dia->data->layers;
+    for (i = 0; i < layers->len; i++) {
+      DiaLayer *temp_layer = (DiaLayer *) g_ptr_array_index(layers, i);
+      if (temp_layer == layer) {
+        dia_layer_set_visible (temp_layer, TRUE);
+      } else {
+        dia_layer_set_visible (temp_layer, !visible);
+      }
+    }
+  } else {
+    dia_layer_set_visible (layer, !dia_layer_is_visible (layer));
+  }
+  diagram_add_update_all (dia);
+}
+
+/** Revert to the visibility before this change was applied.
+ */
+static void
+layer_visibility_change_revert(struct LayerVisibilityChange *change,
+                              Diagram *dia)
+{
+  GList *vis = change->original_visibility;
+  GPtrArray *layers = dia->data->layers;
+  int i;
+
+  for (i = 0; vis != NULL && i < layers->len; vis = g_list_next(vis), i++) {
+    DiaLayer *layer = DIA_LAYER (g_ptr_array_index (layers, i));
+    dia_layer_set_visible (layer, GPOINTER_TO_INT (vis->data));
+  }
+
+  if (vis != NULL || i < layers->len) {
+    printf("Internal error: visibility undo has %d visibilities, but %d layers\n",
+          g_list_length(change->original_visibility), layers->len);
+  }
+
+  diagram_add_update_all(dia);
+}
+
+static void
+layer_visibility_change_free(struct LayerVisibilityChange *change)
+{
+  g_list_free(change->original_visibility);
+}
+
+struct LayerVisibilityChange *
+undo_layer_visibility(Diagram *dia, DiaLayer *layer, gboolean exclusive)
+{
+  struct LayerVisibilityChange *change;
+  GList *visibilities = NULL;
+  int i;
+  GPtrArray *layers = dia->data->layers;
+
+  change = g_new0(struct LayerVisibilityChange, 1);
+
+  change->change.apply = (UndoApplyFunc) layer_visibility_change_apply;
+  change->change.revert = (UndoRevertFunc) layer_visibility_change_revert;
+  change->change.free = (UndoFreeFunc) layer_visibility_change_free;
+
+  for (i = 0; i < layers->len; i++) {
+    DiaLayer *temp_layer = DIA_LAYER (g_ptr_array_index (layers, i));
+    visibilities = g_list_append (visibilities, GINT_TO_POINTER (dia_layer_is_visible (temp_layer)));
+  }
+
+  change->original_visibility = visibilities;
+  change->layer = layer;
+  change->is_exclusive = exclusive;
+
+  undo_push_change(dia->undo, (Change *) change);
+  return change;
+}
+
+/*!
+ * \brief edit a layers name, possibly also creating the layer
+ */
+void
+diagram_edit_layer(Diagram *dia, DiaLayer *layer)
+{
+  g_return_if_fail(dia != NULL);
+
+  layer_dialog_edit_layer (layer ? NULL : dia, layer);
+}
diff --git a/app/layer-editor/layer_dialog.h b/app/layer-editor/layer_dialog.h
new file mode 100644
index 00000000..687acb20
--- /dev/null
+++ b/app/layer-editor/layer_dialog.h
@@ -0,0 +1,70 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "diagram.h"
+
+G_BEGIN_DECLS
+
+enum LayerChangeType {
+  TYPE_DELETE_LAYER,
+  TYPE_ADD_LAYER,
+  TYPE_RAISE_LAYER,
+  TYPE_LOWER_LAYER,
+};
+
+struct LayerChange {
+  Change change;
+
+  enum LayerChangeType type;
+  DiaLayer *layer;
+  int index;
+  int applied;
+};
+
+struct LayerVisibilityChange {
+  Change change;
+
+  GList *original_visibility;
+  DiaLayer *layer;
+  gboolean is_exclusive;
+  int applied;
+};
+
+Change                       *undo_layer                    (Diagram                      *dia,
+                                                             DiaLayer                     *layer,
+                                                             enum LayerChangeType         ,
+                                                             int                           index);
+struct LayerVisibilityChange *undo_layer_visibility         (Diagram                      *dia,
+                                                             DiaLayer                     *layer,
+                                                             gboolean                      exclusive);
+void                          layer_visibility_change_apply (struct LayerVisibilityChange *change,
+                                                             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);
+
+void diagram_edit_layer (Diagram *dia, DiaLayer *layer);
+
+G_END_DECLS
diff --git a/app/meson.build b/app/meson.build
index 14566bba..b0a94798 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -8,7 +8,18 @@ dia_sources = [
     'defaults.c',
     'undo.c',
     'object_ops.c',
-    'layer_dialog.c',
+
+    'layer-editor/dia-layer-widget.c',
+    'layer-editor/dia-layer-widget.h',
+    'layer-editor/dia-layer-editor.c',
+    'layer-editor/dia-layer-editor.h',
+    'layer-editor/dia-layer-editor-dialog.c',
+    'layer-editor/dia-layer-editor-dialog.h',
+    'layer-editor/dia-layer-properties.c',
+    'layer-editor/dia-layer-properties.h',
+    'layer-editor/layer_dialog.c',
+    'layer-editor/layer_dialog.h',
+
     'commands.c',
     'app_procs.c',
     'connectionpoint_ops.c',
diff --git a/app/recent_files.c b/app/recent_files.c
index d51c6e1f..c9a16f60 100644
--- a/app/recent_files.c
+++ b/app/recent_files.c
@@ -34,7 +34,7 @@
 #include "diagram.h"
 #include "display.h"
 #include "interface.h"
-#include "layer_dialog.h"
+#include "layer-editor/layer_dialog.h"
 #include "preferences.h"
 #include "../lib/filter.h"
 #include "../lib/intl.h"
diff --git a/lib/dia-layer.h b/lib/dia-layer.h
index 079689ba..7906a48d 100644
--- a/lib/dia-layer.h
+++ b/lib/dia-layer.h
@@ -23,6 +23,7 @@
 #include <glib.h>
 
 #include "diatypes.h"
+#include "diarenderer.h"
 
 #pragma once
 


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