]> Pileus Git - ~andy/gtk/blob - gtk/gtkwidgetpath.c
Compare region names as quarks in style matching.
[~andy/gtk] / gtk / gtkwidgetpath.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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 "config.h"
21
22 #include <string.h>
23
24 #include "gtkwidget.h"
25 #include "gtkwidgetpath.h"
26
27 typedef struct GtkPathElement GtkPathElement;
28
29 struct GtkPathElement
30 {
31   GType type;
32   gchar *name;
33   GHashTable *regions;
34 };
35
36 struct GtkWidgetPath
37 {
38   GArray *elems; /* First element contains the described widget */
39 };
40
41 GtkWidgetPath *
42 gtk_widget_path_new (void)
43 {
44   GtkWidgetPath *path;
45
46   path = g_slice_new0 (GtkWidgetPath);
47   path->elems = g_array_new (FALSE, TRUE, sizeof (GtkPathElement));
48
49   return path;
50 }
51
52 GtkWidgetPath *
53 gtk_widget_path_copy (const GtkWidgetPath *path)
54 {
55   GtkWidgetPath *new_path;
56   guint i;
57
58   g_return_val_if_fail (path != NULL, NULL);
59
60   new_path = gtk_widget_path_new ();
61
62   for (i = 0; i < path->elems->len; i++)
63     {
64       GtkPathElement *elem, new = { 0 };
65
66       elem = &g_array_index (path->elems, GtkPathElement, i);
67
68       new.type = elem->type;
69       new.name = g_strdup (elem->name);
70
71       if (elem->regions)
72         {
73           GHashTableIter iter;
74           gpointer key, value;
75
76           g_hash_table_iter_init (&iter, elem->regions);
77           new.regions = g_hash_table_new (NULL, NULL);
78
79           while (g_hash_table_iter_next (&iter, &key, &value))
80             g_hash_table_insert (new.regions, key, value);
81         }
82
83       g_array_append_val (new_path->elems, new);
84     }
85
86   return new_path;
87 }
88
89 void
90 gtk_widget_path_free (GtkWidgetPath *path)
91 {
92   guint i;
93
94   g_return_if_fail (path != NULL);
95
96   for (i = 0; i < path->elems->len; i++)
97     {
98       GtkPathElement *elem;
99
100       elem = &g_array_index (path->elems, GtkPathElement, i);
101       g_free (elem->name);
102
103       if (elem->regions)
104         g_hash_table_destroy (elem->regions);
105     }
106
107   g_array_free (path->elems, TRUE);
108   g_slice_free (GtkWidgetPath, path);
109 }
110
111 guint
112 gtk_widget_path_length (const GtkWidgetPath *path)
113 {
114   g_return_val_if_fail (path != NULL, 0);
115
116   return path->elems->len;
117 }
118
119 guint
120 gtk_widget_path_prepend_type (GtkWidgetPath *path,
121                               GType          type)
122 {
123   GtkPathElement new = { 0 };
124
125   g_return_val_if_fail (path != NULL, 0);
126   g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), 0);
127
128   new.type = type;
129   g_array_append_val (path->elems, new);
130
131   return path->elems->len - 1;
132 }
133
134 GType
135 gtk_widget_path_get_element_type (const GtkWidgetPath *path,
136                                   guint                pos)
137 {
138   GtkPathElement *elem;
139
140   g_return_val_if_fail (path != NULL, G_TYPE_INVALID);
141   g_return_val_if_fail (pos < path->elems->len, G_TYPE_INVALID);
142
143   elem = &g_array_index (path->elems, GtkPathElement, pos);
144   return elem->type;
145 }
146
147 void
148 gtk_widget_path_set_element_type (GtkWidgetPath *path,
149                                   guint          pos,
150                                   GType          type)
151 {
152   GtkPathElement *elem;
153
154   g_return_if_fail (path != NULL);
155   g_return_if_fail (pos < path->elems->len);
156   g_return_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET));
157
158   elem = &g_array_index (path->elems, GtkPathElement, pos);
159   elem->type = type;
160 }
161
162 G_CONST_RETURN gchar *
163 gtk_widget_path_get_element_name (const GtkWidgetPath *path,
164                                   guint                pos)
165 {
166   GtkPathElement *elem;
167
168   g_return_val_if_fail (path != NULL, NULL);
169   g_return_val_if_fail (pos < path->elems->len, NULL);
170
171   elem = &g_array_index (path->elems, GtkPathElement, pos);
172   return elem->name;
173 }
174
175 void
176 gtk_widget_path_set_element_name (GtkWidgetPath *path,
177                                   guint          pos,
178                                   const gchar   *name)
179 {
180   GtkPathElement *elem;
181
182   g_return_if_fail (path != NULL);
183   g_return_if_fail (pos < path->elems->len);
184   g_return_if_fail (name != NULL);
185
186   elem = &g_array_index (path->elems, GtkPathElement, pos);
187
188   if (elem->name)
189     g_free (elem->name);
190
191   elem->name = g_strdup (name);
192 }
193
194 void
195 gtk_widget_path_iter_add_region (GtkWidgetPath      *path,
196                                  guint               pos,
197                                  const gchar        *name,
198                                  GtkChildClassFlags  flags)
199 {
200   GtkPathElement *elem;
201   GQuark qname;
202
203   g_return_if_fail (path != NULL);
204   g_return_if_fail (pos < path->elems->len);
205   g_return_if_fail (name != NULL);
206
207   elem = &g_array_index (path->elems, GtkPathElement, pos);
208   qname = g_quark_from_string (name);
209
210   if (!elem->regions)
211     elem->regions = g_hash_table_new (NULL, NULL);
212
213   g_hash_table_insert (elem->regions,
214                        GUINT_TO_POINTER (qname),
215                        GUINT_TO_POINTER (flags));
216 }
217
218 void
219 gtk_widget_path_iter_remove_region (GtkWidgetPath *path,
220                                     guint          pos,
221                                     const gchar   *name)
222 {
223   GtkPathElement *elem;
224   GQuark qname;
225
226   g_return_if_fail (path != NULL);
227   g_return_if_fail (pos < path->elems->len);
228   g_return_if_fail (name != NULL);
229
230   qname = g_quark_try_string (name);
231
232   if (qname == 0)
233     return;
234
235   elem = &g_array_index (path->elems, GtkPathElement, pos);
236
237   if (elem->regions)
238     g_hash_table_remove (elem->regions, GUINT_TO_POINTER (qname));
239 }
240
241 void
242 gtk_widget_path_iter_clear_regions (GtkWidgetPath *path,
243                                     guint          pos)
244 {
245   GtkPathElement *elem;
246
247   g_return_if_fail (path != NULL);
248   g_return_if_fail (pos < path->elems->len);
249
250   elem = &g_array_index (path->elems, GtkPathElement, pos);
251
252   if (elem->regions)
253     g_hash_table_remove_all (elem->regions);
254 }
255
256 GSList *
257 gtk_widget_path_iter_list_regions (const GtkWidgetPath *path,
258                                    guint                pos)
259 {
260   GtkPathElement *elem;
261   GHashTableIter iter;
262   GSList *list = NULL;
263   gpointer key;
264
265   g_return_val_if_fail (path != NULL, NULL);
266   g_return_val_if_fail (pos < path->elems->len, NULL);
267
268   elem = &g_array_index (path->elems, GtkPathElement, pos);
269
270   if (!elem->regions)
271     return NULL;
272
273   g_hash_table_iter_init (&iter, elem->regions);
274
275   while (g_hash_table_iter_next (&iter, &key, NULL))
276     {
277       GQuark qname;
278
279       qname = GPOINTER_TO_UINT (key);
280       list = g_slist_prepend (list, (gchar *) g_quark_to_string (qname));
281     }
282
283   return list;
284 }
285
286 gboolean
287 gtk_widget_path_iter_has_qregion (const GtkWidgetPath *path,
288                                   guint                pos,
289                                   GQuark               qname,
290                                   GtkChildClassFlags  *flags)
291 {
292   GtkPathElement *elem;
293   gpointer value;
294
295   g_return_val_if_fail (path != NULL, FALSE);
296   g_return_val_if_fail (pos < path->elems->len, FALSE);
297   g_return_val_if_fail (qname != 0, FALSE);
298
299   elem = &g_array_index (path->elems, GtkPathElement, pos);
300
301   if (!elem->regions)
302     return FALSE;
303
304   if (!g_hash_table_lookup_extended (elem->regions,
305                                      GUINT_TO_POINTER (qname),
306                                      NULL, &value))
307     return FALSE;
308
309   if (flags)
310     *flags = GPOINTER_TO_UINT (value);
311
312   return TRUE;
313 }
314
315 gboolean
316 gtk_widget_path_iter_has_region (const GtkWidgetPath *path,
317                                  guint                pos,
318                                  const gchar         *name,
319                                  GtkChildClassFlags  *flags)
320 {
321   GQuark qname;
322
323   g_return_val_if_fail (path != NULL, FALSE);
324   g_return_val_if_fail (pos < path->elems->len, FALSE);
325   g_return_val_if_fail (name != NULL, FALSE);
326
327   qname = g_quark_try_string (name);
328
329   if (qname == 0)
330     return FALSE;
331
332   return gtk_widget_path_iter_has_qregion (path, pos, qname, flags);
333 }
334
335 GType
336 gtk_widget_path_get_widget_type (const GtkWidgetPath *path)
337 {
338   GtkPathElement *elem;
339
340   g_return_val_if_fail (path != NULL, G_TYPE_INVALID);
341
342   elem = &g_array_index (path->elems, GtkPathElement, 0);
343   return elem->type;
344 }
345
346 gboolean
347 gtk_widget_path_is_type (const GtkWidgetPath *path,
348                          GType                type)
349 {
350   GtkPathElement *elem;
351
352   g_return_val_if_fail (path != NULL, FALSE);
353   g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), FALSE);
354
355   elem = &g_array_index (path->elems, GtkPathElement, 0);
356
357   if (elem->type == type ||
358       g_type_is_a (elem->type, type))
359     return TRUE;
360
361   return FALSE;
362 }
363
364 gboolean
365 gtk_widget_path_has_parent (const GtkWidgetPath *path,
366                             GType                type)
367 {
368   guint i;
369
370   g_return_val_if_fail (path != NULL, FALSE);
371   g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), FALSE);
372
373   for (i = 1; i < path->elems->len; i++)
374     {
375       GtkPathElement *elem;
376
377       elem = &g_array_index (path->elems, GtkPathElement, i);
378
379       if (elem->type == type ||
380           g_type_is_a (elem->type, type))
381         return TRUE;
382     }
383
384   return FALSE;
385 }
386
387 #define __GTK_WIDGET_PATH_C__
388 #include "gtkaliasdef.c"