updated changelog
[platform/upstream/evolution-data-server.git] / libebackend / e-extension.c
1 /*
2  * e-extension.c
3  *
4  * This library is free software you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation.
7  *
8  * This library is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 /**
19  * SECTION: e-extension
20  * @include: libebackend/libebackend.h
21  * @short_description: An abstract base class for extensions
22  *
23  * #EExtension provides a way to extend the functionality of objects
24  * that implement the #EExtensible interface.  #EExtension subclasses
25  * can target a particular extensible object type.  New instances of
26  * an extensible object type get paired with a new instance of each
27  * #EExtension subclass that targets the extensible object type.
28  *
29  * The first steps of writing a new extension are as follows:
30  *
31  * 1. Subclass #EExtension.
32  *
33  * 2. In the class initialization function, specify the #GType being
34  *    extended.  The #GType must implement the #EExtensible interface.
35  *
36  * 3. Register the extension's own #GType.  If the extension is to
37  *    be loaded dynamically using #GTypeModule, the type should be
38  *    registered in the library module's e_module_load() function.
39  **/
40
41 #include "e-extension.h"
42
43 #include <config.h>
44
45 #define E_EXTENSION_GET_PRIVATE(obj) \
46         (G_TYPE_INSTANCE_GET_PRIVATE \
47         ((obj), E_TYPE_EXTENSION, EExtensionPrivate))
48
49 struct _EExtensionPrivate {
50         gpointer extensible;  /* weak pointer */
51 };
52
53 enum {
54         PROP_0,
55         PROP_EXTENSIBLE
56 };
57
58 G_DEFINE_ABSTRACT_TYPE (
59         EExtension,
60         e_extension,
61         G_TYPE_OBJECT)
62
63 static void
64 extension_set_extensible (EExtension *extension,
65                           EExtensible *extensible)
66 {
67         EExtensionClass *class;
68         GType extensible_type;
69
70         g_return_if_fail (E_IS_EXTENSIBLE (extensible));
71         g_return_if_fail (extension->priv->extensible == NULL);
72
73         class = E_EXTENSION_GET_CLASS (extension);
74         extensible_type = G_OBJECT_TYPE (extensible);
75
76         /* Verify the EExtensible object is the type we want. */
77         if (!g_type_is_a (extensible_type, class->extensible_type)) {
78                 g_warning (
79                         "%s is meant to extend %s but was given an %s",
80                         G_OBJECT_TYPE_NAME (extension),
81                         g_type_name (class->extensible_type),
82                         g_type_name (extensible_type));
83                 return;
84         }
85
86         extension->priv->extensible = extensible;
87
88         g_object_add_weak_pointer (
89                 G_OBJECT (extensible), &extension->priv->extensible);
90 }
91
92 static void
93 extension_set_property (GObject *object,
94                         guint property_id,
95                         const GValue *value,
96                         GParamSpec *pspec)
97 {
98         switch (property_id) {
99                 case PROP_EXTENSIBLE:
100                         extension_set_extensible (
101                                 E_EXTENSION (object),
102                                 g_value_get_object (value));
103                         return;
104         }
105
106         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
107 }
108
109 static void
110 extension_get_property (GObject *object,
111                         guint property_id,
112                         GValue *value,
113                         GParamSpec *pspec)
114 {
115         switch (property_id) {
116                 case PROP_EXTENSIBLE:
117                         g_value_set_object (
118                                 value, e_extension_get_extensible (
119                                 E_EXTENSION (object)));
120                         return;
121         }
122
123         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
124 }
125
126 static void
127 extension_dispose (GObject *object)
128 {
129         EExtensionPrivate *priv;
130
131         priv = E_EXTENSION_GET_PRIVATE (object);
132
133         if (priv->extensible != NULL) {
134                 g_object_remove_weak_pointer (
135                         G_OBJECT (priv->extensible), &priv->extensible);
136                 priv->extensible = NULL;
137         }
138
139         /* Chain up to parent's dispose() method. */
140         G_OBJECT_CLASS (e_extension_parent_class)->dispose (object);
141 }
142
143 static void
144 e_extension_class_init (EExtensionClass *class)
145 {
146         GObjectClass *object_class;
147
148         g_type_class_add_private (class, sizeof (EExtensionPrivate));
149
150         object_class = G_OBJECT_CLASS (class);
151         object_class->set_property = extension_set_property;
152         object_class->get_property = extension_get_property;
153         object_class->dispose = extension_dispose;
154
155         g_object_class_install_property (
156                 object_class,
157                 PROP_EXTENSIBLE,
158                 g_param_spec_object (
159                         "extensible",
160                         "Extensible Object",
161                         "The object being extended",
162                         E_TYPE_EXTENSIBLE,
163                         G_PARAM_READWRITE |
164                         G_PARAM_CONSTRUCT_ONLY));
165 }
166
167 static void
168 e_extension_init (EExtension *extension)
169 {
170         extension->priv = E_EXTENSION_GET_PRIVATE (extension);
171 }
172
173 /**
174  * e_extension_get_extensible:
175  * @extension: an #EExtension
176  *
177  * Returns the object that @extension extends.
178  *
179  * Returns: the object being extended
180  *
181  * Since: 3.4
182  **/
183 EExtensible *
184 e_extension_get_extensible (EExtension *extension)
185 {
186         g_return_val_if_fail (E_IS_EXTENSION (extension), NULL);
187
188         return E_EXTENSIBLE (extension->priv->extensible);
189 }