]> Pileus Git - ~andy/gtk/blob - gtk/gtkmnemonichash.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkmnemonichash.c
1 /* gtkmnemonichash.c: Sets of mnemonics with cycling
2  *
3  * GTK - The GIMP Toolkit
4  * Copyright (C) 2002, Red Hat Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "gtkmnemonichash.h"
21
22 struct _GtkMnemnonicHash
23 {
24   GHashTable *hash;
25 };
26
27
28 GtkMnemonicHash *
29 _gtk_mnemonic_hash_new (void)
30 {
31   GtkMnemonicHash *mnemonic_hash = g_new (GtkMnemonicHash, 1);
32
33   mnemonic_hash->hash = g_hash_table_new (g_direct_hash, NULL);
34
35   return mnemonic_hash;
36 }
37
38 static void
39 mnemonic_hash_free_foreach (gpointer    key,
40                             gpointer    value,
41                             gpointer    user)
42 {
43   guint keyval = GPOINTER_TO_UINT (key);
44   GSList *targets = value;
45
46   gchar *name = gtk_accelerator_name (keyval, 0);
47       
48   g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
49              name, targets->data);
50   g_free (name);
51   
52   g_slist_free (targets);
53 }
54
55 void
56 _gtk_mnemonic_hash_free (GtkMnemonicHash *mnemonic_hash)
57 {
58   g_hash_table_foreach (mnemonic_hash->hash,
59                         mnemonic_hash_free_foreach,
60                         NULL);
61
62   g_hash_table_destroy (mnemonic_hash->hash);
63   g_free (mnemonic_hash);
64 }
65
66 void
67 _gtk_mnemonic_hash_add (GtkMnemonicHash *mnemonic_hash,
68                         guint            keyval,
69                         GtkWidget       *target)
70 {
71   gpointer key = GUINT_TO_POINTER (keyval);
72   GSList *targets, *new_targets;
73   
74   g_return_if_fail (GTK_IS_WIDGET (target));
75   
76   targets = g_hash_table_lookup (mnemonic_hash->hash, key);
77   g_return_if_fail (g_slist_find (targets, target) == NULL);
78
79   new_targets = g_slist_append (targets, target);
80   if (new_targets != targets)
81     g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
82 }
83
84 void
85 _gtk_mnemonic_hash_remove (GtkMnemonicHash *mnemonic_hash,
86                            guint           keyval,
87                            GtkWidget      *target)
88 {
89   gpointer key = GUINT_TO_POINTER (keyval);
90   GSList *targets, *new_targets;
91   
92   g_return_if_fail (GTK_IS_WIDGET (target));
93   
94   targets = g_hash_table_lookup (mnemonic_hash->hash, key);
95
96   g_return_if_fail (targets && g_slist_find (targets, target) != NULL);
97
98   new_targets = g_slist_remove (targets, target);
99   if (new_targets != targets)
100     {
101       if (new_targets == NULL)
102         g_hash_table_remove (mnemonic_hash->hash, key);
103       else
104         g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
105     }
106 }
107
108 gboolean
109 _gtk_mnemonic_hash_activate (GtkMnemonicHash *mnemonic_hash,
110                              guint            keyval)
111 {
112   GSList *list, *targets;
113   GtkWidget *widget, *chosen_widget;
114   GdkWindow *window;
115   gboolean overloaded;
116
117   targets = g_hash_table_lookup (mnemonic_hash->hash,
118                                  GUINT_TO_POINTER (keyval));
119   if (!targets)
120     return FALSE;
121   
122   overloaded = FALSE;
123   chosen_widget = NULL;
124   for (list = targets; list; list = list->next)
125     {
126       widget = GTK_WIDGET (list->data);
127       window = gtk_widget_get_window (widget);
128
129       if (gtk_widget_is_sensitive (widget) &&
130           gtk_widget_get_mapped (widget) &&
131           window && gdk_window_is_viewable (window))
132         {
133           if (chosen_widget)
134             {
135               overloaded = TRUE;
136               break;
137             }
138           else
139             chosen_widget = widget;
140         }
141     }
142
143   if (chosen_widget)
144     {
145       /* For round robin we put the activated entry on
146        * the end of the list after activation
147        */
148       targets = g_slist_remove (targets, chosen_widget);
149       targets = g_slist_append (targets, chosen_widget);
150       g_hash_table_insert (mnemonic_hash->hash,
151                            GUINT_TO_POINTER (keyval),
152                            targets);
153
154       return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
155     }
156   return FALSE;
157 }
158
159 GSList *
160 _gtk_mnemonic_hash_lookup (GtkMnemonicHash *mnemonic_hash,
161                            guint            keyval)
162 {
163   return g_hash_table_lookup (mnemonic_hash->hash, GUINT_TO_POINTER (keyval));
164 }
165
166 static void
167 mnemonic_hash_foreach_func (gpointer key,
168                             gpointer value,
169                             gpointer data)
170 {
171   struct {
172     GtkMnemonicHashForeach func;
173     gpointer func_data;
174   } *info = data;
175
176   guint keyval = GPOINTER_TO_UINT (key);
177   GSList *targets = value;
178   
179   (*info->func) (keyval, targets, info->func_data);
180 }
181
182 void
183 _gtk_mnemonic_hash_foreach (GtkMnemonicHash       *mnemonic_hash,
184                             GtkMnemonicHashForeach func,
185                             gpointer               func_data)
186 {
187   struct {
188     GtkMnemonicHashForeach func;
189     gpointer func_data;
190   } info;
191   
192   info.func = func;
193   info.func_data = func_data;
194
195   g_hash_table_foreach (mnemonic_hash->hash,
196                         mnemonic_hash_foreach_func,
197                         &info);
198 }