[dia] layers: emit signals for changes to layers



commit 5a0a5dd141145de5b1b1b07611f38d5272529f0b
Author: Zander Brown <zbrown gnome org>
Date:   Wed Apr 22 10:08:30 2020 +0100

    layers: emit signals for changes to layers
    
    DiaList -> DiaLayerList with logic for tracking layer state incorporated

 app/layer-editor/dia-layer-editor.c               | 263 ++-------
 app/layer-editor/{dia-list.c => dia-layer-list.c} | 683 +++++++++++++---------
 app/layer-editor/dia-layer-list.h                 |  50 ++
 app/layer-editor/dia-layer-properties.c           |   2 +-
 app/layer-editor/dia-layer-widget.c               |  89 +--
 app/layer-editor/dia-layer-widget.h               |   3 +-
 app/layer-editor/dia-list.h                       |  70 ---
 app/load_save.c                                   |   6 +-
 app/meson.build                                   |   4 +-
 lib/diagramdata.c                                 | 284 ++++++---
 lib/diamarshal.list                               |   1 +
 lib/layer.c                                       |  14 +-
 plug-ins/drs/dia-render-script-import.c           |   6 +-
 plug-ins/pdf/pdf-import.cpp                       |   5 +-
 14 files changed, 754 insertions(+), 726 deletions(-)
---
diff --git a/app/layer-editor/dia-layer-editor.c b/app/layer-editor/dia-layer-editor.c
index 4cea78a6..c16700f8 100644
--- a/app/layer-editor/dia-layer-editor.c
+++ b/app/layer-editor/dia-layer-editor.c
@@ -23,11 +23,11 @@
 
 #include "intl.h"
 
+#include "dia-layer.h"
 #include "dia-layer-widget.h"
 #include "dia-layer-editor.h"
 #include "dia-layer-properties.h"
-#include "dia-layer.h"
-#include "dia-list.h"
+#include "dia-layer-list.h"
 #include "layer_dialog.h"
 
 typedef struct _ButtonData ButtonData;
@@ -155,51 +155,13 @@ list_button_press (GtkWidget      *widget,
 }
 
 
-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 (layer_row) != layer) {
-      connectable |= dia_layer_is_connectable (layer);
-    }
-  }
-
-  /*  Now, toggle the connectability for all layers except the specified one  */
-  list = gtk_container_get_children (GTK_CONTAINER (priv->list));
-  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;
+  DiaLayer *active;
   Diagram *dia;
-  DiaLayerWidget *selected;
-  GList *list = NULL;
-  GtkWidget *layer_widget;
   int pos;
   static int next_layer_num = 1;
 
@@ -208,38 +170,18 @@ new_layer (GtkWidget *widget, DiaLayerEditor *self)
   if (dia != NULL) {
     char* new_layer_name = g_strdup_printf (_("New layer %d"),
                                             next_layer_num++);
-    layer = dia_layer_new (new_layer_name, dia->data);
-
-    selected = dia_list_get_selected (DIA_LIST (priv->list));
-
-    g_return_if_fail (selected != NULL);
+    layer = dia_layer_new (new_layer_name, DIA_DIAGRAM_DATA (dia));
 
-    pos = dia_list_child_position (DIA_LIST (priv->list), selected);
+    active = dia_diagram_data_get_active_layer (DIA_DIAGRAM_DATA (dia));
+    pos = data_layer_get_index (DIA_DIAGRAM_DATA (dia), active);
 
-    data_add_layer_at (DIA_DIAGRAM_DATA (dia),
-                       layer,
-                       data_layer_count (DIA_DIAGRAM_DATA (dia)) - pos);
+    data_add_layer_at (DIA_DIAGRAM_DATA (dia), layer, pos + 1);
+    data_set_active_layer (DIA_DIAGRAM_DATA (dia), layer);
 
     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);
-
-    dia_list_insert_items (DIA_LIST (priv->list), list, pos);
-
-    dia_list_select_item (DIA_LIST (priv->list), pos);
-
-    dia_layer_change_new (dia,
-                          layer,
-                          TYPE_ADD_LAYER,
-                          data_layer_count (DIA_DIAGRAM_DATA (dia)) - pos);
+    dia_layer_change_new (dia, layer, TYPE_ADD_LAYER, pos + 1);
     undo_set_transactionpoint (dia->undo);
 
     g_clear_pointer (&new_layer_name, g_free);
@@ -248,112 +190,76 @@ new_layer (GtkWidget *widget, DiaLayerEditor *self)
 }
 
 
-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_diagram_data_get_active_layer (DIA_DIAGRAM_DATA (dia));
-
-  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;
-  DiaLayerWidget *selected;
   DiaLayer *layer;
   int pos;
 
   dia = priv->diagram;
 
-
-  if ((dia != NULL) && (data_layer_count (DIA_DIAGRAM_DATA (dia)) > 1)) {
-    selected = dia_list_get_selected (DIA_LIST (priv->list));
-
-    g_return_if_fail (selected != NULL);
-
+  if (dia != NULL) {
     layer = dia_diagram_data_get_active_layer (DIA_DIAGRAM_DATA (dia));
 
-    pos = dia_list_child_position (DIA_LIST (priv->list), selected);
-    gtk_container_remove (GTK_CONTAINER (priv->list), GTK_WIDGET (selected));
+    g_return_if_fail (layer);
 
-    dia_layer_change_new (dia, layer, TYPE_DELETE_LAYER,
-                          data_layer_count (DIA_DIAGRAM_DATA (dia)) - pos);
+    pos = data_layer_get_index (DIA_DIAGRAM_DATA (dia), layer);
+
+    dia_layer_change_new (dia, layer, TYPE_DELETE_LAYER, pos);
     undo_set_transactionpoint (dia->undo);
 
     data_remove_layer (dia->data, layer);
+
     diagram_add_update_all (dia);
     diagram_flush (dia);
-
-    if (--pos < 0) {
-      pos = 0;
-    }
-
-    dia_list_select_item (DIA_LIST (priv->list), pos);
   }
 }
 
 
 static void
-raise_layer (GtkWidget *widget, DiaLayerEditor *self)
+rename_layer (GtkWidget *widget, DiaLayerEditor *self)
 {
   DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
   DiaLayer *layer;
-  Diagram *dia;
-  DiaLayerWidget *selected;
-  GList *list = NULL;
-  int pos;
-
-  dia = priv->diagram;
-
-  if ((dia != NULL) && (data_layer_count (DIA_DIAGRAM_DATA (dia)) > 1)) {
-    selected = dia_list_get_selected (DIA_LIST (priv->list));
+  GtkWidget *dlg;
 
-    g_return_if_fail (selected != NULL);
+  if (priv->diagram == NULL) {
+    return;
+  }
 
-    pos = dia_list_child_position (DIA_LIST (priv->list), selected);
+  layer = dia_diagram_data_get_active_layer (DIA_DIAGRAM_DATA (priv->diagram));
 
-    if (pos > 0) {
-      layer = dia_layer_widget_get_layer (selected);
-      data_raise_layer (DIA_DIAGRAM_DATA (dia), layer);
+  dlg = g_object_new (DIA_TYPE_LAYER_PROPERTIES,
+                      "layer", layer,
+                      "visible", TRUE,
+                      NULL);
+  gtk_widget_show (dlg);
+}
 
-      list = g_list_prepend (list, selected);
 
-      g_object_ref (selected);
+static void
+raise_layer (GtkWidget *widget, DiaLayerEditor *self)
+{
+  DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
+  DiaLayer *layer;
+  Diagram *dia;
 
-      dia_list_remove_items (DIA_LIST (priv->list),
-                             list);
+  dia = priv->diagram;
 
-      dia_list_insert_items (DIA_LIST (priv->list),
-                             list, pos - 1);
+  if (dia != NULL) {
+    layer = dia_diagram_data_get_active_layer (DIA_DIAGRAM_DATA (dia));
 
-      g_clear_object (&selected);
+    g_return_if_fail (layer);
 
-      dia_list_select_item (DIA_LIST (priv->list), pos-1);
+    dia_layer_change_new (dia, layer, TYPE_RAISE_LAYER, 0);
+    undo_set_transactionpoint (dia->undo);
 
-      diagram_add_update_all (dia);
-      diagram_flush (dia);
+    data_raise_layer (DIA_DIAGRAM_DATA (dia), layer);
 
-      dia_layer_change_new (dia, layer, TYPE_RAISE_LAYER, 0);
-      undo_set_transactionpoint (dia->undo);
-    }
+    diagram_add_update_all (dia);
+    diagram_flush (dia);
   }
 }
 
@@ -364,43 +270,21 @@ lower_layer (GtkWidget *widget, DiaLayerEditor *self)
   DiaLayerEditorPrivate *priv = dia_layer_editor_get_instance_private (self);
   DiaLayer *layer;
   Diagram *dia;
-  DiaLayerWidget *selected;
-  GList *list = NULL;
-  int pos;
 
   dia = priv->diagram;
 
-  if ((dia != NULL) && (data_layer_count (DIA_DIAGRAM_DATA (dia)) > 1)) {
-    selected = dia_list_get_selected (DIA_LIST (priv->list));
-
-    g_return_if_fail (selected != NULL);
-
-    pos = dia_list_child_position (DIA_LIST (priv->list), selected);
-
-    if (pos < data_layer_count (DIA_DIAGRAM_DATA (dia)) - 1) {
-      layer = dia_layer_widget_get_layer (selected);
-      data_lower_layer (DIA_DIAGRAM_DATA (dia), layer);
-
-      list = g_list_prepend (list, selected);
-
-      g_object_ref (selected);
-
-      dia_list_remove_items (DIA_LIST (priv->list),
-                             list);
-
-      dia_list_insert_items (DIA_LIST (priv->list),
-                             list, pos + 1);
+  if (dia != NULL) {
+    layer = dia_diagram_data_get_active_layer (DIA_DIAGRAM_DATA (dia));
 
-      g_clear_object (&selected);
+    g_return_if_fail (layer);
 
-      dia_list_select_item (DIA_LIST (priv->list), pos+1);
+    dia_layer_change_new (dia, layer, TYPE_LOWER_LAYER, 0);
+    undo_set_transactionpoint (dia->undo);
 
-      diagram_add_update_all (dia);
-      diagram_flush (dia);
+    data_lower_layer (DIA_DIAGRAM_DATA (dia), layer);
 
-      dia_layer_change_new (dia, layer, TYPE_LOWER_LAYER, 0);
-      undo_set_transactionpoint (dia->undo);
-    }
+    diagram_add_update_all (dia);
+    diagram_flush (dia);
   }
 }
 
@@ -436,10 +320,11 @@ dia_layer_editor_init (DiaLayerEditor *self)
                                   GTK_POLICY_AUTOMATIC);
   gtk_box_pack_start (GTK_BOX (self), scrolled_win, TRUE, TRUE, 2);
 
