[dia] Object alias definition via sheet file
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] Object alias definition via sheet file
- Date: Mon, 13 Jun 2011 21:42:29 +0000 (UTC)
commit 5c810e89c6c6ed509f029107ecbe074d6f2cb7d6
Author: Hans Breuer <hans breuer org>
Date: Mon Jun 13 23:23:23 2011 +0200
Object alias definition via sheet file
To keep compatibility when renaming old shapes/objects the
new alias facility could be used, see following commits for
bug 598969 and bug 567886
doc/sheet.dtd | 6 ++-
lib/Makefile.am | 2 +
lib/makefile.msc | 1 +
lib/object-alias.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/object-alias.h | 8 ++
lib/sheet.c | 19 ++++--
6 files changed, 214 insertions(+), 7 deletions(-)
---
diff --git a/doc/sheet.dtd b/doc/sheet.dtd
index 916d386..8d35881 100644
--- a/doc/sheet.dtd
+++ b/doc/sheet.dtd
@@ -8,9 +8,13 @@
<!ATTLIST description
xml:lang NMTOKEN #IMPLIED 'C' >
+<!ELEMENT alias (#PCDATA)* >
+<!ATTLIST alias
+ name CDATA #REQUIRED >
+
<!ELEMENT contents (object | shape | br)* >
-<!ELEMENT object (description)* >
+<!ELEMENT object (description | alias)* >
<!ATTLIST object
name CDATA #REQUIRED
intdata CDATA #IMPLIED >
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 7f6dd4e..1fca5ca 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -90,6 +90,8 @@ libdia_la_SOURCES = \
handle.h \
object.h \
object.c \
+ object-alias.h \
+ object-alias.c \
object_defaults.c \
connection.c \
connection.h \
diff --git a/lib/makefile.msc b/lib/makefile.msc
index 8f79dcc..a6a8be3 100644
--- a/lib/makefile.msc
+++ b/lib/makefile.msc
@@ -83,6 +83,7 @@ OBJECTS = \
neworth_conn.obj \
objchange.obj \
object.obj \
+ object-alias.obj \
object_defaults.obj \
orth_conn.obj \
paper.obj \
diff --git a/lib/object-alias.c b/lib/object-alias.c
new file mode 100644
index 0000000..df49ffb
--- /dev/null
+++ b/lib/object-alias.c
@@ -0,0 +1,185 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * object-alias.c : a way to correct typos in object names
+ *
+ * Copyright (C) 2011 Hans Breuer
+ *
+ * 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>
+
+/* To map an old name to a new object type the alias indirection is used.
+ * Starting with the old object from file the old name will persist. So there
+ * even should be no issue with forward compatibility (except if the object
+ * itself has issues, like an updated version).
+ *
+ * An extra feature would be the availability of construction only properties.
+ * These would be applied to the real object after creation and should not be
+ * accessible to any user of the alias name, i.e. neither be listed by
+ * _alias_describe_props and _alias_get_props. But they additionally need to be
+ * filtered in _alias_set_props, because e.g. for groups some properties might
+ * get tried to be applied which do not come from the original set(?).
+ *
+ * The sheet code already relies on the correct order of type registration and
+ * access, so we can assume the target type is registered before the alias is
+ * created.
+ */
+
+#include <stdlib.h> /* atoi() */
+#include <string.h>
+
+#include <glib.h>
+
+#include "intl.h"
+
+#include <libxml/tree.h>
+#include "dia_xml_libxml.h"
+#include "dia_xml.h"
+#include "object.h"
+#include "message.h"
+#include "dia_dirs.h"
+#include "propinternals.h"
+
+/* DiaObjectType _alias_type must be dynamically
+ *
+ * The hash table is mapping the alias name to the real type.
+ */
+GHashTable *_alias_types_ht = NULL;
+
+/* It should be possible to modify the original object after creation to point
+ * back to the alias type, at least as long as there are no dedicated object_ops
+ */
+#undef MODIFY_OBJECTS_TYPE
+
+static void *
+_alias_lookup (const char *name)
+{
+ if (!_alias_types_ht)
+ return NULL;
+
+ return g_hash_table_lookup (_alias_types_ht, name);
+}
+
+/* type_ops */
+static DiaObject *
+_alias_create (Point *startpoint,
+ void *user_data,
+ Handle **handle1,
+ Handle **handle2);
+static DiaObject *
+_alias_load (ObjectNode obj_node, int version, const char *filename);
+static void
+_alias_save (DiaObject *obj, ObjectNode obj_node, const char *filename);
+
+static ObjectTypeOps _alias_type_ops =
+{
+ (CreateFunc) _alias_create,
+ (LoadFunc) _alias_load, /* can't use object_load_using_properties, signature mismatch */
+ (SaveFunc) _alias_save, /* overwrite for filename normalization */
+ (GetDefaultsFunc) NULL,
+ (ApplyDefaultsFunc) NULL
+};
+
+/*! factory function */
+static DiaObject *
+_alias_create (Point *startpoint,
+ void *user_data,
+ Handle **handle1,
+ Handle **handle2)
+{
+ DiaObject *obj;
+ DiaObjectType *alias_type = (DiaObjectType *)user_data;
+ DiaObjectType *real_type;
+
+ g_return_val_if_fail (alias_type != NULL || alias_type->name != NULL, NULL);
+
+ real_type = _alias_lookup (alias_type->name);
+ if (!real_type)
+ return NULL;
+ g_return_val_if_fail (real_type->ops != &_alias_type_ops, NULL);
+
+ obj = real_type->ops->create (startpoint, real_type->default_user_data, handle1, handle2);
+ if (!obj)
+ return NULL;
+#ifdef MODIFY_OBJECTS_TYPE
+ /* now modify the object for some behavior change */
+ obj->type = alias_type; /* also changes the name */
+#endif
+
+ return obj;
+}
+
+static DiaObject *
+_alias_load (ObjectNode obj_node, int version, const char *filename)
+{
+ DiaObject *obj;
+ xmlChar *str;
+
+ str = xmlGetProp(obj_node, (const xmlChar *)"type");
+ if (str) {
+ DiaObjectType *alias_type = object_get_type ((char *)str);
+ DiaObjectType *real_type = _alias_lookup ((char *)str);
+ Point apoint = {0, 0};
+ Handle *h1, *h2;
+ /* can not use real_type->ops->load (obj_node, ...) because the
+ * typename used from obj_node is wrong for the real object ...
+ * just another reason to pass in the exlplicit this-pointer in every method.
+ */
+ obj = real_type->ops->create (&apoint, real_type->default_user_data, &h1, &h2);
+ object_load_props (obj, obj_node);
+#ifdef MODIFY_OBJECTS_TYPE
+ /* now modify the object for some behavior change */
+ obj->type = alias_type; /* also changes the name */
+#endif
+ xmlFree(str);
+ }
+ return obj;
+}
+
+static void
+_alias_save (DiaObject *obj, ObjectNode obj_node, const char *filename)
+{
+ object_save_using_properties (obj, obj_node, filename);
+}
+
+void
+object_register_alias_type (DiaObjectType *type, ObjectNode alias_node)
+{
+ xmlChar *name;
+
+ /* real type must be available before the alias can be created */
+ g_return_if_fail (type != NULL && object_get_type (type->name) != NULL);
+
+ name = xmlGetProp(alias_node, (const xmlChar *)"name");
+ if (name) {
+ DiaObjectType *alias_type = g_new0 (DiaObjectType, 1);
+
+ alias_type->name = g_strdup ((char *)name);
+ alias_type->ops = &_alias_type_ops;
+ alias_type->version = type->version; /* really? */
+ alias_type->pixmap = alias_type->pixmap;
+ alias_type->pixmap_file = type->pixmap_file ;
+ alias_type->default_user_data = alias_type; /* _create has no self pointer */
+
+ object_register_type (alias_type);
+
+ if (!_alias_types_ht)
+ _alias_types_ht = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (_alias_types_ht, g_strdup (name), type);
+
+ xmlFree (name);
+ }
+}
diff --git a/lib/object-alias.h b/lib/object-alias.h
new file mode 100644
index 0000000..cd5b649
--- /dev/null
+++ b/lib/object-alias.h
@@ -0,0 +1,8 @@
+#ifndef OBJECT_ALIAS_H
+#define OBJECT_ALIAS_H
+
+#include "dia_xml.h"
+
+void object_register_alias_type (DiaObjectType *type, ObjectNode alias_node);
+
+#endif
diff --git a/lib/sheet.c b/lib/sheet.c
index d85caf1..06c3f19 100644
--- a/lib/sheet.c
+++ b/lib/sheet.c
@@ -38,6 +38,7 @@
#include "sheet.h"
#include "message.h"
#include "object.h"
+#include "object-alias.h"
#include "dia_dirs.h"
static GSList *sheets = NULL;
@@ -360,6 +361,8 @@ load_register_sheet(const gchar *dirname, const gchar *filename,
gboolean has_intdata = FALSE;
gboolean has_icon_on_sheet = FALSE;
+
+ xmlChar *ot_name = NULL;
if (xmlIsBlankNode(node)) continue;
@@ -389,6 +392,8 @@ load_register_sheet(const gchar *dirname, const gchar *filename,
chardata = (gchar *) xmlGetProp(node, (const xmlChar *)"chardata");
/* TODO.... */
if (chardata) xmlFree(chardata);
+
+ ot_name = xmlGetProp(node, (xmlChar *)"name");
for (subnode = node->xmlChildrenNode;
subnode != NULL ;
@@ -425,13 +430,14 @@ load_register_sheet(const gchar *dirname, const gchar *filename,
}
has_icon_on_sheet = TRUE;
if (tmp) xmlFree(tmp);
+ } else if (subnode->ns == ns && !xmlStrcmp(subnode->name, (const xmlChar *)"alias")) {
+ if (ot_name)
+ object_register_alias_type (object_get_type ((char *)ot_name), subnode);
}
}
- tmp = xmlGetProp(node, (xmlChar *)"name");
-
sheet_obj = g_new(SheetObject,1);
- sheet_obj->object_type = g_strdup((char *) tmp);
+ sheet_obj->object_type = g_strdup((char *) ot_name);
sheet_obj->description = g_strdup(objdesc);
xmlFree(objdesc); objdesc = NULL;
@@ -444,14 +450,14 @@ load_register_sheet(const gchar *dirname, const gchar *filename,
sheet_obj->line_break = set_line_break;
set_line_break = FALSE;
- if ((otype = object_get_type((char *) tmp)) == NULL) {
+ if ((otype = object_get_type((char *) ot_name)) == NULL) {
/* Don't complain. This does happen when disabling plug-ins too.
g_warning("object_get_type(%s) returned NULL", tmp); */
if (sheet_obj->description) g_free(sheet_obj->description);
g_free(sheet_obj->pixmap_file);
g_free(sheet_obj->object_type);
g_free(sheet_obj);
- if (tmp) xmlFree(tmp);
+ if (tmp) xmlFree(ot_name);
continue;
}
@@ -468,7 +474,8 @@ load_register_sheet(const gchar *dirname, const gchar *filename,
else
sheet_obj->user_data_type = USER_DATA_IS_INTDATA;
- if (tmp) xmlFree(tmp);
+ if (ot_name)
+ xmlFree(ot_name);
/* we don't need to fix up the icon and descriptions for simple objects,
since they don't have their own description, and their icon is
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]