]> Pileus Git - ~andy/gtk/blob - gtk/gtkwidgetpath.c
Remove gtkalias from style context code.
[~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   GQuark name;
33   GHashTable *regions;
34   GArray *classes;
35 };
36
37 struct GtkWidgetPath
38 {
39   GArray *elems; /* First element contains the described widget */
40 };
41
42 GtkWidgetPath *
43 gtk_widget_path_new (void)
44 {
45   GtkWidgetPath *path;
46
47   path = g_slice_new0 (GtkWidgetPath);
48   path->elems = g_array_new (FALSE, TRUE, sizeof (GtkPathElement));
49
50   return path;
51 }
52
53 GtkWidgetPath *
54 gtk_widget_path_copy (const GtkWidgetPath *path)
55 {
56   GtkWidgetPath *new_path;
57   guint i;
58
59   g_return_val_if_fail (path != NULL, NULL);
60
61   new_path = gtk_widget_path_new ();
62
63   for (i = 0; i < path->elems->len; i++)
64     {
65       GtkPathElement *elem, new = { 0 };
66
67       elem = &g_array_index (path->elems, GtkPathElement, i);
68
69       new.type = elem->type;
70       new.name = elem->name;
71
72       if (elem->regions)
73         {
74           GHashTableIter iter;
75           gpointer key, value;
76
77           g_hash_table_iter_init (&iter, elem->regions);
78           new.regions = g_hash_table_new (NULL, NULL);
79
80           while (g_hash_table_iter_next (&iter, &key, &value))
81             g_hash_table_insert (new.regions, key, value);
82         }
83
84       g_array_append_val (new_path->elems, new);
85     }
86
87   return new_path;
88 }
89
90 void
91 gtk_widget_path_free (GtkWidgetPath *path)
92 {
93   guint i;
94
95   g_return_if_fail (path != NULL);
96
97   for (i = 0; i < path->elems->len; i++)
98     {
99       GtkPathElement *elem;
100
101       elem = &g_array_index (path->elems, GtkPathElement, i);
102
103       if (elem->regions)
104         g_hash_table_destroy (elem->regions);
105
106       if (elem->classes)
107         g_array_free (elem->classes, TRUE);
108     }
109
110   g_array_free (path->elems, TRUE);
111   g_slice_free (GtkWidgetPath, path);
112 }
113
114 guint
115 gtk_widget_path_length (const GtkWidgetPath *path)
116 {
117   g_return_val_if_fail (path != NULL, 0);
118
119   return path->elems->len;
120 }
121
122 guint
123 gtk_widget_path_prepend_type (GtkWidgetPath *path,
124                               GType          type)
125 {
126   GtkPathElement new = { 0 };
127
128   g_return_val_if_fail (path != NULL, 0);
129   g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), 0);
130
131   new.type = type;
132   g_array_append_val (path->elems, new);
133
134   return path->elems->len - 1;
135 }
136
137 GType
138 gtk_widget_path_iter_get_widget_type (const GtkWidgetPath *path,
139                                       guint                pos)
140 {
141   GtkPathElement *elem;
142
143   g_return_val_if_fail (path != NULL, G_TYPE_INVALID);
144   g_return_val_if_fail (pos < path->elems->len, G_TYPE_INVALID);
145
146   elem = &g_array_index (path->elems, GtkPathElement, pos);
147   return elem->type;
148 }
149
150 void
151 gtk_widget_path_iter_set_widget_type (GtkWidgetPath *path,
152                                       guint          pos,
153                                       GType          type)
154 {
155   GtkPathElement *elem;
156
157   g_return_if_fail (path != NULL);
158   g_return_if_fail (pos < path->elems->len);
159   g_return_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET));
160
161   elem = &g_array_index (path->elems, GtkPathElement, pos);
162   elem->type = type;
163 }
164
165 G_CONST_RETURN gchar *
166 gtk_widget_path_iter_get_name (const GtkWidgetPath *path,
167                                guint                pos)
168 {
169   GtkPathElement *elem;
170
171   g_return_val_if_fail (path != NULL, NULL);
172   g_return_val_if_fail (pos < path->elems->len, NULL);
173
174   elem = &g_array_index (path->elems, GtkPathElement, pos);
175   return g_quark_to_string (elem->name);
176 }
177
178 void
179 gtk_widget_path_iter_set_name (GtkWidgetPath *path,
180                                guint          pos,
181                                const gchar   *name)
182 {
183   GtkPathElement *elem;
184
185   g_return_if_fail (path != NULL);
186   g_return_if_fail (pos < path->elems->len);
187   g_return_if_fail (name != NULL);
188
189   elem = &g_array_index (path->elems, GtkPathElement, pos);
190
191   elem->name = g_quark_from_string (name);
192 }
193
194 gboolean
195 gtk_widget_path_iter_has_qname (const GtkWidgetPath *path,
196                                 guint                pos,
197                                 GQuark               qname)
198 {
199   GtkPathElement *elem;
200
201   g_return_val_if_fail (path != NULL, FALSE);
202   g_return_val_if_fail (qname != 0, FALSE);
203   g_return_val_if_fail (pos < path->elems->len, FALSE);
204
205   elem = &g_array_index (path->elems, GtkPathElement, pos);
206
207   return (elem->name == qname);
208 }
209
210 gboolean
211 gtk_widget_path_iter_has_name (const GtkWidgetPath *path,
212                                guint                pos,
213                                const gchar         *name)
214 {
215   GQuark qname;
216
217   g_return_val_if_fail (path != NULL, FALSE);
218   g_return_val_if_fail (name != NULL, FALSE);
219   g_return_val_if_fail (pos < path->elems->len, FALSE);
220
221   qname = g_quark_try_string (name);
222
223   if (qname == 0)
224     return FALSE;
225
226   return gtk_widget_path_iter_has_qname (path, pos, qname);
227 }
228
229 void
230 gtk_widget_path_iter_add_class (GtkWidgetPath *path,
231                                 guint          pos,
232                                 const gchar   *name)
233 {
234   GtkPathElement *elem;
235   gboolean added = FALSE;
236   GQuark qname;
237   guint i;
238
239   g_return_if_fail (path != NULL);
240   g_return_if_fail (pos < path->elems->len);
241   g_return_if_fail (name != NULL);
242
243   elem = &g_array_index (path->elems, GtkPathElement, pos);
244   qname = g_quark_from_string (name);
245
246   if (!elem->classes)
247     elem->classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
248
249   for (i = 0; i < elem->classes->len; i++)
250     {
251       GQuark quark;
252
253       quark = g_array_index (elem->classes, GQuark, i);
254
255       if (qname == quark)
256         {
257           /* Already there */
258           added = TRUE;
259           break;
260         }
261       if (qname < quark)
262         {
263           g_array_insert_val (elem->classes, i, qname);
264           added = TRUE;
265           break;
266         }
267     }
268
269   if (!added)
270     g_array_append_val (elem->classes, qname);
271 }
272
273 void
274 gtk_widget_path_iter_remove_class (GtkWidgetPath *path,
275                                    guint          pos,
276                                    const gchar   *name)
277 {
278   GtkPathElement *elem;
279   GQuark qname;
280   guint i;
281
282   g_return_if_fail (path != NULL);
283   g_return_if_fail (pos < path->elems->len);
284   g_return_if_fail (name != NULL);
285
286   qname = g_quark_try_string (name);
287
288   if (qname == 0)
289     return;
290
291   elem = &g_array_index (path->elems, GtkPathElement, pos);
292
293   if (!elem->classes)
294     return;
295
296   for (i = 0; i < elem->classes->len; i++)
297     {
298       GQuark quark;
299
300       quark = g_array_index (elem->classes, GQuark, i);
301
302       if (quark > qname)
303         break;
304       else if (quark == qname)
305         {
306           g_array_remove_index (elem->classes, i);
307           break;
308         }
309     }
310 }
311
312 void
313 gtk_widget_path_iter_clear_classes (GtkWidgetPath *path,
314                                     guint          pos)
315 {
316   GtkPathElement *elem;
317
318   g_return_if_fail (path != NULL);
319   g_return_if_fail (pos < path->elems->len);
320
321   elem = &g_array_index (path->elems, GtkPathElement, pos);
322
323   if (!elem->classes)
324     return;
325
326   if (elem->classes->len > 0)
327     g_array_remove_range (elem->classes, 0, elem->classes->len);
328 }
329
330 GSList *
331 gtk_widget_path_iter_list_classes (const GtkWidgetPath *path,
332                                    guint                pos)
333 {
334   GtkPathElement *elem;
335   GSList *list = NULL;
336   guint i;
337
338   g_return_val_if_fail (path != NULL, NULL);
339   g_return_val_if_fail (pos < path->elems->len, NULL);
340
341   elem = &g_array_index (path->elems, GtkPathElement, pos);
342
343   if (!elem->classes)
344     return NULL;
345
346   for (i = 0; i < elem->classes->len; i++)
347     {
348       GQuark quark;
349
350       quark = g_array_index (elem->classes, GQuark, i);
351       list = g_slist_prepend (list, (gchar *) g_quark_to_string (quark));
352     }
353
354   return g_slist_reverse (list);
355 }
356
357 gboolean
358 gtk_widget_path_iter_has_qclass (const GtkWidgetPath *path,
359                                  guint                pos,
360                                  GQuark               qname)
361 {
362   GtkPathElement *elem;
363   guint i;
364
365   g_return_val_if_fail (path != NULL, FALSE);
366   g_return_val_if_fail (pos < path->elems->len, FALSE);
367   g_return_val_if_fail (qname != 0, FALSE);
368
369   elem = &g_array_index (path->elems, GtkPathElement, pos);
370
371   if (!elem->classes)
372     return FALSE;
373
374   for (i = 0; i < elem->classes->len; i++)
375     {
376       GQuark quark;
377
378       quark = g_array_index (elem->classes, GQuark, i);
379
380       if (quark == qname)
381         return TRUE;
382       else if (quark > qname)
383         break;
384     }
385
386   return FALSE;
387 }
388
389 gboolean
390 gtk_widget_path_iter_has_class (const GtkWidgetPath *path,
391                                 guint                pos,
392                                 const gchar         *name)
393 {
394   GQuark qname;
395
396   g_return_val_if_fail (path != NULL, FALSE);
397   g_return_val_if_fail (pos < path->elems->len, FALSE);
398   g_return_val_if_fail (name != NULL, FALSE);
399
400   qname = g_quark_try_string (name);
401
402   if (qname == 0)
403     return FALSE;
404
405   return gtk_widget_path_iter_has_qclass (path, pos, qname);
406 }
407
408 void
409 gtk_widget_path_iter_add_region (GtkWidgetPath  *path,
410                                  guint           pos,
411                                  const gchar    *name,
412                                  GtkRegionFlags  flags)
413 {
414   GtkPathElement *elem;
415   GQuark qname;
416
417   g_return_if_fail (path != NULL);
418   g_return_if_fail (pos < path->elems->len);
419   g_return_if_fail (name != NULL);
420
421   elem = &g_array_index (path->elems, GtkPathElement, pos);
422   qname = g_quark_from_string (name);
423
424   if (!elem->regions)
425     elem->regions = g_hash_table_new (NULL, NULL);
426
427   g_hash_table_insert (elem->regions,
428                        GUINT_TO_POINTER (qname),
429                        GUINT_TO_POINTER (flags));
430 }
431
432 void
433 gtk_widget_path_iter_remove_region (GtkWidgetPath *path,
434                                     guint          pos,
435                                     const gchar   *name)
436 {
437   GtkPathElement *elem;
438   GQuark qname;
439
440   g_return_if_fail (path != NULL);
441   g_return_if_fail (pos < path->elems->len);
442   g_return_if_fail (name != NULL);
443
444   qname = g_quark_try_string (name);
445
446   if (qname == 0)
447     return;
448
449   elem = &g_array_index (path->elems, GtkPathElement, pos);
450
451   if (elem->regions)
452     g_hash_table_remove (elem->regions, GUINT_TO_POINTER (qname));
453 }
454
455 void
456 gtk_widget_path_iter_clear_regions (GtkWidgetPath *path,
457                                     guint          pos)
458 {
459   GtkPathElement *elem;
460
461   g_return_if_fail (path != NULL);
462   g_return_if_fail (pos < path->elems->len);
463
464   elem = &g_array_index (path->elems, GtkPathElement, pos);
465
466   if (elem->regions)
467     g_hash_table_remove_all (elem->regions);
468 }
469
470 GSList *
471 gtk_widget_path_iter_list_regions (const GtkWidgetPath *path,
472                                    guint                pos)
473 {
474   GtkPathElement *elem;
475   GHashTableIter iter;
476   GSList *list = NULL;
477   gpointer key;
478
479   g_return_val_if_fail (path != NULL, NULL);
480   g_return_val_if_fail (pos < path->elems->len, NULL);
481
482   elem = &g_array_index (path->elems, GtkPathElement, pos);
483
484   if (!elem->regions)
485     return NULL;
486
487   g_hash_table_iter_init (&iter, elem->regions);
488
489   while (g_hash_table_iter_next (&iter, &key, NULL))
490     {
491       GQuark qname;
492
493       qname = GPOINTER_TO_UINT (key);
494       list = g_slist_prepend (list, (gchar *) g_quark_to_string (qname));
495     }
496
497   return list;
498 }
499
500 gboolean
501 gtk_widget_path_iter_has_qregion (const GtkWidgetPath *path,
502                                   guint                pos,
503                                   GQuark               qname,
504                                   GtkRegionFlags      *flags)
505 {
506   GtkPathElement *elem;
507   gpointer value;
508
509   g_return_val_if_fail (path != NULL, FALSE);
510   g_return_val_if_fail (pos < path->elems->len, FALSE);
511   g_return_val_if_fail (qname != 0, FALSE);
512
513   elem = &g_array_index (path->elems, GtkPathElement, pos);
514
515   if (!elem->regions)
516     return FALSE;
517
518   if (!g_hash_table_lookup_extended (elem->regions,
519                                      GUINT_TO_POINTER (qname),
520                                      NULL, &value))
521     return FALSE;
522
523   if (flags)
524     *flags = GPOINTER_TO_UINT (value);
525
526   return TRUE;
527 }
528
529 gboolean
530 gtk_widget_path_iter_has_region (const GtkWidgetPath *path,
531                                  guint                pos,
532                                  const gchar         *name,
533                                  GtkRegionFlags      *flags)
534 {
535   GQuark qname;
536
537   g_return_val_if_fail (path != NULL, FALSE);
538   g_return_val_if_fail (pos < path->elems->len, FALSE);
539   g_return_val_if_fail (name != NULL, FALSE);
540
541   qname = g_quark_try_string (name);
542
543   if (qname == 0)
544     return FALSE;
545
546   return gtk_widget_path_iter_has_qregion (path, pos, qname, flags);
547 }
548
549 GType
550 gtk_widget_path_get_widget_type (const GtkWidgetPath *path)
551 {
552   GtkPathElement *elem;
553
554   g_return_val_if_fail (path != NULL, G_TYPE_INVALID);
555
556   elem = &g_array_index (path->elems, GtkPathElement, 0);
557   return elem->type;
558 }
559
560 gboolean
561 gtk_widget_path_is_type (const GtkWidgetPath *path,
562                          GType                type)
563 {
564   GtkPathElement *elem;
565
566   g_return_val_if_fail (path != NULL, FALSE);
567   g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), FALSE);
568
569   elem = &g_array_index (path->elems, GtkPathElement, 0);
570
571   if (elem->type == type ||
572       g_type_is_a (elem->type, type))
573     return TRUE;
574
575   return FALSE;
576 }
577
578 gboolean
579 gtk_widget_path_has_parent (const GtkWidgetPath *path,
580                             GType                type)
581 {
582   guint i;
583
584   g_return_val_if_fail (path != NULL, FALSE);
585   g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), FALSE);
586
587   for (i = 1; i < path->elems->len; i++)
588     {
589       GtkPathElement *elem;
590
591       elem = &g_array_index (path->elems, GtkPathElement, i);
592
593       if (elem->type == type ||
594           g_type_is_a (elem->type, type))
595         return TRUE;
596     }
597
598   return FALSE;
599 }