diff options
author | Matthias Clasen <mclasen@redhat.com> | 2004-12-10 22:09:22 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2004-12-10 22:09:22 +0000 |
commit | f3a74ace5f69840657813cd68f441ceadea671e8 (patch) | |
tree | f7472b9e2844e5b6a983fc8586bf0b6d08edf6ca /gtk/gtkmnemonichash.c | |
parent | 5c98a5ebee6c2554d5d230e18091e071aca7292a (diff) | |
download | gtk+-f3a74ace5f69840657813cd68f441ceadea671e8.tar.gz |
Support no-Alt mnemnonics in menu bars (#101309, Owen Taylor)
2004-12-10 Matthias Clasen <mclasen@redhat.com>
Support no-Alt mnemnonics in menu bars (#101309, Owen Taylor)
* gtk/gtkwindow.c: Factor out mnemonic hash code into
a separate file.
* gtk/gtkmnemonichash.[hc]: Factored out mnemonic hash
code from gtkwindow.c.
* gtk/Makefile.am (gtk_c_sources): Add gtkmnemonichash.[hc].
* gtk/gtkmenushell.c (struct _GtkMenuShellPrivate): Give
menu shells their own mnemonic hash.
* gtk/gtkmenushell.h: Add private api to support mnemonics.
* gtk/gtklabel.c (gtk_label_setup_mnemonic): Add mnemonic to
the menushell mnemonic hash when inside a menu.
Diffstat (limited to 'gtk/gtkmnemonichash.c')
-rw-r--r-- | gtk/gtkmnemonichash.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/gtk/gtkmnemonichash.c b/gtk/gtkmnemonichash.c new file mode 100644 index 0000000000..c9f38408c8 --- /dev/null +++ b/gtk/gtkmnemonichash.c @@ -0,0 +1,197 @@ +/* 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#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; + 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); + + if (GTK_WIDGET_IS_SENSITIVE (widget) && + GTK_WIDGET_MAPPED (widget)) + { + 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); +} |