]> Pileus Git - ~andy/gtk/blob - gtk/gtkmnemonichash.c
c9f38408c8ac383c0e1bd91e2429e5267fe2d396
[~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   gboolean overloaded;
117
118   targets = g_hash_table_lookup (mnemonic_hash->hash,
119                                  GUINT_TO_POINTER (keyval));
120   if (!targets)
121     return FALSE;
122   
123   overloaded = FALSE;
124   chosen_widget = NULL;
125   for (list = targets; list; list = list->next)
126     {
127       widget = GTK_WIDGET (list->data);
128       
129       if (GTK_WIDGET_IS_SENSITIVE (widget) &&
130           GTK_WIDGET_MAPPED (widget))
131         {
132           if (chosen_widget)
133             {
134               overloaded = TRUE;
135               break;
136             }
137           else
138             chosen_widget = widget;
139         }
140     }
141
142   if (chosen_widget)
143     {
144       /* For round robin we put the activated entry on
145        * the end of the list after activation
146        */
147       targets = g_slist_remove (targets, chosen_widget);
148       targets = g_slist_append (targets, chosen_widget);
149       g_hash_table_insert (mnemonic_hash->hash,
150                            GUINT_TO_POINTER (keyval),
151                            targets);
152
153       return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
154     }
155   return FALSE;
156 }
157
158 GSList *
159 _gtk_mnemonic_hash_lookup (GtkMnemonicHash *mnemonic_hash,
160                            guint            keyval)
161 {
162   return g_hash_table_lookup (mnemonic_hash->hash, GUINT_TO_POINTER (keyval));
163 }
164
165 static void
166 mnemonic_hash_foreach_func (gpointer key,
167                             gpointer value,
168                             gpointer data)
169 {
170   struct {
171     GtkMnemonicHashForeach func;
172     gpointer func_data;
173   } *info = data;
174
175   guint keyval = GPOINTER_TO_UINT (key);
176   GSList *targets = value;
177   
178   (*info->func) (keyval, targets, info->func_data);
179 }
180
181 void
182 _gtk_mnemonic_hash_foreach (GtkMnemonicHash       *mnemonic_hash,
183                             GtkMnemonicHashForeach func,
184                             gpointer               func_data)
185 {
186   struct {
187     GtkMnemonicHashForeach func;
188     gpointer func_data;
189   } info;
190   
191   info.func = func;
192   info.func_data = func_data;
193
194   g_hash_table_foreach (mnemonic_hash->hash,
195                         mnemonic_hash_foreach_func,
196                         &info);
197 }