]> Pileus Git - ~andy/gtk/blob - gtk/gtkmnemonichash.c
6258f8aed070347c257eff4970ba8d1c7ad93fa0
[~andy/gtk] / gtk / gtkmnemonichash.c
1 /* gtkmnemonichash.c: Sets of mnemonics with cycling
2  *
3  * GTK - The GTK+ 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 #include "gtkalias.h"
24
25 struct _GtkMnemnonicHash
26 {
27   GHashTable *hash;
28 };
29
30
31 GtkMnemonicHash *
32 _gtk_mnemonic_hash_new (void)
33 {
34   GtkMnemonicHash *mnemonic_hash = g_new (GtkMnemonicHash, 1);
35
36   mnemonic_hash->hash = g_hash_table_new (g_direct_hash, NULL);
37
38   return mnemonic_hash;
39 }
40
41 static void
42 mnemonic_hash_free_foreach (gpointer    key,
43                             gpointer    value,
44                             gpointer    user)
45 {
46   guint keyval = GPOINTER_TO_UINT (key);
47   GSList *targets = value;
48
49   gchar *name = gtk_accelerator_name (keyval, 0);
50       
51   g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
52              name, targets->data);
53   g_free (name);
54   
55   g_slist_free (targets);
56 }
57
58 void
59 _gtk_mnemonic_hash_free (GtkMnemonicHash *mnemonic_hash)
60 {
61   g_hash_table_foreach (mnemonic_hash->hash,
62                         mnemonic_hash_free_foreach,
63                         NULL);
64
65   g_hash_table_destroy (mnemonic_hash->hash);
66   g_free (mnemonic_hash);
67 }
68
69 void
70 _gtk_mnemonic_hash_add (GtkMnemonicHash *mnemonic_hash,
71                         guint            keyval,
72                         GtkWidget       *target)
73 {
74   gpointer key = GUINT_TO_POINTER (keyval);
75   GSList *targets, *new_targets;
76   
77   g_return_if_fail (GTK_IS_WIDGET (target));
78   
79   targets = g_hash_table_lookup (mnemonic_hash->hash, key);
80   g_return_if_fail (g_slist_find (targets, target) == NULL);
81
82   new_targets = g_slist_append (targets, target);
83   if (new_targets != targets)
84     g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
85 }
86
87 void
88 _gtk_mnemonic_hash_remove (GtkMnemonicHash *mnemonic_hash,
89                            guint           keyval,
90                            GtkWidget      *target)
91 {
92   gpointer key = GUINT_TO_POINTER (keyval);
93   GSList *targets, *new_targets;
94   
95   g_return_if_fail (GTK_IS_WIDGET (target));
96   
97   targets = g_hash_table_lookup (mnemonic_hash->hash, key);
98
99   g_return_if_fail (targets && g_slist_find (targets, target) != NULL);
100
101   new_targets = g_slist_remove (targets, target);
102   if (new_targets != targets)
103     {
104       if (new_targets == NULL)
105         g_hash_table_remove (mnemonic_hash->hash, key);
106       else
107         g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
108     }
109 }
110
111 gboolean
112 _gtk_mnemonic_hash_activate (GtkMnemonicHash *mnemonic_hash,
113                              guint            keyval)
114 {
115   GSList *list, *targets;
116   GtkWidget *widget, *chosen_widget;
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       
130       if (GTK_WIDGET_IS_SENSITIVE (widget) &&
131           GTK_WIDGET_MAPPED (widget) &&
132           widget->window &&
133           gdk_window_is_viewable (widget->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 }