Remove all instances of g_return_if_fail (foo != NULL); that are
[platform/upstream/atk.git] / atk / atkregistry.c
1 /* ATK - Accessibility Toolkit
2  * Copyright 2001 Sun Microsystems Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "atkregistry.h"
21 #include "atknoopobjectfactory.h"
22
23 static AtkRegistry *default_registry = NULL;
24
25 static void              atk_registry_init           (AtkRegistry      *instance,
26                                                       AtkRegistryClass *klass);
27 static void              atk_registry_finalize       (GObject          *instance);
28 static void              atk_registry_class_init     (AtkRegistryClass *klass);
29
30 static AtkRegistry*      atk_registry_new            ();
31
32 GType
33 atk_registry_get_type (void)
34 {
35   static GType type = 0;
36
37   if (!type)
38     {
39       static const GTypeInfo info =
40       {
41         sizeof (AtkRegistryClass),
42         (GBaseInitFunc) NULL,                             /* base_init */
43         (GBaseFinalizeFunc) NULL,                         /* base_finalize */
44         (GClassInitFunc) atk_registry_class_init,         /* class_init */
45         (GClassFinalizeFunc) NULL,                        /* class_finalize */
46         NULL,                                             /* class_data */
47         sizeof (AtkRegistry),                             /* instance size */
48         0,                                                /* n_preallocs */
49         (GInstanceInitFunc) atk_registry_init,            /* instance init */
50         NULL                                              /* value table */
51       };
52
53       type = g_type_register_static (G_TYPE_OBJECT, "AtkRegistry", &info, 0);
54     }
55
56   return type;
57 }
58
59 static void
60 atk_registry_class_init (AtkRegistryClass *klass)
61 {
62   GObjectClass *object_class;
63
64   /* is paranoia appropriate in a class initializer ? */
65   g_return_if_fail (G_IS_OBJECT_CLASS (klass));
66
67   object_class = G_OBJECT_CLASS (klass);
68   object_class->finalize = atk_registry_finalize;
69   default_registry = atk_registry_new ();
70 }
71
72 #if 0
73 /*
74  * Cannot define a class_finalize function when calling
75  * g_type_register_static()
76  */
77 static void
78 atk_registry_class_finalize (GObjectClass *klass)
79 {
80   g_return_if_fail (ATK_IS_REGISTRY_CLASS (klass));
81
82   g_free (default_registry);
83 }
84 #endif
85
86 static void
87 atk_registry_init (AtkRegistry *instance, AtkRegistryClass *klass)
88 {
89   instance->factory_type_registry = g_hash_table_new ((GHashFunc) NULL, 
90                                                       (GEqualFunc) NULL);
91   instance->factory_singleton_cache = g_hash_table_new ((GHashFunc) NULL, 
92                                                         (GEqualFunc) NULL);
93 }
94
95 static AtkRegistry*
96 atk_registry_new ()
97 {
98   GObject *object;
99
100   object = g_object_new (ATK_TYPE_REGISTRY, NULL);
101
102   g_return_val_if_fail (ATK_IS_REGISTRY (object), NULL);
103
104   return (AtkRegistry *) object;
105 }
106
107 static void
108 atk_registry_finalize (GObject *instance)
109 {
110   AtkRegistry *registry;
111
112   g_return_if_fail (ATK_IS_REGISTRY (instance));
113   registry = ATK_REGISTRY (instance);
114   g_free (registry->factory_type_registry);
115   g_free (registry->factory_singleton_cache);
116 }
117
118 /**
119  * atk_registry_set_factory_type:
120  * @registry: the #AtkRegistry in which to register the type association
121  * @type: an #AtkObject type 
122  * @factory_type: an #AtkObjectFactory type to associate with @type.  Must
123  * implement AtkObject appropriate for @type.
124  *
125  * Associate an #AtkObjectFactory subclass with a #GType. Note:
126  * The associated @factory_type will thereafter be responsible for
127  * the creation of new #AtkObject implementations for instances
128  * appropriate for @type.
129  **/
130 void
131 atk_registry_set_factory_type (AtkRegistry *registry,
132                                GType type,
133                                GType factory_type)
134 {
135   GType old_type;
136   gpointer value;
137   AtkObjectFactory *old_factory;
138
139   g_return_if_fail (ATK_IS_REGISTRY (registry));
140
141   value = g_hash_table_lookup (registry->factory_type_registry, 
142                                   GUINT_TO_POINTER (type));
143   old_type = GPOINTER_TO_UINT (value);
144   if (old_type && old_type != factory_type)
145     {
146       g_hash_table_remove (registry->factory_type_registry, 
147                            GUINT_TO_POINTER (type));
148       /*
149        * If the old factory was created, notify it that it has
150        * been replaced, then free it.
151        */
152       old_factory = g_hash_table_lookup (registry->factory_singleton_cache, 
153                                          GUINT_TO_POINTER (old_type));
154       if (old_factory)
155         {
156           atk_object_factory_invalidate (old_factory);
157           g_type_free_instance ((GTypeInstance *) old_factory);
158         }
159     }
160   g_hash_table_insert (registry->factory_type_registry, 
161                        GUINT_TO_POINTER (type), 
162                        GUINT_TO_POINTER (factory_type));
163 }
164
165 /**
166  * atk_registry_get_factory_type:
167  * @registry: an #AtkRegistry
168  * @type: a #GType with which to look up the associated #AtkObjectFactory
169  * subclass
170  *
171  * Provides a #GType indicating the #AtkObjectFactory subclass
172  * associated with @type.
173  *
174  * Returns: a #GType associated with type @type
175  **/
176 GType
177 atk_registry_get_factory_type (AtkRegistry *registry,
178                                GType type)
179 {
180   GType factory_type;
181   gpointer value;
182
183   /*
184    * look up factory type in first hash;
185    * if there isn't an explicitly registered factory type,
186    * try inheriting one...
187    */
188   do {
189     value =
190         g_hash_table_lookup (registry->factory_type_registry, 
191                              GUINT_TO_POINTER (type));
192     type = g_type_parent (type);
193     if (type == G_TYPE_INVALID)
194       {
195         break;
196       }
197   } while (value == NULL);
198
199   factory_type = GPOINTER_TO_UINT (value);
200   return factory_type;
201 }
202
203 /**
204  * atk_registry_get_factory:
205  * @registry: an #AtkRegistry
206  * @type: a #GType with which to look up the associated #AtkObjectFactory
207  *
208  * Gets an #AtkObjectFactory appropriate for creating #AtkObjects
209  * appropriate for @type.
210  *
211  * Returns: an #AtkObjectFactory appropriate for creating #AtkObjects
212  * appropriate for @type.
213  **/
214 AtkObjectFactory*
215 atk_registry_get_factory (AtkRegistry *registry,
216                           GType type)
217 {
218   gpointer factory_pointer = NULL;
219   GType factory_type;
220
221   factory_type = atk_registry_get_factory_type (registry, type);
222
223   if (factory_type == G_TYPE_INVALID)
224   {
225   /* Factory type has not been specified for this object type */
226     static AtkObjectFactory* default_factory = NULL;
227
228     if (!default_factory)
229       default_factory = atk_no_op_object_factory_new ();
230
231     return default_factory;
232   }
233
234   /* ask second hashtable for instance of factory type */
235   factory_pointer =
236         g_hash_table_lookup (registry->factory_singleton_cache, 
237         GUINT_TO_POINTER (factory_type));
238
239   /* if there isn't one already, create one and save it */
240   if (factory_pointer == NULL)
241     {
242       factory_pointer = g_type_create_instance (factory_type);
243       g_hash_table_insert (registry->factory_singleton_cache,
244                            GUINT_TO_POINTER (factory_type),
245                            factory_pointer);
246     }
247
248   return ATK_OBJECT_FACTORY (factory_pointer);
249 }
250
251 /**
252  *atk_get_default_registry:
253  *
254  * Gets a default implementation of the #AtkObjectFactory/type
255  * registry.
256  * Note: For most toolkit maintainers, this will be the correct
257  * registry for registering new #AtkObject factories. Following
258  * a call to this function, maintainers may call atk_registry_set_factory_type()
259  * to associate an #AtkObjectFactory subclass with the GType of objects
260  * for whom accessibility information will be provided.
261  *
262  * Returns: a default implementation of the #AtkObjectFactory/type
263  * registry
264  **/
265 AtkRegistry*
266 atk_get_default_registry ()
267 {
268   if (!default_registry)
269   {
270     default_registry = atk_registry_new();
271   }
272   return default_registry;
273 }