diff options
author | Owen Taylor <otaylor@redhat.com> | 1998-08-12 16:49:13 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 1998-08-12 16:49:13 +0000 |
commit | 4af7480f8f64bd7709500bc27af91e2243898969 (patch) | |
tree | 1045a3d1e843fdbb3a0390ee591e9d84257ec8ee /gtk/gtkitemfactory.c | |
parent | 5d270c2f450000cea208443142e7284c23e7af9d (diff) | |
download | gtk+-4af7480f8f64bd7709500bc27af91e2243898969.tar.gz |
Added gdk_text/string_extents() - too calculate all the metrics at once of
Tue Jul 21 12:42:01 1998 Owen Taylor <otaylor@redhat.com>
* gdk/gdk.h gdk/gdkfont.c: Added gdk_text/string_extents() -
too calculate all the metrics at once of a string, including
things which weren't calculated before.
* gtk/Makefile.am gtk/gtk.h gtk/gtktearoffmenu.[ch]: New
MenuItem type, that when put as the first thing in a
menu, makes the menu tearoff. Currently drawn as a
dashed line.
* gtk/gtkmenuitem.h gtk/gtkcheckmenuitem.c: Added a flag
"hide_on_activate" to the MenuItem class structure to allow
check and radio buttons to be changed with <Space> without
hiding the menu.
* gtk/gtkaccellabel.[ch]: Added new capabilities to set
a underline_group and underline_mods for the label -
accelerators added in the underline group matching
underline_mods will be displayed as an underline character.
This doesn't work - Save As needs to be underlined
as Save _As.
* gtk/gtkitemfactory.c:
- Create a AccelGroup for each MenuShell we create.
- If an '&' appears before a character 'c' in the path,
then make 'c' an accelerator in the menu's accel group,
and if the menuitem is menubar <alt>C an accelerator
in the itemfactory's accel group.
* gtk/gtklabel.[ch]: Add support for a pattern arg -
which is a string. If an '_' appears in this string,
the corresponding position in the label is underlined.
Add gtk_label_parse_uline() convenience function which
takes a string with embedded underlines, sets the
pattern and label, and returns the accelerator keyval.
* gtk/gtkmenu.[ch]: Make menus no longer a toplevel widget.
Instead, they create a GtkWindow and add themselves
to that. (When torn off, another new feature, they
create another GtkWindow to hold the torn off menu)
New function gtk_menu_set_tearoff_state()
* gtk/gtkenums.h gtk/gtkmenushell.[ch] gtk/gtkenums.h:
Added action signals for keyboard navigation of menus.
* gtk/gtkmenushell.c: Key press handler which activates
bindings for navigation, and accelerators, for handling
underline accelerators. Exported functions to select
and activate menu items in a menushell.
* gtk/testgtk.c: Added a new "Item Factory" test which
tests GtkItemFactory and the new keyboard navigation
of menus.
Diffstat (limited to 'gtk/gtkitemfactory.c')
-rw-r--r-- | gtk/gtkitemfactory.c | 114 |
1 files changed, 97 insertions, 17 deletions
diff --git a/gtk/gtkitemfactory.c b/gtk/gtkitemfactory.c index 0a624f0605..dd605d2344 100644 --- a/gtk/gtkitemfactory.c +++ b/gtk/gtkitemfactory.c @@ -27,8 +27,10 @@ #include "gtk/gtkmenuitem.h" #include "gtk/gtkradiomenuitem.h" #include "gtk/gtkcheckmenuitem.h" +#include "gtk/gtktearoffmenuitem.h" #include "gtk/gtkaccellabel.h" #include "gdk/gdkprivate.h" /* for gdk_progname */ +#include "gdk/gdkkeysyms.h" #include <string.h> #include <sys/stat.h> #include <fcntl.h> @@ -98,6 +100,8 @@ static const gchar *key_type_check_item = "<CheckItem>"; static GQuark quark_type_check_item = 0; static const gchar *key_type_toggle_item = "<ToggleItem>"; static GQuark quark_type_toggle_item = 0; +static const gchar *key_type_tearoff_item = "<Tearoff>"; +static GQuark quark_type_tearoff_item = 0; static const gchar *key_type_separator_item = "<Separator>"; static GQuark quark_type_separator_item = 0; static const gchar *key_type_branch = "<Branch>"; @@ -210,6 +214,7 @@ gtk_item_factory_class_init (GtkItemFactoryClass *class) quark_type_radio_item = g_quark_from_static_string (key_type_radio_item); quark_type_check_item = g_quark_from_static_string (key_type_check_item); quark_type_toggle_item = g_quark_from_static_string (key_type_toggle_item); + quark_type_tearoff_item = g_quark_from_static_string (key_type_tearoff_item); quark_type_separator_item = g_quark_from_static_string (key_type_separator_item); quark_type_branch = g_quark_from_static_string (key_type_branch); quark_type_last_branch = g_quark_from_static_string (key_type_last_branch); @@ -547,6 +552,7 @@ gtk_item_factory_construct (GtkItemFactory *ifactory, const gchar *path, GtkAccelGroup *accel_group) { + GtkAccelGroup *menu_group; guint len; g_return_if_fail (ifactory != NULL); @@ -579,6 +585,10 @@ gtk_item_factory_construct (GtkItemFactory *ifactory, NULL); gtk_object_ref (GTK_OBJECT (ifactory)); gtk_object_sink (GTK_OBJECT (ifactory)); + + menu_group = gtk_accel_group_new (); + gtk_accel_group_attach (menu_group, GTK_OBJECT (ifactory->widget)); + /* gtk_signal_connect_object_while_alive (GTK_OBJECT (ifactory->widget), "destroy", @@ -880,6 +890,44 @@ gtk_item_factory_get_widget_by_action (GtkItemFactory *ifactory, return NULL; } +static gboolean +gtk_item_factory_parse_path (gchar *str, + gchar **path, + gchar **parent_path, + gchar **item) +{ + gchar *p, *q; + + *path = g_strdup (str); + + p = q = *path; + while (*p) + { + if (*p != '_') + { + *q++ = *p; + } + p++; + } + *q = 0; + + *parent_path = g_strdup (*path); + p = strrchr (*parent_path, '/'); + if (!p) + { + g_warning ("GtkItemFactory: invalid entry path `%s'", str); + return FALSE; + } + *p = 0; + + p = strrchr (str, '/'); + p++; + + *item = g_strdup (p); + + return TRUE; +} + void gtk_item_factory_create_item (GtkItemFactory *ifactory, GtkItemFactoryEntry *entry, @@ -889,11 +937,15 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory, GtkWidget *parent; GtkWidget *widget; GSList *radio_group; + gchar *name; gchar *parent_path; - gchar *p; + gchar *path; + guint accel_key; guint type_id; GtkType type; gchar *item_type_path; + GtkAccelGroup *parent_accel_group = NULL; + GSList *tmp_list; g_return_if_fail (ifactory != NULL); g_return_if_fail (GTK_IS_ITEM_FACTORY (ifactory)); @@ -923,6 +975,8 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory, type = GTK_TYPE_RADIO_MENU_ITEM; else if (type_id == quark_type_check_item) type = GTK_TYPE_CHECK_MENU_ITEM; + else if (type_id == quark_type_tearoff_item) + type = GTK_TYPE_TEAROFF_MENU_ITEM; else if (type_id == quark_type_toggle_item) type = GTK_TYPE_CHECK_MENU_ITEM; else if (type_id == quark_type_separator_item) @@ -949,16 +1003,11 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory, return; } } - - parent_path = g_strdup (entry->path); - p = strrchr (parent_path, '/'); - if (!p) - { - g_warning ("GtkItemFactory: invalid entry path `%s'", entry->path); - return; - } - *p = 0; + if (!gtk_item_factory_parse_path (entry->path, + &path, &parent_path, &name)) + return; + parent = gtk_item_factory_get_widget (ifactory, parent_path); if (!parent) { @@ -977,9 +1026,10 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory, g_free (parent_path); g_return_if_fail (parent != NULL); - - p = strrchr (entry->path, '/'); - p++; + + tmp_list = gtk_accel_groups_from_object (GTK_OBJECT (parent)); + if (tmp_list) + parent_accel_group = tmp_list->data; widget = gtk_widget_new (type, "GtkWidget::visible", TRUE, @@ -993,22 +1043,50 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory, if (GTK_IS_CHECK_MENU_ITEM (widget)) gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (widget), TRUE); - if (type_id != quark_type_separator_item && *p) + if ((type_id != quark_type_separator_item) && + (type_id != quark_type_tearoff_item) && + *name) { GtkWidget *label; - + label = gtk_widget_new (GTK_TYPE_ACCEL_LABEL, - "GtkLabel::label", p, "GtkWidget::visible", TRUE, "GtkWidget::parent", widget, "GtkAccelLabel::accel_widget", widget, "GtkMisc::xalign", 0.0, NULL); + + accel_key = gtk_label_parse_uline (GTK_LABEL (label), name); + + if ((accel_key != GDK_VoidSymbol) && GTK_IS_MENU_BAR (parent)) + { + gtk_widget_add_accelerator (widget, + "activate_item", + ifactory->accel_group, + accel_key, GDK_MOD1_MASK, + GTK_ACCEL_LOCKED); + } + + if ((accel_key != GDK_VoidSymbol) && parent_accel_group) + { + gtk_widget_add_accelerator (widget, + "activate_item", + parent_accel_group, + accel_key, 0, + GTK_ACCEL_LOCKED); + } } + + g_free (name); + if (type_id == quark_type_branch || type_id == quark_type_last_branch) { + GtkAccelGroup *menu_group; + + menu_group = gtk_accel_group_new (); + if (type_id == quark_type_last_branch) gtk_menu_item_right_justify (GTK_MENU_ITEM (widget)); @@ -1016,11 +1094,13 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory, widget = gtk_widget_new (GTK_TYPE_MENU, NULL); + + gtk_accel_group_attach (menu_group, GTK_OBJECT (widget)); gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), widget); } gtk_item_factory_add_item (ifactory, - entry->path, entry->accelerator, + path, entry->accelerator, entry->callback, entry->callback_action, callback_data, callback_type, item_type_path, |