Updated FSF's address
[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, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "atkregistry.h"
19 #include "atknoopobjectfactory.h"
20
21 static AtkRegistry *default_registry = NULL;
22
23 static void              atk_registry_init           (AtkRegistry      *instance,
24                                                       AtkRegistryClass *klass);
25 static void              atk_registry_finalize       (GObject          *instance);
26 static void              atk_registry_class_init     (AtkRegistryClass *klass);
27 static AtkRegistry*      atk_registry_new            (void);
28
29 static gpointer parent_class = NULL;
30
31 GType
32 atk_registry_get_type (void)
33 {
34   static GType type = 0;
35
36   if (!type)
37     {
38       static const GTypeInfo info =
39       {
40         sizeof (AtkRegistryClass),
41         (GBaseInitFunc) NULL,                             /* base_init */
42         (GBaseFinalizeFunc) NULL,                         /* base_finalize */
43         (GClassInitFunc) atk_registry_class_init,         /* class_init */
44         (GClassFinalizeFunc) NULL,                        /* class_finalize */
45         NULL,                                             /* class_data */
46         sizeof (AtkRegistry),                             /* instance size */
47         0,                                                /* n_preallocs */
48         (GInstanceInitFunc) atk_registry_init,            /* instance init */
49         NULL                                              /* value table */
50       };
51
52       type = g_type_register_static (G_TYPE_OBJECT, "AtkRegistry", &info, 0);
53     }
54
55   return type;
56 }
57
58 static void
59 atk_registry_class_init (AtkRegistryClass *klass)
60 {
61   GObjectClass *object_class = (GObjectClass *) klass;
62
63   parent_class = g_type_class_peek_parent (klass);
64
65   object_class->finalize = atk_registry_finalize;
66 }
67
68 #if 0
69 /*
70  * Cannot define a class_finalize function when calling
71  * g_type_register_static()
72  */
73 static void
74 atk_registry_class_finalize (GObjectClass *klass)
75 {
76   g_return_if_fail (ATK_IS_REGISTRY_CLASS (klass));
77
78   g_object_unref (G_OBJECT (default_registry));
79 }
80 #endif
81
82 static void
83 atk_registry_init (AtkRegistry *instance, AtkRegistryClass *klass)
84 {
85   instance->factory_type_registry = g_hash_table_new ((GHashFunc) NULL, 
86                                                       (GEqualFunc) NULL);
87   instance->factory_singleton_cache = g_hash_table_new ((GHashFunc) NULL, 
88                                                         (GEqualFunc) NULL);
89 }
90
91 static AtkRegistry *
92 atk_registry_new (void)
93 {
94   GObject *object;
95
96   object = g_object_new (ATK_TYPE_REGISTRY, NULL);
97
98   g_return_val_if_fail (ATK_IS_REGISTRY (object), NULL);
99
100   return (AtkRegistry *) object;
101 }
102
103 static void
104 atk_registry_finalize (GObject *object)
105 {
106   AtkRegistry *registry = ATK_REGISTRY (object);
107
108   g_hash_table_destroy (registry->factory_type_registry);
109   g_hash_table_destroy (registry->factory_singleton_cache);
110
111   G_OBJECT_CLASS (parent_class)->finalize (object);
112 }
113
114 /**
115  * atk_registry_set_factory_type:
116  * @registry: the #AtkRegistry in which to register the type association
117  * @type: an #AtkObject type 
118  * @factory_type: an #AtkObjectFactory type to associate with @type.  Must
119  * implement AtkObject appropriate for @type.
120  *
121  * Associate an #AtkObjectFactory subclass with a #GType. Note:
122  * The associated @factory_type will thereafter be responsible for
123  * the creation of new #AtkObject implementations for instances
124  * appropriate for @type.
125  **/
126 void
127 atk_registry_set_factory_type (AtkRegistry *registry,
128                                GType type,
129                                GType factory_type)
130 {
131   GType old_type;
132   gpointer value;
133   AtkObjectFactory *old_factory;
134
135   g_return_if_fail (ATK_IS_REGISTRY (registry));
136
137   value = g_hash_table_lookup (registry->factory_type_registry, 
138                                   (gpointer) type);
139   old_type = (GType) value;
140   if (old_type && old_type != factory_type)
141     {
142       g_hash_table_remove (registry->factory_type_registry, 
143                            (gpointer) type);
144       /*
145        * If the old factory was created, notify it that it has
146        * been replaced, then free it.
147        */
148       old_factory = g_hash_table_lookup (registry->factory_singleton_cache, 
149                                          (gpointer) old_type);
150       if (old_factory)
151         {
152           atk_object_factory_invalidate (old_factory);
153           g_type_free_instance ((GTypeInstance *) old_factory);
154         }
155     }
156   g_hash_table_insert (registry->factory_type_registry, 
157                        (gpointer) type, 
158                        (gpointer) factory_type);
159 }
160
161 /**
162  * atk_registry_get_factory_type:
163  * @registry: an #AtkRegistry
164  * @type: a #GType with which to look up the associated #AtkObjectFactory
165  * subclass
166  *
167  * Provides a #GType indicating the #AtkObjectFactory subclass
168  * associated with @type.
169  *
170  * Returns: a #GType associated with type @type
171  **/
172 GType
173 atk_registry_get_factory_type (AtkRegistry *registry,
174                                GType type)
175 {
176   GType factory_type;
177   gpointer value;
178
179   /*
180    * look up factory type in first hash;
181    * if there isn't an explicitly registered factory type,
182    * try inheriting one...
183    */
184   do {
185     value =
186         g_hash_table_lookup (registry->factory_type_registry, 
187                              (gpointer) type);
188     type = g_type_parent (type);
189     if (type == G_TYPE_INVALID)
190       {
191         break;
192       }
193   } while (value == NULL);
194
195   factory_type = (GType) value;
196   return factory_type;
197 }
198
199 /**
200  * atk_registry_get_factory:
201  * @registry: an #AtkRegistry
202  * @type: a #GType with which to look up the associated #AtkObjectFactory
203  *
204  * Gets an #AtkObjectFactory appropriate for creating #AtkObjects
205  * appropriate for @type.
206  *
207  * Returns: (transfer none): an #AtkObjectFactory appropriate for creating
208  * #AtkObjects appropriate for @type.
209  **/
210 AtkObjectFactory*
211 atk_registry_get_factory (AtkRegistry *registry,
212                           GType type)
213 {
214   gpointer factory_pointer = NULL;
215   GType factory_type;
216
217   factory_type = atk_registry_get_factory_type (registry, type);
218
219   if (factory_type == G_TYPE_INVALID)
220   {
221   /* Factory type has not been specified for this object type */
222     static AtkObjectFactory* default_factory = NULL;
223
224     if (!default_factory)
225       default_factory = atk_no_op_object_factory_new ();
226
227     return default_factory;
228   }
229
230   /* ask second hashtable for instance of factory type */
231   factory_pointer =
232         g_hash_table_lookup (registry->factory_singleton_cache, 
233         (gpointer) factory_type);
234
235   /* if there isn't one already, create one and save it */
236   if (factory_pointer == NULL)
237     {
238       factory_pointer = g_type_create_instance (factory_type);
239       g_hash_table_insert (registry->factory_singleton_cache,
240                            (gpointer) factory_type,
241                            factory_pointer);
242     }
243
244   return ATK_OBJECT_FACTORY (factory_pointer);
245 }
246
247 /**
248  * atk_get_default_registry:
249  *
250  * Gets a default implementation of the #AtkObjectFactory/type
251  * registry.
252  * Note: For most toolkit maintainers, this will be the correct
253  * registry for registering new #AtkObject factories. Following
254  * a call to this function, maintainers may call atk_registry_set_factory_type()
255  * to associate an #AtkObjectFactory subclass with the GType of objects
256  * for whom accessibility information will be provided.
257  *
258  * Returns: (transfer full): a default implementation of the
259  * #AtkObjectFactory/type registry
260  **/
261 AtkRegistry*
262 atk_get_default_registry (void)
263 {
264   if (!default_registry)
265     {
266       default_registry = atk_registry_new ();
267     }
268   return default_registry;
269 }