From 84feab41bb9aae3362414ee818139a149a705903 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 19 Mar 2010 17:18:19 -0400 Subject: Introduce a simple extension system for objects. This introduces a simple means of extending Evolution objects. Any GObject subclass wishing to be extensible need only call g_type_add_interface_static (type, E_TYPE_EXTENSIBLE, NULL); when registering its GType, and then at some point during initialization call e_extensible_load_extensions() to load extensions for that subclass. Extensions are implemented by subclassing EExtension, setting the GType being extended in EExtensionClass, and making sure its own GType gets registered at startup. This usually done while loading a GTypeModule. e_extension_get_extensible() provides extensions access to the object being extended. --- e-util/e-extensible.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 e-util/e-extensible.c (limited to 'e-util/e-extensible.c') diff --git a/e-util/e-extensible.c b/e-util/e-extensible.c new file mode 100644 index 0000000000..9960d31d9f --- /dev/null +++ b/e-util/e-extensible.c @@ -0,0 +1,112 @@ +/* + * e-extensible.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + */ + +#include "e-extensible.h" + +#include +#include + +static GQuark extensible_quark; + +static GPtrArray * +extensible_get_extensions (EExtensible *extensible) +{ + return g_object_get_qdata (G_OBJECT (extensible), extensible_quark); +} + +static void +extensible_load_extension (GType extension_type, + EExtensible *extensible) +{ + EExtensionClass *extension_class; + GType extensible_type; + GPtrArray *extensions; + EExtension *extension; + + extensible_type = G_OBJECT_TYPE (extensible); + extension_class = g_type_class_ref (extension_type); + + /* Only load extensions that extend the given extensible object. */ + if (!g_type_is_a (extensible_type, extension_class->extensible_type)) + goto exit; + + extension = g_object_new ( + extension_type, "extensible", extensible, NULL); + + extensions = extensible_get_extensions (extensible); + g_ptr_array_add (extensions, extension); + +exit: + g_type_class_unref (extension_class); +} + +static void +extensible_interface_init (EExtensibleInterface *interface) +{ + extensible_quark = g_quark_from_static_string ("e-extensible-quark"); +} + +GType +e_extensible_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EExtensibleInterface), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) extensible_interface_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + 0, /* instance_size */ + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_INTERFACE, "EExtensible", &type_info, 0); + + g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); + } + + return type; +} + +void +e_extensible_load_extensions (EExtensible *extensible) +{ + GPtrArray *extensions; + + g_return_if_fail (E_IS_EXTENSIBLE (extensible)); + + if (extensible_get_extensions (extensible) != NULL) + return; + + extensions = g_ptr_array_new_with_free_func ( + (GDestroyNotify) g_object_unref); + + g_object_set_qdata_full ( + G_OBJECT (extensible), extensible_quark, + extensions, (GDestroyNotify) g_ptr_array_unref); + + e_type_traverse ( + E_TYPE_EXTENSION, (ETypeFunc) + extensible_load_extension, extensible); +} -- cgit v1.2.3