summaryrefslogtreecommitdiff
path: root/gtk/gtkitemfactory.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>1998-08-12 16:49:13 +0000
committerOwen Taylor <otaylor@src.gnome.org>1998-08-12 16:49:13 +0000
commit4af7480f8f64bd7709500bc27af91e2243898969 (patch)
tree1045a3d1e843fdbb3a0390ee591e9d84257ec8ee /gtk/gtkitemfactory.c
parent5d270c2f450000cea208443142e7284c23e7af9d (diff)
downloadgtk+-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.c114
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,