[dia] change: setup a fundamental type for changes



commit 0c6fd3c425f30f310655cd86360eaa0bf92be540
Author: Zander Brown <zbrown gnome org>
Date:   Sat Sep 28 12:06:40 2019 +0100

    change: setup a fundamental type for changes
    
    This lets us get the benefits of GType without the unneeded overhead of GObject

 app/dia-change.c                    | 288 ++++++++++++++++++++++++++++++++++++
 app/dia-change.h                    |  76 ++++++++++
 app/layer-editor/dia-layer-widget.c |   1 +
 app/layer-editor/layer_dialog.c     |  44 +++---
 app/meson.build                     |   2 +
 docs/dia-app/dia-app-docs.xml       |  15 +-
 6 files changed, 397 insertions(+), 29 deletions(-)
---
diff --git a/app/dia-change.c b/app/dia-change.c
new file mode 100644
index 00000000..b48689f1
--- /dev/null
+++ b/app/dia-change.c
@@ -0,0 +1,288 @@
+/* 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
+ *
+ * Copyright © 2019 Zander Brown <zbrown gnome org>
+ */
+
+#include <glib-object.h>
+#include <gobject/gvaluecollector.h>
+
+#include "dia-change.h"
+#include "diagram.h"
+
+static void
+dia_change_real_apply (DiaChange *self,
+                       Diagram   *diagram)
+{
+  g_critical ("%s doesn't implement apply", DIA_CHANGE_TYPE_NAME (self));
+}
+
+
+static void
+dia_change_real_revert (DiaChange *self,
+                        Diagram   *diagram)
+{
+ g_critical ("%s doesn't implement revert", DIA_CHANGE_TYPE_NAME (self));
+}
+
+
+static void
+dia_change_real_free (DiaChange *self)
+{
+}
+
+
+static void
+dia_change_base_class_init (DiaChangeClass *klass)
+{
+  klass->apply = dia_change_real_apply;
+  klass->revert = dia_change_real_revert;
+  klass->free = dia_change_real_free;
+}
+
+
+static void
+dia_change_class_finalize (DiaChangeClass *klass)
+{
+
+}
+
+
+static void
+dia_change_do_class_init (DiaChangeClass *klass)
+{
+}
+
+
+static void
+dia_change_init (DiaChange      *self,
+                 DiaChangeClass *klass)
+{
+  g_ref_count_init (&self->refs);
+}
+
+
+static void
+g_value_change_init (GValue *value)
+{
+  value->data[0].v_pointer = NULL;
+}
+
+
+static void
+g_value_change_free_value (GValue *value)
+{
+  if (value->data[0].v_pointer) {
+    dia_change_unref (value->data[0].v_pointer);
+  }
+}
+
+
+static void
+g_value_change_copy_value (const GValue *src_value,
+                           GValue       *dest_value)
+{
+  if (src_value->data[0].v_pointer) {
+    dest_value->data[0].v_pointer = dia_change_ref (src_value->data[0].v_pointer);
+  } else {
+    dest_value->data[0].v_pointer = NULL;
+  }
+}
+
+
+static gpointer
+g_value_change_peek_pointer (const GValue *value)
+{
+  return value->data[0].v_pointer;
+}
+
+
+static gchar*
+g_value_change_collect_value (GValue      *value,
+                              guint        n_collect_values,
+                              GTypeCValue *collect_values,
+                              guint        collect_flags)
+{
+  if (collect_values[0].v_pointer) {
+    DiaChange *change = collect_values[0].v_pointer;
+
+    if (change->g_type_instance.g_class == NULL) {
+      return g_strconcat ("invalid unclassed change pointer for value type '",
+                          G_VALUE_TYPE_NAME (value),
+                          "'",
+                          NULL);
+    } else if (!g_value_type_compatible (DIA_CHANGE_TYPE (change), G_VALUE_TYPE (value))) {
+      return g_strconcat ("invalid change type '",
+                          DIA_CHANGE_TYPE_NAME (change),
+                          "' for value type '",
+                          G_VALUE_TYPE_NAME (value),
+                          "'",
+                          NULL);
+      /* never honour G_VALUE_NOCOPY_CONTENTS for ref-counted types */
+      value->data[0].v_pointer = dia_change_ref (change);
+    }
+  } else {
+    value->data[0].v_pointer = NULL;
+  }
+
+  return NULL;
+}
+
+
+static gchar*
+g_value_change_lcopy_value (const GValue *value,
+                            guint         n_collect_values,
+                            GTypeCValue  *collect_values,
+                            guint         collect_flags)
+{
+  DiaChange **change_p = collect_values[0].v_pointer;
+
+  if (!change_p) {
+    return g_strdup_printf ("value location for '%s' passed as NULL",
+                            G_VALUE_TYPE_NAME (value));
+  }
+
+  if (!value->data[0].v_pointer) {
+    *change_p = NULL;
+  } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
+    *change_p = value->data[0].v_pointer;
+  } else {
+    *change_p = dia_change_ref (value->data[0].v_pointer);
+  }
+
+  return NULL;
+}
+
+
+static void
+g_value_change_transform_value (const GValue *src_value,
+                                GValue       *dest_value)
+{
+  if (src_value->data[0].v_pointer &&
+      g_type_is_a (DIA_CHANGE_TYPE (src_value->data[0].v_pointer), G_VALUE_TYPE (dest_value))) {
+    dest_value->data[0].v_pointer = dia_change_ref (src_value->data[0].v_pointer);
+  } else {
+    dest_value->data[0].v_pointer = NULL;
+  }
+}
+
+
+GType
+dia_change_get_type (void)
+{
+  static volatile GType type_id = 0;
+
+  if (g_once_init_enter (&type_id)) {
+    static const GTypeFundamentalInfo finfo = {
+      G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE,
+    };
+    GTypeInfo info = {
+      sizeof (DiaChangeClass),
+      (GBaseInitFunc) dia_change_base_class_init,
+      (GBaseFinalizeFunc) dia_change_class_finalize,
+      (GClassInitFunc) dia_change_do_class_init,
+      NULL,                         /* class_destroy */
+      NULL,                         /* class_data */
+      sizeof (DiaChange),
+      0,                            /* n_preallocs */
+      (GInstanceInitFunc) dia_change_init,
+      NULL,                         /* value_table */
+    };
+    static const GTypeValueTable value_table = {
+      g_value_change_init,          /* value_init */
+      g_value_change_free_value,    /* value_free */
+      g_value_change_copy_value,    /* value_copy */
+      g_value_change_peek_pointer,  /* value_peek_pointer */
+      "p",                          /* collect_format */
+      g_value_change_collect_value, /* collect_value */
+      "p",                          /* lcopy_format */
+      g_value_change_lcopy_value,   /* lcopy_value */
+    };
+    GType type;
+
+    info.value_table = &value_table;
+    type = g_type_register_fundamental (g_type_fundamental_next (),
+                                        g_intern_static_string ("DiaChange"),
+                                        &info,
+                                        &finfo,
+                                        0);
+    g_value_register_transform_func (type,
+                                     type,
+                                     g_value_change_transform_value);
+
+    g_once_init_leave (&type_id, type);
+  }
+
+  return type_id;
+}
+
+
+gpointer
+dia_change_ref (gpointer self)
+{
+  g_return_val_if_fail (self != NULL, NULL);
+
+  g_ref_count_inc (&((DiaChange *) self)->refs);
+
+  return self;
+}
+
+
+void
+dia_change_unref (gpointer self)
+{
+  g_return_if_fail (self != NULL);
+
+  if (g_ref_count_dec (&((DiaChange *) self)->refs)) {
+    DIA_CHANGE_GET_CLASS (self)->free (self);
+
+    g_type_free_instance (self);
+  }
+}
+
+
+gpointer
+dia_change_new (GType type)
+{
+  g_return_val_if_fail (DIA_TYPE_IS_CHANGE (type), NULL);
+
+  return g_type_create_instance (type);
+}
+
+
+void
+dia_change_apply (DiaChange *self,
+                  Diagram   *diagram)
+{
+  g_return_if_fail (self && DIA_IS_CHANGE (self));
+  g_return_if_fail (diagram && DIA_IS_DIAGRAM (diagram));
+
+  DIA_CHANGE_GET_CLASS (self)->apply (self, diagram);
+}
+
+
+void
+dia_change_revert (DiaChange *self,
+                   Diagram   *diagram)
+{
+  g_return_if_fail (self && DIA_IS_CHANGE (self));
+  g_return_if_fail (diagram && DIA_IS_DIAGRAM (diagram));
+
+  DIA_CHANGE_GET_CLASS (self)->revert (self, diagram);
+}
diff --git a/app/dia-change.h b/app/dia-change.h
new file mode 100644
index 00000000..f834dc19
--- /dev/null
+++ b/app/dia-change.h
@@ -0,0 +1,76 @@
+/* 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
+ *
+ * Copyright © 2019 Zander Brown <zbrown gnome org>
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+// TODO: Fix the diagram.h cycle
+typedef struct _Diagram Diagram;
+
+G_BEGIN_DECLS
+
+GType dia_change_get_type (void);
+#define DIA_TYPE_CHANGE dia_change_get_type ()
+
+typedef struct _DiaChange DiaChange;
+typedef struct _DiaChangeClass DiaChangeClass;
+
+#define DIA_TYPE_IS_CHANGE(type)     (G_TYPE_FUNDAMENTAL (type) == DIA_TYPE_CHANGE)
+#define DIA_CHANGE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), DIA_TYPE_CHANGE, DiaChange))
+#define DIA_CHANGE_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), DIA_TYPE_CHANGE, DiaChangeClass))
+#define DIA_IS_CHANGE(object)        (G_TYPE_CHECK_INSTANCE_FUNDAMENTAL_TYPE ((object), DIA_TYPE_CHANGE))
+#define DIA_IS_CHANGE_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), DIA_TYPE_CHANGE))
+#define DIA_CHANGE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), DIA_TYPE_CHANGE, DiaChangeClass))
+#define DIA_CHANGE_TYPE(object)      (G_TYPE_FROM_INSTANCE (object))
+#define DIA_CHANGE_TYPE_NAME(object) (g_type_name (DIA_CHANGE_TYPE (object)))
+#define DIA_CHANGE_CLASS_TYPE(class) (G_TYPE_FROM_CLASS (class))
+#define DIA_CHANGE_CLASS_NAME(class) (g_type_name (DIA_CHANGE_CLASS_TYPE (class)))
+#define G_VALUE_HOLDS_CHANGE(value)  (G_TYPE_CHECK_VALUE_TYPE ((value), DIA_TYPE_CHANGE))
+
+struct _DiaChange {
+  GTypeInstance g_type_instance;
+
+  grefcount refs;
+};
+
+struct _DiaChangeClass {
+  GTypeClass parent;
+
+  void (*apply)  (DiaChange *change,
+                  Diagram   *dia);
+  void (*revert) (DiaChange *change,
+                  Diagram   *dia);
+  void (*free)   (DiaChange *change);
+};
+
+void     dia_change_unref  (gpointer   self);
+gpointer dia_change_ref    (gpointer   self);
+gpointer dia_change_new    (GType      type);
+void     dia_change_apply  (DiaChange *self,
+                            Diagram   *diagram);
+void     dia_change_revert (DiaChange *self,
+                            Diagram   *diagram);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (DiaChange, dia_change_unref)
+
+G_END_DECLS
diff --git a/app/layer-editor/dia-layer-widget.c b/app/layer-editor/dia-layer-widget.c
index c0fd6f76..430ee5d8 100644
--- a/app/layer-editor/dia-layer-widget.c
+++ b/app/layer-editor/dia-layer-widget.c
@@ -22,6 +22,7 @@
 
 #include "widgets.h"
 #include "dia-layer-widget.h"
+#include "layer_dialog.h"
 
 /* The connectability buttons don't quite behave the way they should.
  * The shift-click behavior messes up the active layer.
diff --git a/app/layer-editor/layer_dialog.c b/app/layer-editor/layer_dialog.c
index 1f5ecbb5..d0f80052 100644
--- a/app/layer-editor/layer_dialog.c
+++ b/app/layer-editor/layer_dialog.c
@@ -137,30 +137,6 @@ layer_dialog_set_diagram (Diagram *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
@@ -345,9 +321,23 @@ undo_layer_visibility(Diagram *dia, DiaLayer *layer, gboolean exclusive)
  * \brief edit a layers name, possibly also creating the layer
  */
 void
