]> Pileus Git - ~andy/gtk/blob - gtk/gtkmnemonichash.c
37ee01644ab41d83781d6ededa9a6a18dfc9eccb
[~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, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "gtkmnemonichash.h"
23
24 struct _GtkMnemnonicHash
25 {
26   GHashTable *hash;
27 };
28
29
30 GtkMnemonicHash *
31 _gtk_mnemonic_hash_new (void)
32 {
33   GtkMnemonicHash *mnemonic_hash = g_new (GtkMnemonicHash, 1);
34
35   mnemonic_hash->hash = g_hash_table_new (g_direct_hash, NULL);
36
37   return mnemonic_hash;
38 }
39
40 static void
41 mnemonic_hash_free_foreach (gpointer    key,
42                             gpointer    value,
43                             gpointer    user)
44 {
45   guint keyval = GPOINTER_TO_UINT (key);
46   GSList *targets = value;
47
48   gchar *name = gtk_accelerator_name (keyval, 0);
49       
50   g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
51              name, targets->data);
52   g_free (name);
53   
54   g_slist_free (targets);
55 }
56
57 void
58 _gtk_mnemonic_hash_free (GtkMnemonicHash *mnemonic_hash)
59 {
60   g_hash_table_foreach (mnemonic_hash->hash,
61                         mnemonic_hash_free_foreach,
62                         NULL);
63
64   g_hash_table_destroy (mnemonic_hash->hash);
65   g_free (mnemonic_hash);
66 }
67
68 void
69 _gtk_mnemonic_hash_add (GtkMnemonicHash *mnemonic_hash,
70                         guint            keyval,
71                         GtkWidget       *target)
72 {
73   gpointer key = GUINT_TO_POINTER (keyval);
74   GSList *targets, *new_targets;
75   
76   g_return_if_fail (GTK_IS_WIDGET (target));
77   
78   targets = g_hash_table_lookup (mnemonic_hash->hash, key);
79   g_return_if_fail (g_slist_find (targets, target) == NULL);
80
81   new_targets = g_slist_append (targets, target);
82   if (new_targets != targets)
83     g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
84 }
85
86 void
87 _gtk_mnemonic_hash_remove (GtkMnemonicHash *mnemonic_hash,
88                            guint           keyval,
89                            GtkWidget      *target)
90 {
91   gpointer key = GUINT_TO_POINTER (keyval);
92   GSList *targets, *new_targets;
93   
94   g_return_if_fail (GTK_IS_WIDGET (target));
95   
96   targets = g_hash_table_lookup (mnemonic_hash->hash, key);
97
98   g_return_if_fail (targets && g_slist_find (targets, target) != NULL);
99
100   new_targets = g_slist_remove (targets, target);
101   if (new_targets != targets)
102     {
103       if (new_targets == NULL)
104         g_hash_table_remove (mnemonic_hash->hash, key);
105       else
106         g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
107     }
108 }
109
110 gboolean
111 _gtk_mnemonic_hash_activate (GtkMnemonicHash *mnemonic_hash,
112                              guint            keyval)
113 {
114   GSList *list, *targets;
115   GtkWidget *widget, *chosen_widget;
116   GdkWindow *window;
117   gboolean overloaded;
118
119   targets = g_hash_table_lookup (mnemonic_hash->hash,
120                                  GUINT_TO_POINTER (keyval));
121   if (!targets)
122     return FALSE;
123   
124   overloaded = FALSE;
125   chosen_widget = NULL;
126   for (list = targets; list; list = list->next)
127     {
128       widget = GTK_WIDGET (list->data);
129       window = gtk_widget_get_window (widget);
130
131       if (gtk_widget_is_sensitive (widget) &&
132           gtk_widget_get_mapped (widget) &&
133           window && gdk_window_is_viewable (window))
134         {
135           if (chosen_widget)
136             {
137               overloaded = TRUE;
138               break;
139             }
140           else
141             chosen_widget = widget;
142         }
143     }
144
145   if (chosen_widget)
146     {
147       /* For round robin we put the activated entry on
148        * the end of the list after activation
149        */
150       targets = g_slist_remove (targets, chosen_widget);
151       targets = g_slist_append (targets, chosen_widget);
152       g_hash_table_insert (mnemonic_hash->hash,
153                            GUINT_TO_POINTER (keyval),
154                            targets);
155
156       return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
157     }
158   return FALSE;
159 }
160
161 GSList *
162 _gtk_mnemonic_hash_lookup (GtkMnemonicHash *mnemonic_hash,
163                            guint            keyval)
164 {
165   return g_hash_table_lookup (mnemonic_hash->hash, GUINT_TO_POINTER (keyval));
166 }
167
168 static void
169 mnemonic_hash_foreach_func (gpointer key,
170                             gpointer value,
171                             gpointer data)
172 {
173   struct {
174     GtkMnemonicHashForeach func;
175     gpointer func_data;
176   } *info = data;
177
178   guint keyval = GPOINTER_TO_UINT (key);
179   GSList *targets = value;
180   
181   (*info->func) (keyval, targets, info->func_data);
182 }
183
184 void
185 _gtk_mnemonic_hash_foreach (GtkMnemonicHash       *mnemonic_hash,
186                             GtkMnemonicHashForeach func,
187                             gpointer               func_data)
188 {
189   struct {
190     GtkMnemonicHashForeach func;
191     gpointer func_data;
192   } info;
193   
194   info.func = func;
195   info.func_data = func_data;
196
197   g_hash_table_foreach (mnemonic_hash->hash,
198                         mnemonic_hash_foreach_func,
199                         &info);
200 }