[lasem] Rework of the property handling. Base classes.



commit 851f1af0c64f1e9aaaa3702b8f6e48af84a70714
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date:   Fri Aug 7 11:32:13 2009 +0200

    Rework of the property handling. Base classes.
    
    Properties are now stored in linked lists. It helps to reduce
    memory usage, and ease the property inheritage.

 src/lsm.h           |   45 +++++++
 src/lsmattributes.c |  237 +++++++++++++++++++++++++++++++++++
 src/lsmattributes.h |   67 ++++++++++
 src/lsmproperties.c |  339 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lsmproperties.h |   77 ++++++++++++
 src/lsmtraits.c     |   74 +++++++++++
 src/lsmtraits.h     |   45 +++++++
 7 files changed, 884 insertions(+), 0 deletions(-)
---
diff --git a/src/lsm.h b/src/lsm.h
new file mode 100644
index 0000000..71a93db
--- /dev/null
+++ b/src/lsm.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2009 Emmanuel Pacaud
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_H
+#define LSM_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	double x1;
+	double y1;
+	double x2;
+	double y2;
+} LsmExtents;
+
+typedef struct {
+	double x;
+	double y;
+	double width;
+	double height;
+} LsmBox;
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmattributes.c b/src/lsmattributes.c
new file mode 100644
index 0000000..611a7f8
--- /dev/null
+++ b/src/lsmattributes.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright © 2007-2009  Emmanuel Pacaud
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmattributes.h>
+#include <lsmdebug.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+gboolean
+lsm_attribute_is_defined (const LsmAttribute *attribute)
+{
+	g_return_val_if_fail (attribute != NULL, FALSE);
+
+	return attribute->value != NULL;
+}
+
+#define ATTRIBUTE_TRAIT(attribute) ((void *) (((void *) attribute) + sizeof (LsmAttribute)))
+
+struct _LsmAttributeManager {
+	GHashTable *			hash_by_name;
+};
+
+static LsmAttributeManager *
+lsm_attribute_manager_create (void)
+{
+	LsmAttributeManager *manager;
+
+	manager = g_new0 (LsmAttributeManager, 1);
+	manager->hash_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+
+	return manager;
+}
+
+LsmAttributeManager *
+lsm_attribute_manager_new (unsigned int n_attributes, const LsmAttributeInfos *attribute_infos)
+{
+	LsmAttributeManager *manager;
+
+	manager = lsm_attribute_manager_create ();
+
+	lsm_attribute_manager_add_attributes (manager, n_attributes, attribute_infos);
+
+	return manager;
+}
+
+LsmAttributeManager *
+lsm_attribute_manager_duplicate (const LsmAttributeManager *origin)
+{
+	LsmAttributeManager *manager;
+	GHashTableIter iter;
+	gpointer key, value;
+
+	g_return_val_if_fail (origin != NULL, NULL);
+
+	manager = lsm_attribute_manager_create ();
+
+	g_hash_table_iter_init (&iter, origin->hash_by_name);
+	while (g_hash_table_iter_next (&iter, &key, &value))
+		g_hash_table_insert (manager->hash_by_name, key, value);
+
+	return manager;
+}
+
+void
+lsm_attribute_manager_add_attributes (LsmAttributeManager *manager,
+				      unsigned int n_attributes,
+				      const LsmAttributeInfos *attribute_infos)
+{
+	unsigned int i;
+
+	g_return_if_fail (n_attributes > 0);
+	g_return_if_fail (attribute_infos != NULL);
+
+	for (i = 0; i < n_attributes; i++) {
+		g_assert (attribute_infos[i].name != NULL);
+		g_assert (attribute_infos[i].attribute_offset >= 0);
+		g_assert (attribute_infos[i].trait_class != NULL);
+
+		g_hash_table_insert (manager->hash_by_name,
+				     (void *) attribute_infos[i].name,
+				     (void *) &attribute_infos[i]);
+	}
+
+}
+
+void
+lsm_attribute_manager_free (LsmAttributeManager *manager)
+{
+	g_return_if_fail (manager != NULL);
+
+	g_hash_table_unref (manager->hash_by_name);
+	g_free (manager);
+}
+
+gboolean
+lsm_attribute_manager_set_attribute (LsmAttributeManager *manager,
+				     void *instance,
+				     const char *name,
+				     const char *value)
+{
+	LsmAttribute *attribute;
+	LsmAttributeInfos *attribute_infos;
+	const LsmTraitClass *trait_class;
+
+	g_return_val_if_fail (manager != NULL, FALSE);
+
+	attribute_infos = g_hash_table_lookup (manager->hash_by_name, name);
+	if (attribute_infos == NULL)
+		return FALSE;
+
+	attribute = (void *)(instance + attribute_infos->attribute_offset);
+	g_return_val_if_fail (attribute != NULL, FALSE);
+
+	trait_class = attribute_infos->trait_class;
+
+	g_free (attribute->value);
+	attribute->value = g_strdup (value);
+
+	if (attribute->value != NULL) {
+		if (trait_class->from_string)
+			trait_class->from_string (ATTRIBUTE_TRAIT (attribute), (char *) value);
+	} else {
+		if (trait_class->init)
+			trait_class->init (ATTRIBUTE_TRAIT (attribute), attribute_infos->trait_default);
+		else
+			/* Simple memcpy for default init implementation, discarde by a NULL default value. */
+			if (attribute_infos->trait_default != NULL)
+				memcpy (ATTRIBUTE_TRAIT (attribute),
+					attribute_infos->trait_default,
+					trait_class->size);
+	}
+
+	return TRUE;
+}
+
+char const *
+lsm_attribute_manager_get_attribute (LsmAttributeManager *manager,
+				     void *instance,
+				     const char *name)
+{
+	LsmAttributeInfos *attribute_infos;
+	LsmAttribute *attribute;
+
+	g_return_val_if_fail (manager != NULL, NULL);
+
+	attribute_infos = g_hash_table_lookup (manager->hash_by_name, name);
+	if (attribute_infos == NULL)
+		return NULL;
+
+	attribute = (void *)(instance + attribute_infos->attribute_offset);
+	g_return_val_if_fail (attribute != NULL, NULL);
+
+	return attribute->value;
+}
+
+void
+lsm_attribute_manager_clean_attributes (LsmAttributeManager *manager,
+					void *instance)
+{
+	LsmAttributeInfos *attribute_infos;
+	LsmAttribute *attribute;
+	const LsmTraitClass *trait_class;
+	GHashTableIter iter;
+	gpointer key, value;
+
+	g_return_if_fail (manager != NULL);
+
+	g_hash_table_iter_init (&iter, manager->hash_by_name);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		attribute_infos = value;
+		trait_class = attribute_infos->trait_class;
+
+		if (trait_class->finalize) {
+			attribute = (void *)(instance + attribute_infos->attribute_offset);
+			trait_class->finalize (ATTRIBUTE_TRAIT (attribute));
+		}
+	}
+}
+
+char *
+lsm_attribute_manager_serialize	(LsmAttributeManager *manager,
+				 void *instance)
+{
+	LsmAttributeInfos *attribute_infos;
+	LsmAttribute *attribute;
+	GString *string;
+	GHashTableIter iter;
+	char *c_string;
+	gpointer key, value;
+	gboolean is_first = TRUE;
+
+	g_return_val_if_fail (manager != NULL, NULL);
+
+	string = g_string_new ("");
+
+	g_hash_table_iter_init (&iter, manager->hash_by_name);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		attribute_infos = value;
+		attribute = (void *)(instance + attribute_infos->attribute_offset);
+
+		if (is_first) {
+			g_string_append_printf (string, "%s=\"%s\"",
+						attribute_infos->name,
+						attribute->value);
+			is_first = FALSE;
+		} else {
+			g_string_append_printf (string, " %s=\"%s\"",
+						attribute_infos->name,
+						attribute->value);
+		}
+	}
+
+	c_string = string->str;
+
+	g_string_free (string, FALSE);
+
+	return c_string;
+}
diff --git a/src/lsmattributes.h b/src/lsmattributes.h
new file mode 100644
index 0000000..c00f60c
--- /dev/null
+++ b/src/lsmattributes.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2007-2009 Emmanuel Pacaud
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_ATTRIBUTES_H
+#define LSM_ATTRIBUTES_H
+
+#include <lsm.h>
+#include <lsmtraits.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+	char *value;
+} LsmAttribute;
+
+gboolean	lsm_attribute_is_defined			(const LsmAttribute *attribute);
+
+typedef struct {
+	char const *		name;
+	ptrdiff_t 		attribute_offset;
+	const LsmTraitClass *	trait_class;
+	const void *		trait_default;
+} LsmAttributeInfos;
+
+typedef struct _LsmAttributeManager LsmAttributeManager;
+
+LsmAttributeManager *	lsm_attribute_manager_new 		(unsigned int n_attributes,
+								 const LsmAttributeInfos *attribute_infos);
+void			lsm_attribute_manager_free		(LsmAttributeManager *manager);
+void 			lsm_attribute_manager_add_attributes 	(LsmAttributeManager *manager,
+								 unsigned int n_attributes,
+								 const LsmAttributeInfos *attribute_infos);
+LsmAttributeManager * 	lsm_attribute_manager_duplicate 	(const LsmAttributeManager *origin);
+
+gboolean	lsm_attribute_manager_set_attribute		(LsmAttributeManager *manager,
+								 void *instance,
+								 char const *name,
+								 char const *value);
+char const *	lsm_attribute_manager_get_attribute		(LsmAttributeManager *manager,
+								 void *instance,
+								 char const *name);
+void		lsm_attribute_manager_clean_attributes 		(LsmAttributeManager *manager,
+								 void *instance);
+char *		lsm_attribute_manager_serialize			(LsmAttributeManager *manager,
+								 void *instance);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmproperties.c b/src/lsmproperties.c
new file mode 100644
index 0000000..4f8dd35
--- /dev/null
+++ b/src/lsmproperties.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright © 2007-2009 Emmanuel Pacaud
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmproperties.h>
+#include <lsmdebug.h>
+#include <lsmstr.h>
+#include <string.h>
+
+#define PROPERTY_TRAIT(property) ((void *) (((void *) property) + sizeof (LsmProperty)))
+#define PROPERTY_SIZE(trait_class) (trait_class->size + sizeof (LsmProperty))
+
+struct _LsmPropertyManager {
+	unsigned int		n_properties;
+	const LsmPropertyInfos *property_infos;
+	GHashTable *		hash_by_name;
+};
+
+LsmPropertyManager *
+lsm_property_manager_new (unsigned int n_properties, const LsmPropertyInfos *property_infos)
+{
+	LsmPropertyManager *manager;
+	guint16 i;
+
+	g_return_val_if_fail (n_properties > 0, NULL);
+	g_return_val_if_fail (property_infos != NULL, NULL);
+
+	manager = g_new (LsmPropertyManager, 1);
+	manager->hash_by_name = g_hash_table_new (g_str_hash, g_str_equal);
+	manager->n_properties = n_properties;
+	manager->property_infos = property_infos;
+
+	for (i = 0; i < n_properties; i++) {
+
+		g_assert (property_infos[i].name != NULL);
+		g_assert (property_infos[i].trait_class != NULL);
+
+		g_hash_table_insert (manager->hash_by_name,
+				     (void *) property_infos[i].name,
+				     (void *) &property_infos[i]);
+	}
+
+	return manager;
+}
+
+void
+lsm_property_manager_free (LsmPropertyManager *manager)
+{
+	g_return_if_fail (manager != NULL);
+
+	g_hash_table_unref (manager->hash_by_name);
+	g_free (manager);
+}
+
+static void
+property_free (LsmProperty *property, const LsmTraitClass *trait_class)
+{
+	if (trait_class != NULL && trait_class->finalize != NULL)
+		trait_class->finalize (PROPERTY_TRAIT (property));
+
+	g_free (property->value);
+	g_slice_free1 (PROPERTY_SIZE (trait_class), property);
+}
+
+static gboolean
+_set_property (LsmPropertyManager *manager,
+	       LsmPropertyBag *property_bag,
+	       const char *name, const char *value)
+{
+	LsmProperty *property;
+	const LsmPropertyInfos *property_infos;
+	const LsmTraitClass *trait_class;
+
+	property_infos = g_hash_table_lookup (manager->hash_by_name, name);
+	if (property_infos == NULL)
+		return FALSE;
+
+	trait_class = property_infos->trait_class;
+
+	/* We don't check for existing property in the list. The cleanup will be done later. */
+
+	property = g_slice_alloc0 (PROPERTY_SIZE (trait_class));
+	property->id = property_infos->id;
+	property->value = g_strdup (value);
+
+	if (trait_class->init)
+		trait_class->init (PROPERTY_TRAIT (property), NULL);
+
+	if (property->value != NULL && trait_class->from_string)
+		trait_class->from_string (PROPERTY_TRAIT (property), (char *) value);
+
+	property_bag->properties = g_slist_prepend (property_bag->properties, property);
+
+	return TRUE;
+}
+
+gboolean
+lsm_property_manager_set_property (LsmPropertyManager *manager,
+				   LsmPropertyBag *property_bag,
+				   const char *name, const char *value)
+{
+	gboolean property_found;
+	char *inline_style;
+
+	g_return_val_if_fail (property_bag != NULL, FALSE);
+	g_return_val_if_fail (manager != NULL, FALSE);
+	g_return_val_if_fail (name != NULL, FALSE);
+
+	property_found = _set_property (manager, property_bag, name, value);
+	if (property_found)
+		return TRUE;
+
+	if (strcmp (name, "style") != 0)
+		return FALSE;
+
+	inline_style = g_strdup (value);
+	if (inline_style == NULL)
+		return FALSE;
+
+	{
+		char *end_ptr = inline_style;
+		char *name;
+		char *value;
+
+		while (*end_ptr != '\0') {
+
+			lsm_str_skip_spaces (&end_ptr);
+
+			name = end_ptr;
+
+			while (*end_ptr != '\0' && *end_ptr != ':' && !g_ascii_isspace (*end_ptr))
+				end_ptr++;
+
+			if (*end_ptr != '\0') {
+				*end_ptr = '\0';
+				end_ptr++;
+
+				lsm_str_skip_colon_and_spaces (&end_ptr);
+
+				if (*end_ptr != '\0') {
+					char old_char;
+
+					value = end_ptr;
+
+					while (*end_ptr != ';' && *end_ptr != '\0')
+						end_ptr++;
+
+					old_char = *end_ptr;
+					*end_ptr = '\0';
+
+					lsm_debug ("[LsmPropertyManager::set_property] inline_style %s = %s",
+						   name, value);
+
+					_set_property (manager, property_bag, name, value);
+
+					*end_ptr = old_char;
+
+					lsm_str_skip_char (&end_ptr, ';');
+				}
+			}
+		}
+		g_free (inline_style);
+	}
+
+	return TRUE;
+}
+
+const char *
+lsm_property_manager_get_property (LsmPropertyManager *manager,
+				   LsmPropertyBag *property_bag,
+				   const char *name)
+{
+	LsmProperty *property = NULL;
+	const LsmPropertyInfos *property_infos;
+	GSList *iter;
+
+	g_return_val_if_fail (property_bag != NULL, NULL);
+	g_return_val_if_fail (manager != NULL, NULL);
+
+	property_infos = g_hash_table_lookup (manager->hash_by_name, name);
+	if (property_infos == NULL)
+		return NULL;
+
+	g_message ("Get property with name %s (%d)", name, property_infos->id);
+
+	for (iter = property_bag->properties; iter != NULL; iter = iter->next) {
+		property = iter->data;
+		if (property->id == property_infos->id)
+			break;
+	}
+
+	if (property == NULL)
+		return NULL;
+
+	return property->value;
+}
+
+void
+lsm_property_manager_clean_properties (LsmPropertyManager *manager,
+				       LsmPropertyBag *property_bag)
+{
+	LsmProperty *property;
+	GSList *iter;
+
+	g_return_if_fail (property_bag != NULL);
+	g_return_if_fail (manager != NULL);
+
+	for (iter = property_bag->properties; iter != NULL; iter = iter->next) {
+		property = iter->data;
+
+		if (property->id < manager->n_properties) {
+			const LsmPropertyInfos *property_infos;
+
+			property_infos = &manager->property_infos[property->id];
+			property_free (property, property_infos->trait_class);
+		}
+	}
+
+	g_slist_free (property_bag->properties);
+	property_bag->properties = NULL;
+}
+
+char *
+lsm_property_manager_serialize (LsmPropertyManager *manager,
+				LsmPropertyBag *property_bag)
+{
+	LsmProperty *property;
+	GSList *iter;
+	GString *string;
+	char *c_string;
+
+	g_return_val_if_fail (property_bag != NULL, NULL);
+	g_return_val_if_fail (manager != NULL, NULL);
+
+	string = g_string_new ("");
+
+	for (iter = property_bag->properties; iter != NULL; iter = iter->next) {
+		property = iter->data;
+
+		if (property->id < manager->n_properties) {
+			const LsmPropertyInfos *property_infos;
+
+			property_infos = &manager->property_infos[property->id];
+			g_string_append_printf (string, "%s=\"%s\"%s",
+						property_infos->name,
+						property->value,
+						iter->next != NULL ? " ": "");
+		}
+	}
+
+	c_string = string->str;
+	g_string_free (string, FALSE);
+
+	return c_string;
+}
+
+void
+lsm_property_manager_apply_property_bag (LsmPropertyManager *manager,
+					 LsmPropertyBag *bag,
+					 void *style,
+					 const void *parent_style)
+{
+	LsmProperty *property;
+	GSList *iter;
+
+	g_return_if_fail (bag != NULL);
+	g_return_if_fail (manager != NULL);
+
+	for (iter = bag->properties; iter != NULL; iter = iter->next) {
+		property = iter->data;
+
+		if (property->id < manager->n_properties) {
+			const LsmPropertyInfos *property_infos;
+
+			property_infos = &manager->property_infos[property->id];
+
+			if (g_strcmp0 (property->value, "inherit") != 0)
+				*((LsmProperty **) ((void*) style
+						   + LSM_PROPERTY_ID_TO_OFFSET (property->id))) = property;
+			else
+				*((LsmProperty **) ((void*) style
+						   + LSM_PROPERTY_ID_TO_OFFSET (property->id))) =
+					*((LsmProperty **) ((void*) parent_style
+							   + LSM_PROPERTY_ID_TO_OFFSET (property->id)));
+		}
+	}
+}
+
+void lsm_property_manager_init_default_style (LsmPropertyManager *property_manager,
+					      void *style)
+{
+	LsmProperty *property;
+	const LsmPropertyInfos *property_infos;
+	const LsmTraitClass *trait_class;
+	unsigned int i;
+
+	g_return_if_fail (property_manager != NULL);
+
+	for (i = 0; i < property_manager->n_properties; i++) {
+		property_infos = &property_manager->property_infos[i];
+		trait_class = property_infos->trait_class;
+
+		property = g_slice_alloc0 (PROPERTY_SIZE (trait_class));
+		property->id = property_infos->id;
+		property->value = g_strdup (property_infos->trait_default);
+
+		if (trait_class->from_string)
+			trait_class->from_string (PROPERTY_TRAIT (property),
+						  (char *) property_infos->trait_default);
+
+		*((LsmProperty **) ((void*) style
+				    + LSM_PROPERTY_ID_TO_OFFSET (property->id))) = property;
+	}
+}
+
+void
+lsm_property_bag_init (LsmPropertyBag *bag)
+{
+	g_return_if_fail (bag != NULL);
+
+	bag->properties = NULL;
+}
diff --git a/src/lsmproperties.h b/src/lsmproperties.h
new file mode 100644
index 0000000..bb944e4
--- /dev/null
+++ b/src/lsmproperties.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2007-2009 Emmanuel Pacaud
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+#ifndef LSM_PROPERTIES_H
+#define LSM_PROPERTIES_H
+
+#include <lsm.h>
+#include <lsmtraits.h>
+
+G_BEGIN_DECLS
+
+#define LSM_PROPERTY_OFFSET_TO_ID(structure,member) offsetof (structure, member) / sizeof (void *)
+#define LSM_PROPERTY_ID_TO_OFFSET(id) id * sizeof (void *)
+
+typedef struct {
+	guint16	id;
+	guint16	flags;
+	char *	value;
+} LsmProperty;
+
+typedef struct {
+	char const *		name;
+	guint16			id;
+	const LsmTraitClass *	trait_class;
+	const char *		trait_default;
+} LsmPropertyInfos;
+
+typedef struct {
+	GSList *properties;
+} LsmPropertyBag;
+
+typedef struct _LsmPropertyManager LsmPropertyManager;
+
+LsmPropertyManager *	lsm_property_manager_new	(unsigned int n_properties,
+							 const LsmPropertyInfos *property_infos);
+void			lsm_property_manager_free	(LsmPropertyManager *manager);
+
+gboolean 	lsm_property_manager_set_property 	(LsmPropertyManager *manager,
+							 LsmPropertyBag *property_bag,
+							 const char *name,
+							 const char *value);
+const char *	lsm_property_manager_get_property 	(LsmPropertyManager *manager,
+							 LsmPropertyBag *property_bag,
+							 const char *name);
+void		lsm_property_manager_clean_properties	(LsmPropertyManager *manager,
+							 LsmPropertyBag *property_bag);
+char * 		lsm_property_manager_serialize 		(LsmPropertyManager *property_manager,
+							 LsmPropertyBag *property_bag);
+void		lsm_property_manager_apply_property_bag (LsmPropertyManager *property_manager,
+							 LsmPropertyBag *property_bag,
+							 void *style,
+							 const void *parent_style);
+void		lsm_property_manager_init_default_style (LsmPropertyManager *property_manager,
+							 void *style);
+
+void		lsm_property_bag_init			(LsmPropertyBag *bag);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmtraits.c b/src/lsmtraits.c
new file mode 100644
index 0000000..36b217c
--- /dev/null
+++ b/src/lsmtraits.c
@@ -0,0 +1,74 @@
+#include <lsmtraits.h>
+#include <lsmstr.h>
+
+const LsmTraitClass lsm_null_trait_class = {
+	.size = 0
+};
+
+static void
+lsm_double_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	double *trait = (double *) abstract_trait;
+
+	*trait = g_strtod (string, NULL);
+}
+
+static char *
+lsm_double_trait_to_string (LsmTrait *abstract_trait)
+{
+	double *trait = (double *) abstract_trait;
+
+	return g_strdup_printf ("%g", *trait);
+}
+
+const LsmTraitClass lsm_double_trait_class = {
+	.size = sizeof (double),
+	.from_string = lsm_double_trait_from_string,
+	.to_string = lsm_double_trait_to_string
+};
+
+static void
+lsm_box_trait_from_string (LsmTrait *abstract_trait, char *string)
+{
+	LsmBox *trait = (LsmBox *) abstract_trait;
+	unsigned int i;
+	double value[4];
+
+	for (i = 0; i < 4 && *string != '\0'; i++) {
+		lsm_str_skip_semicolon_and_spaces (&string);
+
+		if (!lsm_str_parse_double (&string, &value[i]))
+			break;
+	}
+
+	if (i == 4) {
+		trait->x = value[0];
+		trait->y = value[1];
+		trait->width = value[2];
+		trait->height = value[3];
+
+		return;
+	}
+
+	trait->x =
+	trait->y =
+	trait->width =
+	trait->height = 0.0;
+}
+
+char *
+lsm_box_trait_to_string (LsmTrait *abstract_trait)
+{
+	LsmBox *trait = (LsmBox *) abstract_trait;
+
+	return g_strdup_printf ("%g %g %g %g",
+				trait->x, trait->y,
+				trait->width, trait->height);
+}
+
+const LsmTraitClass lsm_box_trait_class = {
+	.size = sizeof (LsmBox),
+	.from_string = lsm_box_trait_from_string,
+	.to_string = lsm_box_trait_to_string
+};
+
diff --git a/src/lsmtraits.h b/src/lsmtraits.h
new file mode 100644
index 0000000..e7f5d3e
--- /dev/null
+++ b/src/lsmtraits.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2009 Emmanuel Pacaud
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_TRAITS_H
+#define LSM_TRAITS_H
+
+#include <lsm.h>
+
+G_BEGIN_DECLS
+
+typedef void * LsmTrait;
+
+typedef struct {
+	size_t		size;
+	void 		(*init)			(LsmTrait *abstract_trait, const void *trait_default);
+	void 		(*finalize)		(LsmTrait *abstract_trait);
+	void		(*from_string)		(LsmTrait *abstract_trait, char *string);
+	char * 		(*to_string)		(LsmTrait *abstract_trait);
+} LsmTraitClass;
+
+extern const LsmTraitClass lsm_null_trait_class;
+extern const LsmTraitClass lsm_double_trait_class;
+extern const LsmTraitClass lsm_box_trait_class;
+
+G_END_DECLS
+
+#endif



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