source: trunk/third/atk/atk/atkregistry.c @ 18245

Revision 18245, 8.1 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18244, which included commits to RCS files with non-trunk default branches.
Line 
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
23static AtkRegistry *default_registry = NULL;
24
25static void              atk_registry_init           (AtkRegistry      *instance,
26                                                      AtkRegistryClass *klass);
27static void              atk_registry_finalize       (GObject          *instance);
28static void              atk_registry_class_init     (AtkRegistryClass *klass);
29static AtkRegistry*      atk_registry_new            (void);
30
31static gpointer parent_class = NULL;
32
33GType
34atk_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
60static void
61atk_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 */
75static void
76atk_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
84static void
85atk_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
93static AtkRegistry *
94atk_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
105static void
106atk_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 **/
128void
129atk_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 **/
174GType
175atk_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: an #AtkObjectFactory appropriate for creating #AtkObjects
210 * appropriate for @type.
211 **/
212AtkObjectFactory*
213atk_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: a default implementation of the #AtkObjectFactory/type
261 * registry
262 **/
263AtkRegistry*
264atk_get_default_registry (void)
265{
266  if (!default_registry)
267    {
268      default_registry = atk_registry_new ();
269    }
270  return default_registry;
271}
Note: See TracBrowser for help on using the repository browser.