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