-  priv->list = dia_list_new ();
+  priv->list = dia_layer_list_new ();
 
   gtk_widget_show (priv->list);
-  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), priv->list);
+  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)));
 
@@ -481,8 +366,7 @@ dia_layer_editor_init (DiaLayerEditor *self)
 GtkWidget *
 dia_layer_editor_new (void)
 {
-  return g_object_new (DIA_TYPE_LAYER_EDITOR,
-                       NULL);
+  return g_object_new (DIA_TYPE_LAYER_EDITOR, NULL);
 }
 
 
@@ -491,48 +375,19 @@ 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_get_active_layer (DIA_DIAGRAM_DATA (dia));
+  if (g_set_object (&priv->diagram, dia)) {
+    dia_layer_list_set_diagram (DIA_LAYER_LIST (priv->list),
+                                DIA_DIAGRAM_DATA (dia));
 
-  dia_list_clear_items (DIA_LIST (priv->list), 0, -1);
+    gtk_widget_set_sensitive (GTK_WIDGET (self), dia != NULL);
 
-  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;
-    }
+    g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_DIAGRAM]);
   }
-
-  dia_list_select_item (DIA_LIST (priv->list), sel_pos);
-
-  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_DIAGRAM]);
 }
 
 
diff --git a/app/layer-editor/dia-list.c b/app/layer-editor/dia-layer-list.c
similarity index 54%
rename from app/layer-editor/dia-list.c
rename to app/layer-editor/dia-layer-list.c
index e09a8075..5d77d232 100644
--- a/app/layer-editor/dia-list.c
+++ b/app/layer-editor/dia-layer-list.c
@@ -1,3 +1,25 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1999 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.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * © 2020 Zander Brown <zbrown gnome org>
+ */
+
 /* GTK - The GIMP Toolkit
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  *
@@ -28,15 +50,16 @@
 
 #include <gtk/gtk.h>
 
-#include "dia-list.h"
+#include "dia-layer-list.h"
 #include "dia-layer-widget.h"
 
 
-typedef struct _DiaListPrivate DiaListPrivate;
-struct _DiaListPrivate
-{
+typedef struct _DiaLayerListPrivate DiaLayerListPrivate;
+struct _DiaLayerListPrivate {
   GtkContainer container;
 
+  DiagramData *diagram;
+
   GList *children;
   DiaLayerWidget *selected;
 
@@ -44,24 +67,87 @@ struct _DiaListPrivate
 };
 
 
-G_DEFINE_TYPE_WITH_PRIVATE (DiaList, dia_list, GTK_TYPE_CONTAINER)
+G_DEFINE_TYPE_WITH_PRIVATE (DiaLayerList, dia_layer_list, GTK_TYPE_CONTAINER)
+
+
+enum {
+  PROP_0,
+  PROP_DIAGRAM,
+  LAST_PROP
+};
+static GParamSpec *pspecs[LAST_PROP] = { NULL, };
+
+
+
+static void            dia_layer_list_insert_items   (DiaLayerList        *self,
+                                                      GList               *items,
+                                                      int                  position);
+static void            dia_layer_list_remove_items   (DiaLayerList        *self,
+                                                      GList               *items);
+static void            dia_layer_list_select_item    (DiaLayerList        *self,
+                                                      int                  item);
+static void            dia_layer_list_select_child   (DiaLayerList        *self,
+                                                      DiaLayerWidget      *item);
+static void            dia_layer_list_unselect_child (DiaLayerList        *self,
+                                                      DiaLayerWidget      *item);
+
+static void
+dia_layer_list_finalize (GObject *object)
+{
+  DiaLayerList *list = DIA_LAYER_LIST (object);
+  DiaLayerListPrivate *priv = dia_layer_list_get_instance_private (list);
+
+  g_clear_pointer (&priv->children, g_list_free);
+  g_clear_object (&priv->selected);
+
+  G_OBJECT_CLASS (dia_layer_list_parent_class)->finalize (object);
+}
+
+
+static void
+dia_layer_list_set_property (GObject      *object,
+                             guint         property_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  DiaLayerList *self = DIA_LAYER_LIST (object);
+
+  switch (property_id) {
+    case PROP_DIAGRAM:
+      dia_layer_list_set_diagram (self, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
 
 
 static void
-dia_list_dispose (GObject *object)
+dia_layer_list_get_property (GObject    *object,
+                             guint       property_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
 {
-  dia_list_clear_items (DIA_LIST (object), 0, -1);
+  DiaLayerList *self = DIA_LAYER_LIST (object);
 
-  G_OBJECT_CLASS (dia_list_parent_class)->dispose (object);
+  switch (property_id) {
+    case PROP_DIAGRAM:
+      g_value_set_object (value, dia_layer_list_get_diagram (self));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
 }
 
 
 static void
-dia_list_size_request (GtkWidget      *widget,
-                       GtkRequisition *requisition)
+dia_layer_list_size_request (GtkWidget      *widget,
+                             GtkRequisition *requisition)
 {
-  DiaList *list = DIA_LIST (widget);
-  DiaListPrivate *priv = dia_list_get_instance_private (list);
+  DiaLayerList *list = DIA_LAYER_LIST (widget);
+  DiaLayerListPrivate *priv = dia_layer_list_get_instance_private (list);
   GtkWidget *child;
   GList *children;
   int border_width;
@@ -80,7 +166,7 @@ dia_list_size_request (GtkWidget      *widget,
       gtk_widget_size_request (child, &child_requisition);
 
       requisition->width = MAX (requisition->width,
-              child_requisition.width);
+                                child_requisition.width);
       requisition->height += child_requisition.height;
     }
   }
@@ -96,11 +182,11 @@ dia_list_size_request (GtkWidget      *widget,
 
 
 static void
-dia_list_size_allocate (GtkWidget     *widget,
-                        GtkAllocation *allocation)
+dia_layer_list_size_allocate (GtkWidget     *widget,
+                              GtkAllocation *allocation)
 {
-  DiaList *list = DIA_LIST (widget);
-  DiaListPrivate *priv = dia_list_get_instance_private (list);
+  DiaLayerList *list = DIA_LAYER_LIST (widget);
+  DiaLayerListPrivate *priv = dia_layer_list_get_instance_private (list);
   GtkWidget *child;
   GtkAllocation child_allocation;
   GList *children;
@@ -146,15 +232,15 @@ dia_list_size_allocate (GtkWidget     *widget,
 
 
 static void
-dia_list_realize (GtkWidget *widget)
+dia_layer_list_realize (GtkWidget *widget)
 {
   GtkAllocation alloc;
   GdkWindowAttr attributes;
   gint attributes_mask;
   GdkWindow *window;
   GtkStyle *style;
-  gtk_widget_set_realized (widget, TRUE);
 
+  gtk_widget_set_realized (widget, TRUE);
   gtk_widget_get_allocation (widget, &alloc);
 
   attributes.window_type = GDK_WINDOW_CHILD;
@@ -165,7 +251,7 @@ dia_list_realize (GtkWidget *widget)
   attributes.wclass = GDK_INPUT_OUTPUT;
   attributes.visual = gtk_widget_get_visual (widget);
   attributes.colormap = gtk_widget_get_colormap (widget);
-  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
 
   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
 
@@ -185,7 +271,7 @@ dia_list_realize (GtkWidget *widget)
 
 
 static void
-dia_list_unmap (GtkWidget *widget)
+dia_layer_list_unmap (GtkWidget *widget)
 {
   GdkWindow *window;
 
@@ -202,8 +288,8 @@ dia_list_unmap (GtkWidget *widget)
 
 
 static gboolean
-dia_list_button_press (GtkWidget      *widget,
-                       GdkEventButton *event)
+dia_layer_list_button_press (GtkWidget      *widget,
+                             GdkEventButton *event)
 {
   GtkWidget *item;
 
@@ -230,8 +316,8 @@ dia_list_button_press (GtkWidget      *widget,
 
 
 static void
-dia_list_style_set (GtkWidget *widget,
-                    GtkStyle  *previous_style)
+dia_layer_list_style_set (GtkWidget *widget,
+                          GtkStyle  *previous_style)
 {
   GtkStyle *style;
 
@@ -244,8 +330,8 @@ dia_list_style_set (GtkWidget *widget,
 
 
 static void
-dia_list_add (GtkContainer *container,
-              GtkWidget    *widget)
+dia_layer_list_add (GtkContainer *container,
+                    GtkWidget    *widget)
 {
   GList *item_list;
 
@@ -254,13 +340,13 @@ dia_list_add (GtkContainer *container,
   item_list = g_list_alloc ();
   item_list->data = widget;
 
-  dia_list_append_items (DIA_LIST (container), item_list);
+  dia_layer_list_insert_items (DIA_LAYER_LIST (container), item_list, -1);
 }
 
 
 static void
-dia_list_remove (GtkContainer *container,
-                 GtkWidget    *widget)
+dia_layer_list_remove (GtkContainer *container,
+                       GtkWidget    *widget)
 {
   GList *item_list;
 
@@ -269,20 +355,20 @@ dia_list_remove (GtkContainer *container,
   item_list = g_list_alloc ();
   item_list->data = widget;
 
-  dia_list_remove_items (DIA_LIST (container), item_list);
+  dia_layer_list_remove_items (DIA_LAYER_LIST (container), item_list);
 
   g_list_free (item_list);
 }
 
 
 static void
-dia_list_forall (GtkContainer  *container,
-                 gboolean       include_internals,
-                 GtkCallback    callback,
-                 gpointer       callback_data)
+dia_layer_list_forall (GtkContainer *container,
+                       gboolean      include_internals,
+                       GtkCallback   callback,
+                       gpointer      callback_data)
 {
-  DiaList *list = DIA_LIST (container);
-  DiaListPrivate *priv = dia_list_get_instance_private (list);
+  DiaLayerList *list = DIA_LAYER_LIST (container);
+  DiaLayerListPrivate *priv = dia_layer_list_get_instance_private (list);
   GtkWidget *child;
   GList *children;
 
@@ -298,28 +384,28 @@ dia_list_forall (GtkContainer  *container,
 
 
 static GType
-dia_list_child_type (GtkContainer *container)
+dia_layer_list_child_type (GtkContainer *container)
 {
   return DIA_TYPE_LAYER_WIDGET;
 }
 
 
 static void
-dia_list_set_focus_child (GtkContainer *container,
-                          GtkWidget    *child)
+dia_layer_list_set_focus_child (GtkContainer *container,
+                                GtkWidget    *child)
 {
-  DiaList *list;
+  DiaLayerList *list;
   GtkWidget *focus_child;
-  DiaListPrivate *priv;
+  DiaLayerListPrivate *priv;
 
-  g_return_if_fail (DIA_IS_LIST (container));
+  g_return_if_fail (DIA_IS_LAYER_LIST (container));
 
   if (child) {
     g_return_if_fail (GTK_IS_WIDGET (child));
   }
 
-  list = DIA_LIST (container);
-  priv = dia_list_get_instance_private (list);
+  list = DIA_LAYER_LIST (container);
+  priv = dia_layer_list_get_instance_private (list);
 
   focus_child = gtk_container_get_focus_child (container);
 
@@ -328,7 +414,7 @@ dia_list_set_focus_child (GtkContainer *container,
       priv->last_focus_child = focus_child;
       g_clear_object (&focus_child);
     }
-    GTK_CONTAINER_CLASS (dia_list_parent_class)->set_focus_child (container, child);
+    GTK_CONTAINER_CLASS (dia_layer_list_parent_class)->set_focus_child (container, child);
     if (child) {
       g_object_ref (child);
     }
@@ -350,23 +436,23 @@ dia_list_set_focus_child (GtkContainer *container,
                                  alloc.height));
     }
 
-    dia_list_select_child (list, DIA_LAYER_WIDGET (child));
+    dia_layer_list_select_child (list, DIA_LAYER_WIDGET (child));
   }
 }
 
 
 static gboolean
-dia_list_focus (GtkWidget        *widget,
-                GtkDirectionType  direction)
+dia_layer_list_focus (GtkWidget        *widget,
+                      GtkDirectionType  direction)
 {
   gint return_val = FALSE;
   GtkContainer *container;
   GtkWidget *focus_child;
-  DiaListPrivate *priv;
+  DiaLayerListPrivate *priv;
 
-  g_return_val_if_fail (DIA_IS_LIST (widget), FALSE);
+  g_return_val_if_fail (DIA_IS_LAYER_LIST (widget), FALSE);
 
-  priv = dia_list_get_instance_private (DIA_LIST (widget));
+  priv = dia_layer_list_get_instance_private (DIA_LAYER_LIST (widget));
 
   container = GTK_CONTAINER (widget);
   focus_child = gtk_container_get_focus_child (container);
@@ -376,8 +462,8 @@ dia_list_focus (GtkWidget        *widget,
       gtk_container_set_focus_child (container, priv->last_focus_child);
     }
 
-    if (GTK_WIDGET_CLASS (dia_list_parent_class)->focus) {
-      return_val = GTK_WIDGET_CLASS (dia_list_parent_class)->focus (widget,
+    if (GTK_WIDGET_CLASS (dia_layer_list_parent_class)->focus) {
+      return_val = GTK_WIDGET_CLASS (dia_layer_list_parent_class)->focus (widget,
                                                                         direction);
     }
   }
@@ -395,46 +481,229 @@ dia_list_focus (GtkWidget        *widget,
 
 
 static void
-dia_list_class_init (DiaListClass *klass)
+dia_layer_list_class_init (DiaLayerListClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
 
-  object_class->dispose = dia_list_dispose;
-
-  widget_class->unmap = dia_list_unmap;
-  widget_class->style_set = dia_list_style_set;
-  widget_class->realize = dia_list_realize;
-  widget_class->button_press_event = dia_list_button_press;
-  widget_class->size_request = dia_list_size_request;
-  widget_class->size_allocate = dia_list_size_allocate;
-  widget_class->focus = dia_list_focus;
-
-  container_class->add = dia_list_add;
-  container_class->remove = dia_list_remove;
-  container_class->forall = dia_list_forall;
-  container_class->child_type = dia_list_child_type;
-  container_class->set_focus_child = dia_list_set_focus_child;
+  object_class->finalize = dia_layer_list_finalize;
+  object_class->get_property = dia_layer_list_get_property;
+  object_class->set_property = dia_layer_list_set_property;
+
+  widget_class->unmap = dia_layer_list_unmap;
+  widget_class->style_set = dia_layer_list_style_set;
+  widget_class->realize = dia_layer_list_realize;
+  widget_class->button_press_event = dia_layer_list_button_press;
+  widget_class->size_request = dia_layer_list_size_request;
+  widget_class->size_allocate = dia_layer_list_size_allocate;
+  widget_class->focus = dia_layer_list_focus;
+
+  container_class->add = dia_layer_list_add;
+  container_class->remove = dia_layer_list_remove;
+  container_class->forall = dia_layer_list_forall;
+  container_class->child_type = dia_layer_list_child_type;
+  container_class->set_focus_child = dia_layer_list_set_focus_child;
+
+  /**
+   * DiaLayerList:diagram:
+   *
+   * Since: 0.98
+   */
+  pspecs[PROP_DIAGRAM] =
+    g_param_spec_object ("diagram",
+                         "Diagram",
+                         "The current diagram",
+                         DIA_TYPE_DIAGRAM_DATA,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (object_class, LAST_PROP, pspecs);
 }
 
 
 static void
