| /* gtkmnemonichash.c: Sets of mnemonics with cycling |
| * |
| * GTK - The GIMP Toolkit |
| * Copyright (C) 2002, Red Hat Inc. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include "gtkmnemonichash.h" |
| |
| struct _GtkMnemnonicHash |
| { |
| GHashTable *hash; |
| }; |
| |
| |
| GtkMnemonicHash * |
| _gtk_mnemonic_hash_new (void) |
| { |
| GtkMnemonicHash *mnemonic_hash = g_new (GtkMnemonicHash, 1); |
| |
| mnemonic_hash->hash = g_hash_table_new (g_direct_hash, NULL); |
| |
| return mnemonic_hash; |
| } |
| |
| static void |
| mnemonic_hash_free_foreach (gpointer key, |
| gpointer value, |
| gpointer user) |
| { |
| guint keyval = GPOINTER_TO_UINT (key); |
| GSList *targets = value; |
| |
| gchar *name = gtk_accelerator_name (keyval, 0); |
| |
| g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)", |
| name, targets->data); |
| g_free (name); |
| |
| g_slist_free (targets); |
| } |
| |
| void |
| _gtk_mnemonic_hash_free (GtkMnemonicHash *mnemonic_hash) |
| { |
| g_hash_table_foreach (mnemonic_hash->hash, |
| mnemonic_hash_free_foreach, |
| NULL); |
| |
| g_hash_table_destroy (mnemonic_hash->hash); |
| g_free (mnemonic_hash); |
| } |
| |
| void |
| _gtk_mnemonic_hash_add (GtkMnemonicHash *mnemonic_hash, |
| guint keyval, |
| GtkWidget *target) |
| { |
| gpointer key = GUINT_TO_POINTER (keyval); |
| GSList *targets, *new_targets; |
| |
| g_return_if_fail (GTK_IS_WIDGET (target)); |
| |
| targets = g_hash_table_lookup (mnemonic_hash->hash, key); |
| g_return_if_fail (g_slist_find (targets, target) == NULL); |
| |
| new_targets = g_slist_append (targets, target); |
| if (new_targets != targets) |
| g_hash_table_insert (mnemonic_hash->hash, key, new_targets); |
| } |
| |
| void |
| _gtk_mnemonic_hash_remove (GtkMnemonicHash *mnemonic_hash, |
| guint keyval, |
| GtkWidget *target) |
| { |
| gpointer key = GUINT_TO_POINTER (keyval); |
| GSList *targets, *new_targets; |
| |
| g_return_if_fail (GTK_IS_WIDGET (target)); |
| |
| targets = g_hash_table_lookup (mnemonic_hash->hash, key); |
| |
| g_return_if_fail (targets && g_slist_find (targets, target) != NULL); |
| |
| new_targets = g_slist_remove (targets, target); |
| if (new_targets != targets) |
| { |
| if (new_targets == NULL) |
| g_hash_table_remove (mnemonic_hash->hash, key); |
| else |
| g_hash_table_insert (mnemonic_hash->hash, key, new_targets); |
| } |
| } |
| |
| gboolean |
| _gtk_mnemonic_hash_activate (GtkMnemonicHash *mnemonic_hash, |
| guint keyval) |
| { |
| GSList *list, *targets; |
| GtkWidget *widget, *chosen_widget; |
| GdkWindow *window; |
| gboolean overloaded; |
| |
| targets = g_hash_table_lookup (mnemonic_hash->hash, |
| GUINT_TO_POINTER (keyval)); |
| if (!targets) |
| return FALSE; |
| |
| overloaded = FALSE; |
| chosen_widget = NULL; |
| for (list = targets; list; list = list->next) |
| { |
| widget = GTK_WIDGET (list->data); |
| window = gtk_widget_get_window (widget); |
| |
| if (gtk_widget_is_sensitive (widget) && |
| gtk_widget_get_mapped (widget) && |
| window && gdk_window_is_viewable (window)) |
| { |
| if (chosen_widget) |
| { |
| overloaded = TRUE; |
| break; |
| } |
| else |
| chosen_widget = widget; |
| } |
| } |
| |
| if (chosen_widget) |
| { |
| /* For round robin we put the activated entry on |
| * the end of the list after activation |
| */ |
| targets = g_slist_remove (targets, chosen_widget); |
| targets = g_slist_append (targets, chosen_widget); |
| g_hash_table_insert (mnemonic_hash->hash, |
| GUINT_TO_POINTER (keyval), |
| targets); |
| |
| return gtk_widget_mnemonic_activate (chosen_widget, overloaded); |
| } |
| return FALSE; |
| } |
| |
| GSList * |
| _gtk_mnemonic_hash_lookup (GtkMnemonicHash *mnemonic_hash, |
| guint keyval) |
| { |
| return g_hash_table_lookup (mnemonic_hash->hash, GUINT_TO_POINTER (keyval)); |
| } |
| |
| static void |
| mnemonic_hash_foreach_func (gpointer key, |
| gpointer value, |
| gpointer data) |
| { |
| struct { |
| GtkMnemonicHashForeach func; |
| gpointer func_data; |
| } *info = data; |
| |
| guint keyval = GPOINTER_TO_UINT (key); |
| GSList *targets = value; |
| |
| (*info->func) (keyval, targets, info->func_data); |
| } |
| |
| void |
| _gtk_mnemonic_hash_foreach (GtkMnemonicHash *mnemonic_hash, |
| GtkMnemonicHashForeach func, |
| gpointer func_data) |
| { |
| struct { |
| GtkMnemonicHashForeach func; |
| gpointer func_data; |
| } info; |
| |
| info.func = func; |
| info.func_data = func_data; |
| |
| g_hash_table_foreach (mnemonic_hash->hash, |
| mnemonic_hash_foreach_func, |
| &info); |
| } |