-diagram_edit_layer(Diagram *dia, DiaLayer *layer)
+diagram_edit_layer (Diagram *dia, DiaLayer *layer)
 {
-  g_return_if_fail(dia != NULL);
+  GtkWidget *dlg;
+
+  g_return_if_fail (dia || layer);
 
-  layer_dialog_edit_layer (layer ? NULL : 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);
 }
diff --git a/app/meson.build b/app/meson.build
index b0a94798..3dd80d71 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -7,6 +7,8 @@ dia_sources = [
     'properties-dialog.c',
     'defaults.c',
     'undo.c',
+    'dia-change.c',
+    'dia-change.h',
     'object_ops.c',
 
     'layer-editor/dia-layer-widget.c',
diff --git a/docs/dia-app/dia-app-docs.xml b/docs/dia-app/dia-app-docs.xml
index f18db812..795b215e 100644
--- a/docs/dia-app/dia-app-docs.xml
+++ b/docs/dia-app/dia-app-docs.xml
@@ -55,7 +55,14 @@
     <xi:include href="xml/handle_ops.xml" />
     <xi:include href="xml/highlight.xml" />
     <xi:include href="xml/interface.xml" />
-    <xi:include href="xml/layer_dialog.xml" />
+    <chapter id="layer-editor">
+        <title>Layer Editor</title>
+        <xi:include href="xml/dia-layer-editor.xml" />
+        <xi:include href="xml/dia-layer-widget.xml" />
+        <xi:include href="xml/dia-layer-editor-dialog.xml" />
+        <xi:include href="xml/dia-layer-properties.xml" />
+        <xi:include href="xml/layer_dialog.xml" />
+    </chapter>
     <xi:include href="xml/load_save.xml" />
     <xi:include href="xml/magnify.xml" />
     <xi:include href="xml/menus.xml" />
@@ -78,7 +85,11 @@
     <xi:include href="xml/textedit.xml" />
     <xi:include href="xml/toolbox.xml" />
     <xi:include href="xml/tool.xml" />
-    <xi:include href="xml/undo.xml" />
+    <chapter id="undo-api">
+        <title>Undo</title>
+        <xi:include href="xml/dia-change.xml" />
+        <xi:include href="xml/undo.xml" />
+    </chapter>
   </part>
 
   <chapter id="object-tree">


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