-dia_list_init (DiaList *list)
+dia_layer_list_init (DiaLayerList *list)
 {
-  DiaListPrivate *priv = dia_list_get_instance_private (list);
+}
 
-  priv->children = NULL;
-  priv->selected = NULL;
 
-  priv->last_focus_child = NULL;
+GtkWidget *
+dia_layer_list_new (void)
+{
+  return g_object_new (DIA_TYPE_LAYER_LIST, NULL);
 }
 
 
-GtkWidget *
-dia_list_new (void)
+static void
+exclusive_connectable (DiaLayerWidget *layer_row,
+                       DiaLayerList   *self)
 {
-  return g_object_new (DIA_TYPE_LIST, NULL);
+  DiaLayerListPrivate *priv = dia_layer_list_get_instance_private (self);
+  GList *list;
+  DiaLayerWidget *lw;
+  int connectable = FALSE;
+
+  /*  First determine if _any_ other layer widgets are set to connectable  */
+  DIA_FOR_LAYER_IN_DIAGRAM (priv->diagram, layer, i, {
+    if (dia_layer_widget_get_layer (layer_row) != layer) {
+      connectable |= dia_layer_is_connectable (layer);
+    }
+  });
+
+  /*  Now, toggle the connectability for all layers except the specified one  */
+  list = priv->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
+layers_changed (DiagramData  *diagram,
+                guint         pos,
+                guint         removed,
+                guint         added,
+                DiaLayerList *self)
+{
+  DiaLayerListPrivate *priv;
+  GtkWidget *widget;
+  DiaLayer *layer;
+  GList *list = NULL;
+
+  g_return_if_fail (DIA_IS_LAYER_LIST (self));
+
+  priv = dia_layer_list_get_instance_private (self);
+
+  for (int i = 0; i < removed; i++) {
+    GList *children = priv->children;
+    children = g_list_nth (children, pos + i);
+
+    if (children->data) {
+      list = g_list_append (list, children->data);
+    }
+  }
+
+  dia_layer_list_remove_items (self, list);
+
+  list = NULL;
+
+  for (int i = 0; i < added; i++) {
+    layer = data_layer_get_nth (diagram, pos + i);
+    widget = dia_layer_widget_new (layer);
+    g_signal_connect (widget,
+                      "exclusive",
+                      G_CALLBACK (exclusive_connectable),
+                      self);
+    gtk_widget_show (widget);
+    list = g_list_append (list, widget);
+  }
+
+  dia_layer_list_insert_items (self, list, pos);
+}
+
+
+static void
+active_changed (DiagramData  *diagram,
+                GParamSpec   *pspec,
+                DiaLayerList *self)
+{
+  DiaLayer *active = dia_diagram_data_get_active_layer (diagram);
+  guint pos = data_layer_get_index (diagram, active);
+
+  dia_layer_list_select_item (self, pos);
+}
+
+
+void
+dia_layer_list_set_diagram (DiaLayerList *self,
+                            DiagramData  *diagram)
+{
+  DiaLayerListPrivate *priv;
+  GtkWidget *layer_widget;
+  DiagramData *old = NULL;
+
+  g_return_if_fail (DIA_IS_LAYER_LIST (self));
+
+  priv = dia_layer_list_get_instance_private (self);
+
+  if (priv->diagram) {
+    old = g_object_ref (priv->diagram);
+  }
+
+  if (g_set_object (&priv->diagram, diagram)) {
+    gtk_container_foreach (GTK_CONTAINER (self),
+                           (GtkCallback) gtk_widget_destroy,
+                           NULL);
+
+    if (old) {
+      g_object_disconnect (old,
+                           "any-signal::layers-changed",
+                           G_CALLBACK (layers_changed),
+                           self,
+                           "any-signal::notify::active-layer",
+                           G_CALLBACK (active_changed),
+                           self,
+                           NULL);
+
+      g_clear_object (&old);
+    }
+
+    if (diagram == NULL) {
+      gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+
+      g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_DIAGRAM]);
+
+      return;
+    }
+
+    gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
+
+    DIA_FOR_LAYER_IN_DIAGRAM (diagram, layer, i, {
+      layer_widget = dia_layer_widget_new (layer);
+      g_signal_connect (layer_widget,
+                        "exclusive",
+                        G_CALLBACK (exclusive_connectable),
+                        self);
+      gtk_widget_show (layer_widget);
+
+      gtk_container_add (GTK_CONTAINER (self),
+                         layer_widget);
+    });
+
+    g_object_connect (diagram,
+                      "signal::layers-changed",
+                      G_CALLBACK (layers_changed),
+                      self,
+                      "signal::notify::active-layer",
+                      G_CALLBACK (active_changed),
+                      self,
+                      NULL);
+
+    g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_DIAGRAM]);
+  }
+
+  g_clear_object (&old);
+}
+
+
+DiagramData *
+dia_layer_list_get_diagram (DiaLayerList *self)
+{
+  DiaLayerListPrivate *priv;
+
+  g_return_val_if_fail (DIA_IS_LAYER_LIST (self), NULL);
+
+  priv = dia_layer_list_get_instance_private (self);
+
+  return priv->diagram;
 }
 
 
@@ -442,10 +711,10 @@ static void
 scroll_vertical (DiaLayerWidget *list_item,
                  GtkScrollType   scroll_type,
                  double          position,
-                 DiaList        *list)
+                 DiaLayerList   *list)
 {
   GtkContainer *container;
-  DiaListPrivate *priv;
+  DiaLayerListPrivate *priv;
   GList *work;
   GtkWidget *item;
   GtkAdjustment *adj;
@@ -453,9 +722,9 @@ scroll_vertical (DiaLayerWidget *list_item,
   GtkAllocation alloc;
   gint new_value;
 
-  g_return_if_fail (DIA_IS_LIST (list));
+  g_return_if_fail (DIA_IS_LAYER_LIST (list));
 
-  priv = dia_list_get_instance_private (list);
+  priv = dia_layer_list_get_instance_private (list);
 
   container = GTK_CONTAINER (list);
   focus_child = gtk_container_get_focus_child (container);
@@ -637,18 +906,18 @@ scroll_vertical (DiaLayerWidget *list_item,
 }
 
 
-void
-dia_list_insert_items (DiaList *list,
-                       GList   *items,
-                       int      position)
+static void
+dia_layer_list_insert_items (DiaLayerList *list,
+                             GList        *items,
+                             int           position)
 {
   GtkWidget *widget;
-  DiaListPrivate *priv;
+  DiaLayerListPrivate *priv;
   GList *tmp_list;
   GList *last;
   int nchildren;
 
-  g_return_if_fail (DIA_IS_LIST (list));
+  g_return_if_fail (DIA_IS_LAYER_LIST (list));
 
   if (!items) {
     return;
@@ -667,7 +936,7 @@ dia_list_insert_items (DiaList *list,
                       list);
   }
 
-  priv = dia_list_get_instance_private (list);
+  priv = dia_layer_list_get_instance_private (list);
 
   nchildren = g_list_length (priv->children);
   if ((position < 0) || (position > nchildren))
@@ -698,38 +967,22 @@ dia_list_insert_items (DiaList *list,
   }
 
   if (priv->children && !priv->selected) {
-    widget = priv->children->data;
-    dia_list_select_child (list, DIA_LAYER_WIDGET (widget));
-  }
-}
-
-
-void
-dia_list_append_items (DiaList *list,
-                       GList   *items)
-{
-  g_return_if_fail (DIA_IS_LIST (list));
-
-  dia_list_insert_items (list, items, -1);
-}
+    DiaLayer *active = dia_diagram_data_get_active_layer (priv->diagram);
 
+    dia_layer_list_select_item (list,
+                                data_layer_get_index (priv->diagram, active));
+  }
 
-void
-dia_list_prepend_items (DiaList *list,
-                        GList   *items)
-{
-  g_return_if_fail (DIA_IS_LIST (list));
-
-  dia_list_insert_items (list, items, 0);
+  gtk_widget_queue_resize (GTK_WIDGET (list));
 }
 
 
-void
-dia_list_remove_items (DiaList *list,
-                       GList   *items)
+static void
+dia_layer_list_remove_items (DiaLayerList *list,
+                             GList        *items)
 {
   GtkWidget *widget;
-  DiaListPrivate *priv;
+  DiaLayerListPrivate *priv;
   GtkWidget *new_focus_child;
   GtkWidget *old_focus_child;
   GtkWidget *focus_child;
@@ -738,9 +991,9 @@ dia_list_remove_items (DiaList *list,
   GList *work;
   gboolean grab_focus = FALSE;
 
-  g_return_if_fail (DIA_IS_LIST (list));
+  g_return_if_fail (DIA_IS_LAYER_LIST (list));
 
-  priv = dia_list_get_instance_private (list);
+  priv = dia_layer_list_get_instance_private (list);
 
   if (!items) {
     return;
@@ -755,7 +1008,7 @@ dia_list_remove_items (DiaList *list,
     tmp_list = tmp_list->next;
 
     if (gtk_widget_get_state (widget) == GTK_STATE_SELECTED) {
-      dia_list_unselect_child (list, DIA_LAYER_WIDGET (widget));
+      dia_layer_list_unselect_child (list, DIA_LAYER_WIDGET (widget));
     }
   }
 
@@ -811,7 +1064,7 @@ dia_list_remove_items (DiaList *list,
 
     if (!priv->selected) {
       priv->last_focus_child = new_focus_child;
-      dia_list_select_child (list, DIA_LAYER_WIDGET (new_focus_child));
+      dia_layer_list_select_child (list, DIA_LAYER_WIDGET (new_focus_child));
     }
   }
 
@@ -821,145 +1074,35 @@ dia_list_remove_items (DiaList *list,
 }
 
 
-void
-dia_list_clear_items (DiaList *list,
-                      int         start,
-                      int         end)
-{
-  GtkContainer *container;
-  GtkWidget *widget;
-  DiaListPrivate *priv;
-  GtkWidget *new_focus_child = NULL;
-  GtkWidget *focus_child;
-  GList *start_list;
-  GList *end_list;
-  GList *tmp_list;
-  guint nchildren;
-  gboolean grab_focus = FALSE;
-
-  g_return_if_fail (DIA_IS_LIST (list));
-
-  priv = dia_list_get_instance_private (list);
-
-  nchildren = g_list_length (priv->children);
-
-  if (nchildren == 0) {
-    return;
-  }
-
-  if ((end < 0) || (end > nchildren)) {
-    end = nchildren;
-  }
-
-  if (start >= end) {
-    return;
-  }
-
-  container = GTK_CONTAINER (list);
-
-  start_list = g_list_nth (priv->children, start);
-  end_list = g_list_nth (priv->children, end);
-
-  if (start_list->prev) {
-    start_list->prev->next = end_list;
-  }
-  if (end_list && end_list->prev) {
-    end_list->prev->next = NULL;
-  }
-  if (end_list) {
-    end_list->prev = start_list->prev;
-  }
-  if (start_list == priv->children) {
-    priv->children = end_list;
-  }
-
-  focus_child = gtk_container_get_focus_child (container);
-
-  if (focus_child) {
-    if (g_list_find (start_list, focus_child)) {
-      if (start_list->prev) {
-        new_focus_child = start_list->prev->data;
-      } else if (priv->children) {
-        new_focus_child = priv->children->data;
-      }
-
-      if (gtk_widget_has_focus (focus_child)) {
-        grab_focus = TRUE;
-      }
-    }
-  }
-
-  tmp_list = start_list;
-  while (tmp_list) {
-    widget = tmp_list->data;
-    tmp_list = tmp_list->next;
-
-    g_object_ref (widget);
-
-    if (gtk_widget_get_state (widget) == GTK_STATE_SELECTED) {
-      dia_list_unselect_child (list, DIA_LAYER_WIDGET (widget));
-    }
-
-    g_signal_handlers_disconnect_by_data (widget, list);
-    gtk_widget_unparent (widget);
-
-    if (widget == priv->last_focus_child) {
-      priv->last_focus_child = NULL;
-    }
-
-    g_clear_object (&widget);
-  }
-
-  g_list_free (start_list);
-
-  if (new_focus_child) {
-    if (grab_focus) {
-      gtk_widget_grab_focus (new_focus_child);
-    } else if (focus_child) {
-      gtk_container_set_focus_child (container, new_focus_child);
-    }
-
-    if (!priv->selected) {
-      priv->last_focus_child = new_focus_child;
-      dia_list_select_child (list, DIA_LAYER_WIDGET (new_focus_child));
-    }
-  }
-
-  if (gtk_widget_get_visible (GTK_WIDGET (list))) {
-    gtk_widget_queue_resize (GTK_WIDGET (list));
-  }
-}
-
-
-void
-dia_list_select_item (DiaList *list,
-                      int      item)
+static void
+dia_layer_list_select_item (DiaLayerList *list,
+                            int           item)
 {
   GList *tmp_list;
-  DiaListPrivate *priv;
+  DiaLayerListPrivate *priv;
 
-  g_return_if_fail (DIA_IS_LIST (list));
+  g_return_if_fail (DIA_IS_LAYER_LIST (list));
 
-  priv = dia_list_get_instance_private (list);
+  priv = dia_layer_list_get_instance_private (list);
 
   tmp_list = g_list_nth (priv->children, item);
   if (tmp_list) {
-    dia_list_select_child (list, tmp_list->data);
+    dia_layer_list_select_child (list, tmp_list->data);
   }
 }
 
 
-void
-dia_list_select_child (DiaList        *self,
-                       DiaLayerWidget *item)
+static void
+dia_layer_list_select_child (DiaLayerList   *self,
+                             DiaLayerWidget *item)
 {
-  DiaListPrivate *priv;
+  DiaLayerListPrivate *priv;
   DiaLayerWidget *old = NULL;
 
-  g_return_if_fail (DIA_IS_LIST (self));
+  g_return_if_fail (DIA_IS_LAYER_LIST (self));
   g_return_if_fail (DIA_IS_LAYER_WIDGET (item));
 
-  priv = dia_list_get_instance_private (self);
+  priv = dia_layer_list_get_instance_private (self);
 
   if (priv->selected) {
     old = g_object_ref (priv->selected);
@@ -979,64 +1122,22 @@ dia_list_select_child (DiaList        *self,
 }
 
 
-void
-dia_list_unselect_child (DiaList        *self,
-                         DiaLayerWidget *item)
+static void
+dia_layer_list_unselect_child (DiaLayerList   *self,
+                               DiaLayerWidget *item)
 {
-  DiaListPrivate *priv;
+  DiaLayerListPrivate *priv;
 
-  g_return_if_fail (DIA_IS_LIST (self));
+  g_return_if_fail (DIA_IS_LAYER_LIST (self));
   g_return_if_fail (DIA_IS_LAYER_WIDGET (item));
 
-  priv = dia_list_get_instance_private (self);
+  priv = dia_layer_list_get_instance_private (self);
 
   g_return_if_fail (priv->selected == item);
 
   gtk_widget_set_state (GTK_WIDGET (priv->selected), GTK_STATE_NORMAL);
 
-  g_clear_object (&priv->selected);
-
-  dia_layer_widget_deselect (item);
-}
-
-
-int
-dia_list_child_position (DiaList        *self,
-                         DiaLayerWidget *item)
-{
-  DiaListPrivate *priv;
-  GList *children;
-  int pos;
-
-  g_return_val_if_fail (DIA_IS_LIST (self), -1);
-  g_return_val_if_fail (DIA_IS_LAYER_WIDGET (item), -1);
-
-  priv = dia_list_get_instance_private (self);
+  dia_layer_widget_deselect (priv->selected);
 
-  pos = 0;
-  children = priv->children;
-
-  while (children) {
-    if (item == children->data) {
-      return pos;
-    }
-
-    pos += 1;
-    children = children->next;
-  }
-
-  return -1;
-}
-
-
-DiaLayerWidget *
-dia_list_get_selected (DiaList *self)
-{
-  DiaListPrivate *priv;
-
-  g_return_val_if_fail (DIA_IS_LIST (self), NULL);
-
-  priv = dia_list_get_instance_private (self);
-
-  return priv->selected;
+  g_clear_object (&priv->selected);
 }
diff --git a/app/layer-editor/dia-layer-list.h b/app/layer-editor/dia-layer-list.h
new file mode 100644
index 00000000..33411944
--- /dev/null
+++ b/app/layer-editor/dia-layer-list.h
@@ -0,0 +1,50 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1999 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.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * © 2020 Zander Brown <zbrown gnome org>
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "diagramdata.h"
+#include "dia-layer-widget.h"
+
+G_BEGIN_DECLS
+
+#define DIA_TYPE_LAYER_LIST dia_layer_list_get_type ()
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (GtkContainer, g_object_unref)
+
+G_DECLARE_DERIVABLE_TYPE (DiaLayerList, dia_layer_list, DIA, LAYER_LIST, GtkContainer)
+
+
+struct _DiaLayerListClass {
+  GtkContainerClass parent_class;
+};
+
+
+GtkWidget   *dia_layer_list_new         (void);
+void         dia_layer_list_set_diagram (DiaLayerList *self,
+                                         DiagramData  *diagram);
+DiagramData *dia_layer_list_get_diagram (DiaLayerList *self);
+
+
+G_END_DECLS
diff --git a/app/layer-editor/dia-layer-properties.c b/app/layer-editor/dia-layer-properties.c
index 93a2358d..baa711b5 100644
--- a/app/layer-editor/dia-layer-properties.c
+++ b/app/layer-editor/dia-layer-properties.c
@@ -136,7 +136,7 @@ dia_layer_properties_response (GtkDialog *dialog,
   } else if (priv->diagram) {
     DiaLayer *layer;
     int pos = data_layer_get_index (DIA_DIAGRAM_DATA (priv->diagram),
-                                    dia_diagram_data_get_active_layer (DIA_DIAGRAM_DATA (priv->diagram)) + 
1);
+                                    dia_diagram_data_get_active_layer (DIA_DIAGRAM_DATA (priv->diagram))) + 
1;
 
     layer = dia_layer_new (gtk_entry_get_text (GTK_ENTRY (priv->entry)),
                            DIA_DIAGRAM_DATA (priv->diagram));
diff --git a/app/layer-editor/dia-layer-widget.c b/app/layer-editor/dia-layer-widget.c
index 62870958..cebaec2e 100644
--- a/app/layer-editor/dia-layer-widget.c
+++ b/app/layer-editor/dia-layer-widget.c
@@ -34,8 +34,7 @@
  */
 
 typedef struct _DiaLayerWidgetPrivate DiaLayerWidgetPrivate;
-struct _DiaLayerWidgetPrivate
-{
+struct _DiaLayerWidgetPrivate {
   DiaLayer *layer;
 
   GBinding *name_binding;
@@ -53,8 +52,6 @@ struct _DiaLayerWidgetPrivate
    */
   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.
    *
@@ -68,22 +65,21 @@ struct _DiaLayerWidgetPrivate
 
 G_DEFINE_TYPE_WITH_PRIVATE (DiaLayerWidget, dia_layer_widget, GTK_TYPE_BIN)
 
+
 enum {
   EXCLUSIVE,
   SCROLL_VERTICAL,
   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, };
 
 
@@ -99,9 +95,6 @@ dia_layer_widget_set_property (GObject      *object,
     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;
@@ -124,9 +117,6 @@ dia_layer_widget_get_property (GObject    *object,
     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;
@@ -144,7 +134,6 @@ dia_layer_widget_finalize (GObject *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);
 }
@@ -374,20 +363,6 @@ dia_layer_widget_class_init (DiaLayerWidgetClass *klass)
                          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:
    *
@@ -494,7 +469,6 @@ connectable_toggled (GtkToggleButton *widget,
                                gtk_toggle_button_get_active (widget));
   }
 
-
   if (priv->layer == dia_diagram_data_get_active_layer (dia_layer_get_parent_diagram (priv->layer))) {
     priv->connect_off = !gtk_toggle_button_get_active (widget);
     if (priv->connect_off) {
@@ -519,7 +493,7 @@ connectable_toggled (GtkToggleButton *widget,
 
 
 static void
-visible_clicked (GtkToggleButton *widget,
+visible_toggled (GtkToggleButton *widget,
                  gpointer         userdata)
 {
   DiaLayerWidget *self = DIA_LAYER_WIDGET (userdata);
@@ -527,7 +501,7 @@ visible_clicked (GtkToggleButton *widget,
   DiaChange *change;
 
   /* Have to use this internal_call hack 'cause there's no way to switch
-   * a toggle button without causing the 'clicked' event:(
+   * a toggle button without causing the 'toggled' event:(
    */
   if (!priv->internal_call) {
     Diagram *dia = DIA_DIAGRAM (dia_layer_get_parent_diagram (priv->layer));
@@ -561,8 +535,6 @@ dia_layer_widget_init (DiaLayerWidget *self)
   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),
@@ -572,8 +544,8 @@ dia_layer_widget_init (DiaLayerWidget *self)
                     G_CALLBACK (button_event),
                     self);
   g_signal_connect (G_OBJECT (priv->visible),
-                    "clicked",
-                    G_CALLBACK (visible_clicked),
+                    "toggled",
+                    G_CALLBACK (visible_toggled),
                     self);
   gtk_box_pack_start (GTK_BOX (hbox), priv->visible, FALSE, TRUE, 2);
   gtk_widget_show (priv->visible);
@@ -591,7 +563,7 @@ dia_layer_widget_init (DiaLayerWidget *self)
                     G_CALLBACK (button_event),
                     self);
   g_signal_connect (G_OBJECT (priv->connectable),
-                    "clicked",
+                    "toggled",
                     G_CALLBACK (connectable_toggled),
                     self);
 
@@ -619,15 +591,9 @@ dia_layer_widget_set_layer (DiaLayerWidget *self,
 
   priv = dia_layer_widget_get_instance_private (self);
 
-  g_clear_object (&priv->layer);
-  if (layer) {
-    priv->layer = g_object_ref (layer);
-
   if (g_set_object (&priv->layer, layer)) {
     g_clear_object (&priv->name_binding);
 
-    g_message (" -> accepted %p", priv->layer);
-
     if (!layer) {
       gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
 
@@ -676,38 +642,6 @@ dia_layer_widget_get_layer (DiaLayerWidget *self)
 }
 
 
-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)
 {
@@ -737,12 +671,9 @@ dia_layer_widget_get_connectable (DiaLayerWidget *self)
 
 
 GtkWidget *
-dia_layer_widget_new (DiaLayer *layer, DiaLayerEditor *editor)
+dia_layer_widget_new (DiaLayer *layer)
 {
-  return g_object_new (DIA_TYPE_LAYER_WIDGET,
-                       "layer", layer,
-                       "editor", editor,
-                       NULL);
+  return g_object_new (DIA_TYPE_LAYER_WIDGET, "layer", layer, NULL);
 }
 
 
diff --git a/app/layer-editor/dia-layer-widget.h b/app/layer-editor/dia-layer-widget.h
index 378d346e..a5189bb3 100644
--- a/app/layer-editor/dia-layer-widget.h
+++ b/app/layer-editor/dia-layer-widget.h
@@ -35,8 +35,7 @@ struct _DiaLayerWidgetClass {
   GtkBinClass parent_class;
 };
 
-GtkWidget      *dia_layer_widget_new             (DiaLayer       *layer,
-                                                  DiaLayerEditor *editor);
+GtkWidget      *dia_layer_widget_new             (DiaLayer       *layer);
 void            dia_layer_widget_set_layer       (DiaLayerWidget *self,
                                                   DiaLayer       *layer);
 DiaLayer       *dia_layer_widget_get_layer       (DiaLayerWidget *self);
diff --git a/app/load_save.c b/app/load_save.c
index a9c321e4..4ec329db 100644
--- a/app/load_save.c
+++ b/app/load_save.c
@@ -445,8 +445,8 @@ diagram_data_load (const char  *filename,
     return FALSE;
   }
 
-  namespace = xmlSearchNs (doc, root, "dia");
-  if (xmlStrcmp (root->name, "diagram") || (namespace == NULL)) {
+  namespace = xmlSearchNs (doc, root, (const xmlChar *) "dia");
+  if (xmlStrcmp (root->name, (const xmlChar *) "diagram") || (namespace == NULL)) {
     message_error (_("Error loading diagram %s.\nNot a Dia file."),
                    dia_message_filename (filename));
     xmlFreeDoc (doc);
@@ -712,7 +712,7 @@ diagram_data_load (const char  *filename,
 
     if (!layer_node) break;
 
-    name = xmlGetProp (layer_node, "name");
+    name = xmlGetProp (layer_node, (const xmlChar *) "name");
     if (!name) break; /* name is mandatory */
 
     layer = dia_layer_new ((char *) name, data);
diff --git a/app/meson.build b/app/meson.build
index 083eb137..565335d3 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -11,8 +11,8 @@ dia_sources = [
     'dia-change.h',
     'object_ops.c',
 
-    'layer-editor/dia-list.c',
-    'layer-editor/dia-list.h',
+    'layer-editor/dia-layer-list.c',
+    'layer-editor/dia-layer-list.h',
     'layer-editor/dia-layer-widget.c',
     'layer-editor/dia-layer-widget.h',
     'layer-editor/dia-layer-editor.c',
diff --git a/lib/diagramdata.c b/lib/diagramdata.c
index 0ee321dc..e02e4543 100644
--- a/lib/diagramdata.c
+++ b/lib/diagramdata.c
@@ -16,7 +16,10 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-/** \file diagramdata.c  This file defines the DiagramData object, which holds (mostly) saveable
+/**
+ * SECTION:diagramdata:
+ *
+ * This file defines the #DiagramData object, which holds (mostly) saveable
  * data global to a diagram.
  */
 
@@ -38,27 +41,35 @@
 
 static const DiaRectangle invalid_extents = { -1.0,-1.0,-1.0,-1.0 };
 
-static void diagram_data_class_init (DiagramDataClass *klass);
+static void dia_diagram_data_class_init (DiagramDataClass *klass);
 static void diagram_data_init (DiagramData *object);
 
+typedef struct {
+  DiaObject *obj;
+  DiaHighlightType type;
+} ObjectHighlight;
+
+
+enum {
+  PROP_0,
+  PROP_ACTIVE_LAYER,
+  LAST_PROP
+};
+static GParamSpec *pspecs[LAST_PROP] = { NULL, };
+
+
 enum {
   OBJECT_ADD,
   OBJECT_REMOVE,
   SELECTION_CHANGED,
+  LAYERS_CHANGED,
   LAST_SIGNAL
 };
-
-typedef struct {
-  DiaObject *obj;
-  DiaHighlightType type;
-} ObjectHighlight;
-
-static guint diagram_data_signals[LAST_SIGNAL] = { 0, };
+static guint signals[LAST_SIGNAL] = { 0, };
 
 static gpointer parent_class = NULL;
 
-/** Get the type object for the DiagramData class.
- */
+
 GType
 diagram_data_get_type(void)
 {
@@ -71,7 +82,7 @@ diagram_data_get_type(void)
         sizeof (DiagramDataClass),
         (GBaseInitFunc) NULL,
         (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) diagram_data_class_init,
+        (GClassInitFunc) dia_diagram_data_class_init,
         NULL,           /* class_finalize */
         NULL,           /* class_data */
         sizeof (DiagramData),
@@ -107,9 +118,7 @@ _diagram_data_selection_changed (DiagramData* dia, int n)
 {
 }
 
-/** Initialize a new diagram data object.
- * @param data A diagram data object to initialize.
- */
+
 static void
 diagram_data_init(DiagramData *data)
 {
@@ -146,9 +155,18 @@ diagram_data_init(DiagramData *data)
 }
 
 
-/** Deallocate memory owned by a DiagramData object.
- * @param object A DiagramData object to finalize.
- */
+static void
+active_layer_died (gpointer  data,
+                   GObject  *dead_object)
+{
+  DiagramData *self = DIA_DIAGRAM_DATA (data);
+
+  self->active_layer = NULL;
+
+  g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_ACTIVE_LAYER]);
+}
+
+
 static void
 diagram_data_finalize (GObject *object)
 {
@@ -156,7 +174,11 @@ diagram_data_finalize (GObject *object)
 
   g_clear_pointer (&data->paper.name, g_free);
 
-  g_clear_weak_pointer (&data->active_layer);
+  if (data->active_layer) {
+    g_object_weak_unref (G_OBJECT (data->active_layer),
+                         active_layer_died,
+                         data);
+  }
   g_ptr_array_free (data->layers, TRUE);
 
   g_list_free (data->selected);
@@ -167,6 +189,44 @@ diagram_data_finalize (GObject *object)
 }
 
 
+static void
+dia_diagram_data_set_property (GObject      *object,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  DiagramData *self = DIA_DIAGRAM_DATA (object);
+
+  switch (property_id) {
+    case PROP_ACTIVE_LAYER:
+      data_set_active_layer (self, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
+static void
+dia_diagram_data_get_property (GObject    *object,
+                               guint       property_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  DiagramData *self = DIA_DIAGRAM_DATA (object);
+
+  switch (property_id) {
+    case PROP_ACTIVE_LAYER:
+      g_value_set_object (value, dia_diagram_data_get_active_layer (self));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+
 /*!
  * \brief Create a copy of the whole diagram data
  *
@@ -244,17 +304,37 @@ diagram_data_clone_selected (DiagramData *data)
   return clone;
 }
 
-/** Initialize the DiagramData class data.
- * @param klass The class object to initialize functions for.
- */
+
 static void
-diagram_data_class_init(DiagramDataClass *klass)
+dia_diagram_data_class_init (DiagramDataClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+  object_class->finalize = diagram_data_finalize;
+  object_class->set_property = dia_diagram_data_set_property;
+  object_class->get_property = dia_diagram_data_get_property;
+
+  klass->object_add = _diagram_data_object_add;
+  klass->object_remove = _diagram_data_object_remove;
+  klass->selection_changed = _diagram_data_selection_changed;
+
   parent_class = g_type_class_peek_parent (klass);
 
-  diagram_data_signals[OBJECT_ADD] =
+  /**
+   * DiagramData:active-layer:
+   *
+   * Since: 0.98
+   */
+  pspecs[PROP_ACTIVE_LAYER] =
+    g_param_spec_object ("active-layer",
+                         "Active Layer",
+                         "The active layer",
+                         DIA_TYPE_LAYER,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (object_class, LAST_PROP, pspecs);
+
+  signals[OBJECT_ADD] =
     g_signal_new ("object_add",
               G_TYPE_FROM_CLASS (klass),
               G_SIGNAL_RUN_FIRST,
@@ -266,7 +346,7 @@ diagram_data_class_init(DiagramDataClass *klass)
               G_TYPE_POINTER,
               G_TYPE_POINTER);
 
-  diagram_data_signals[OBJECT_REMOVE] =
+  signals[OBJECT_REMOVE] =
     g_signal_new ("object_remove",
               G_TYPE_FROM_CLASS (klass),
               G_SIGNAL_RUN_FIRST,
@@ -278,51 +358,79 @@ diagram_data_class_init(DiagramDataClass *klass)
               G_TYPE_POINTER,
               G_TYPE_POINTER);
 
-  diagram_data_signals[SELECTION_CHANGED] =
+  signals[SELECTION_CHANGED] =
     g_signal_new ("selection_changed",
-                 G_TYPE_FROM_CLASS (klass),
-                 G_SIGNAL_RUN_FIRST,
-                 G_STRUCT_OFFSET (DiagramDataClass, selection_changed),
-                 NULL, NULL,
-                 dia_marshal_VOID__INT,
-                 G_TYPE_NONE, 1,
-                 G_TYPE_INT);
-
-  object_class->finalize = diagram_data_finalize;
-  klass->object_add = _diagram_data_object_add;
-  klass->object_remove = _diagram_data_object_remove;
-  klass->selection_changed = _diagram_data_selection_changed;
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (DiagramDataClass, selection_changed),
+                  NULL, NULL,
+                  dia_marshal_VOID__INT,
+                  G_TYPE_NONE, 1,
+                  G_TYPE_INT);
+
+  /**
+   * DiagramData::layers-changed:
+   * @self: the #DiagramData
+   * @position: where the change happened
+   * @removed: number of layers removed
+   * @added: number of layers added
+   *
+   * Since: 0.98
+   */
+  signals[LAYERS_CHANGED] =
+    g_signal_new ("layers-changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  0, NULL, NULL,
+                  dia_marshal_VOID__UINT_UINT_UINT,
+                  G_TYPE_NONE, 3,
+                  G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
 }
 
 
-/*!
- * \brief Raise a layer up one in a diagram.
- * @param data The diagram that the layer belongs to.
- * @param layer The layer to raise.
- * \memberof _DiagramData
+/**
+ * data_raise_layer:
+ * @data: The diagram that the layer belongs to.
+ * @layer: The layer to raise.
+ *
+ * Raise a layer up one in a diagram.
+ *
+ * Since: dawn-of-time
  */
 void
 data_raise_layer (DiagramData *data, DiaLayer *layer)
 {
-  guint layer_nr = 0;
+  int layer_nr = -1;
   DiaLayer *tmp;
 
   layer_nr = data_layer_get_index (data, layer);
 
-  if (layer_nr < data_layer_count (data) - 1) {
-    tmp = g_ptr_array_index (data->layers, layer_nr + 1);
-    g_ptr_array_index (data->layers, layer_nr + 1) =
+  g_return_if_fail (layer_nr >= 0);
+
+  if (layer_nr > 0) {
+    tmp = g_ptr_array_index (data->layers, layer_nr - 1);
+    g_ptr_array_index (data->layers, layer_nr - 1) =
                                 g_ptr_array_index (data->layers, layer_nr);
     g_ptr_array_index (data->layers, layer_nr) = tmp;
+
+    g_signal_emit (data,
+                   signals[LAYERS_CHANGED],
+                   0,
+                   layer_nr - 1,
+                   2,
+                   2);
   }
 }
 
 
-/*!
- * \brief Lower a layer by one in a diagram.
- * @param data The diagram that the layer belongs to.
- * @param layer The layer to lower.
- * \memberof _DiagramData
+/**
+ * data_lower_layer:
+ * @data: The diagram that the layer belongs to.
+ * @layer: The layer to lower.
+ *
+ * Lower a layer by one in a diagram.
+ *
+ * Since: dawn-of-time
  */
 void
 data_lower_layer (DiagramData *data, DiaLayer *layer)
@@ -334,11 +442,18 @@ data_lower_layer (DiagramData *data, DiaLayer *layer)
 
   g_return_if_fail (layer_nr >= 0);
 
-  if (layer_nr > 0) {
-    tmp = g_ptr_array_index (data->layers, layer_nr-1);
-    g_ptr_array_index (data->layers, layer_nr-1) =
-                                g_ptr_array_index(data->layers, layer_nr);
-    g_ptr_array_index (data->layers, layer_nr) = tmp;
+  if (layer_nr < data_layer_count (data) - 1) {
+    tmp = g_ptr_array_index (data->layers, layer_nr);
+    g_ptr_array_index (data->layers, layer_nr) =
+                                g_ptr_array_index (data->layers, layer_nr + 1);
+    g_ptr_array_index (data->layers, layer_nr + 1) = tmp;
+
+    g_signal_emit (data,
+                   signals[LAYERS_CHANGED],
+                   0,
+                   layer_nr,
+                   2,
+                   2);
   }
 }
 
@@ -383,6 +498,8 @@ data_add_layer_at (DiagramData *data, DiaLayer *layer, int pos)
     g_ptr_array_index (data->layers, pos) = layer;
   }
 
+  g_signal_emit (data, signals[LAYERS_CHANGED], 0, pos, 0, 1);
+
   dia_layer_set_parent_diagram (layer, data);
   data_emit (data, layer, NULL, "object_add");
   dia_layer_update_extents (layer);
@@ -467,7 +584,21 @@ data_layer_count (const DiagramData *data)
 void
 data_set_active_layer (DiagramData *data, DiaLayer *layer)
 {
-  g_set_weak_pointer (&data->active_layer, layer);
+  g_return_if_fail (DIA_IS_DIAGRAM_DATA (data));
+
+  if (data->active_layer == layer) {
+    return;
+  }
+
+  if (data->active_layer) {
+    g_object_weak_unref (G_OBJECT (data->active_layer),
+                         active_layer_died,
+                         data);
+  }
+  data->active_layer = layer;
+  g_object_weak_ref (G_OBJECT (data->active_layer), active_layer_died, data);
+
+  g_object_notify_by_pspec (G_OBJECT (data), pspecs[PROP_ACTIVE_LAYER]);
 }
 
 
@@ -500,21 +631,38 @@ dia_diagram_data_get_active_layer (DiagramData *self)
 void
 data_remove_layer (DiagramData *data, DiaLayer *layer)
 {
+  DiaLayer *active;
+  int location;
+
   if (data_layer_count (data) <= 1) {
     return;
   }
 
-  if (dia_diagram_data_get_active_layer (data) == layer) {
+  active = dia_diagram_data_get_active_layer (data);
+
+  if (active == layer) {
     data_remove_all_selected (data);
   }
 
   data_emit (data, layer, NULL, "object_remove");
-  dia_layer_set_parent_diagram (layer, NULL);
-  g_ptr_array_remove (data->layers, layer);
 
-  if (dia_diagram_data_get_active_layer (data) == NULL) {
-    data_set_active_layer (data, data_layer_get_nth (data, 0));
+  g_object_ref (layer);
+  location = data_layer_get_index (data, layer);
+  g_ptr_array_remove_index (data->layers, location);
+
+  g_signal_emit (data, signals[LAYERS_CHANGED], 0, location, 1, 0);
+
+  if (active == layer || active == NULL) {
+    DiaLayer *next_layer = data_layer_get_nth (data, location);
+    if (next_layer) {
+      data_set_active_layer (data, next_layer);
+    } else {
+      data_set_active_layer (data, data_layer_get_nth (data, location - 1));
+    }
   }
+
+  dia_layer_set_parent_diagram (layer, NULL);
+  g_object_unref (layer);
 }
 
 
@@ -587,7 +735,7 @@ data_select(DiagramData *data, DiaObject *obj)
     return; /* should this be an error?`*/
   data->selected = g_list_prepend(data->selected, obj);
   data->selected_count_private++;
-  g_signal_emit (data, diagram_data_signals[SELECTION_CHANGED], 0, data->selected_count_private);
+  g_signal_emit (data, signals[SELECTION_CHANGED], 0, data->selected_count_private);
 }
 
 /*!
@@ -606,7 +754,7 @@ data_unselect(DiagramData *data, DiaObject *obj)
     return; /* should this be an error?`*/
   data->selected = g_list_remove(data->selected, obj);
   data->selected_count_private--;
-  g_signal_emit (data, diagram_data_signals[SELECTION_CHANGED], 0, data->selected_count_private);
+  g_signal_emit (data, signals[SELECTION_CHANGED], 0, data->selected_count_private);
 }
 
 /*!
@@ -621,7 +769,7 @@ data_remove_all_selected(DiagramData *data)
   g_list_free(data->selected); /* Remove previous selection */
   data->selected = NULL;
   data->selected_count_private = 0;
-  g_signal_emit (data, diagram_data_signals[SELECTION_CHANGED], 0, data->selected_count_private);
+  g_signal_emit (data, signals[SELECTION_CHANGED], 0, data->selected_count_private);
 }
 
 
@@ -854,10 +1002,10 @@ data_emit (DiagramData *data,
 {
   /* check what signal it is */
   if (strcmp("object_add",signal_name) == 0)
-    g_signal_emit(data, diagram_data_signals[OBJECT_ADD], 0, layer, obj);
+    g_signal_emit(data, signals[OBJECT_ADD], 0, layer, obj);
 
   if (strcmp("object_remove",signal_name) == 0)
-    g_signal_emit(data, diagram_data_signals[OBJECT_REMOVE], 0, layer, obj);
+    g_signal_emit(data, signals[OBJECT_REMOVE], 0, layer, obj);
 
 }
 
diff --git a/lib/diamarshal.list b/lib/diamarshal.list
index 67e179da..7c3dc9b6 100644
--- a/lib/diamarshal.list
+++ b/lib/diamarshal.list
@@ -29,3 +29,4 @@ VOID: OBJECT,OBJECT
 VOID: INT
 VOID: POINTER,POINTER
 VOID: STRING, FLAGS
+VOID: UINT,UINT,UINT
diff --git a/lib/layer.c b/lib/layer.c
index bc1167da..7a35e239 100644
--- a/lib/layer.c
+++ b/lib/layer.c
@@ -73,12 +73,17 @@ static GParamSpec *pspecs[LAST_PROP] = { NULL, };
  */
 
 
+static int count = 0;
+
 static void
 dia_layer_finalize (GObject *object)
 {
   DiaLayer *self = DIA_LAYER (object);
   DiaLayerPrivate *priv = dia_layer_get_instance_private (self);
 
+  count--;
+  g_message ("RIP Layer %p %p (%i)", self, priv->parent_diagram, count);
+
   g_clear_pointer (&priv->name, g_free);
   destroy_object_list (priv->objects);
 
@@ -221,6 +226,9 @@ dia_layer_init (DiaLayer *self)
   priv->extents.right = 10.0;
   priv->extents.top = 0.0;
   priv->extents.bottom = 10.0;
+
+  g_message ("NEW Layer %p %p (%i)", self, priv->parent_diagram, count);
+  count++;
 }
 
 
@@ -985,8 +993,9 @@ dia_layer_set_object_list (DiaLayer *layer, GList *list)
   g_list_free (ol);
 }
 
+
 /**
- * dia_layer_set_object_list:
+ * dia_layer_get_object_list:
  * @layer: the #DiaLayer
  *
  * Since: 0.98
@@ -1003,6 +1012,7 @@ dia_layer_get_object_list (DiaLayer *layer)
   return priv->objects;
 }
 
+
 /**
  * dia_layer_get_parent_diagram:
  * @layer: the #DiaLayer
@@ -1021,6 +1031,7 @@ dia_layer_get_parent_diagram (DiaLayer *layer)
   return priv->parent_diagram;
 }
 
+
 /**
  * dia_layer_set_parent_diagram:
  * @layer: the #DiaLayer
@@ -1043,6 +1054,7 @@ dia_layer_set_parent_diagram (DiaLayer    *layer,
   }
 }
 
+
 /**
  * dia_layer_is_connectable:
  * @self: the #DiaLayer
diff --git a/plug-ins/drs/dia-render-script-import.c b/plug-ins/drs/dia-render-script-import.c
index 7d87ed78..da503e03 100644
--- a/plug-ins/drs/dia-render-script-import.c
+++ b/plug-ins/drs/dia-render-script-import.c
@@ -488,13 +488,13 @@ import_drs (const gchar *filename, DiagramData *dia, DiaContext *ctx, void* user
   for (node = root->children; node != NULL; node = node->next) {
     if (xmlStrcmp (node->name, (const xmlChar *) "layer") == 0) {
       xmlChar *str;
-      xmlChar *name = xmlGetProp (node, "name");
+      xmlChar *name = xmlGetProp (node, (const xmlChar *) "name");
       DiaLayer *layer = dia_layer_new (name ? (char *) name : _("Layer"), dia);
 
       dia_clear_xml_string (&name);
 
-      str = xmlGetProp (node, "active");
-      if (xmlStrcmp (str, "true")) {
+      str = xmlGetProp (node, (const xmlChar *) "active");
+      if (xmlStrcmp (str, (const xmlChar *) "true")) {
         g_set_object (&active_layer, layer);
       }
       dia_clear_xml_string (&str);
diff --git a/plug-ins/pdf/pdf-import.cpp b/plug-ins/pdf/pdf-import.cpp
index d2b138ef..185a2063 100644
--- a/plug-ins/pdf/pdf-import.cpp
+++ b/plug-ins/pdf/pdf-import.cpp
@@ -414,8 +414,9 @@ public :
                      this->page_height * ((this->pageNum - 1) / m)};
     advance.x += group->position.x;
     advance.y += group->position.y;
-    group->ops->move (group, &advance);
-    dia_layer_add_object (this->dia->active_layer, group);
+    dia_object_move (group, &advance);
+    dia_layer_add_object (dia_diagram_data_get_active_layer (this->dia),
+                          group);
     dia_object_set_meta (group, "name", name);
     g_free (name);
   }


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