diff --git a/ChangeLog b/ChangeLog index c108495679..6da4b19804 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,48 @@ +Wed Mar 10 00:11:32 1999 Tim Janik + + * gtk/testgtk.c (create_item_factory): unref the item factory after + window's destruction. + + * gtk/gtkmenushell.c (gtk_menu_shell_activate_item): keep a reference + count on the menu shell around the menu item's activation, since the + signal emission may cause menu shell destruction. + + * gtk/gtkitemfactory.c: + the previous code leaked one accel group per menu. we use + gtk_menu_get_uline_accel_group() now to fix that, and with that + also create the underline accelerator group of the menus only if + required (i.e. an underline accelerator has been specified). + (gtk_item_factory_construct): + (gtk_item_factory_create_item): removed code that would create an + extra accel group for the menu (and leak references). + (gtk_item_factory_create_item): adapted the underline accelerator + installation code to properly feature gtk_menu_get_uline_accel_group(). + + * gtk/gtkmenu.[hc]: added gtk_menu_get_accel_group() to retrive + menu->accel_group, this may return NULL if the accelerator group + hasn't been set yet. + added gtk_menu_get_uline_accel_group() to retrive the underline + accelerator group of the menu, this will be created on demand + and proper care is taken about its reference count. + + * gtk/gtkitemfactory.h: + * gtk/gtkitemfactory.c: + dumped the approach of keeping a widgets by action list on the + factory since the factory<->widget destroy negotiation didn't work + and would be hard to get going at all. instead we keep a list of + GtkItemFactoryItem items on the factory (GtkItemFactoryItems are + persistant throughout a program's life time). + also, i removed the static const gchar *key_* variables, and made + them inline strings (they weren't actually used anyways). + (gtk_item_factory_add_item): update ifactory->items. + (gtk_item_factory_destroy): destroy ifactory->items (and remove + the item factory pointer from the remaining ifactory widgets). + (gtk_item_factory_get_widget_by_action): walk the GtkItemFactoryItem + list to find the widget. + (gtk_item_factory_get_item): new function that works around + gtk_item_factory_get_widget() limitations, this function will only + return menu items, even for entries. + Tue Mar 9 01:01:28 1999 Tim Janik * gdk/gdkfont.c (gdk_font_load): first lookup the xfont ID in our diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index c108495679..6da4b19804 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,48 @@ +Wed Mar 10 00:11:32 1999 Tim Janik + + * gtk/testgtk.c (create_item_factory): unref the item factory after + window's destruction. + + * gtk/gtkmenushell.c (gtk_menu_shell_activate_item): keep a reference + count on the menu shell around the menu item's activation, since the + signal emission may cause menu shell destruction. + + * gtk/gtkitemfactory.c: + the previous code leaked one accel group per menu. we use + gtk_menu_get_uline_accel_group() now to fix that, and with that + also create the underline accelerator group of the menus only if + required (i.e. an underline accelerator has been specified). + (gtk_item_factory_construct): + (gtk_item_factory_create_item): removed code that would create an + extra accel group for the menu (and leak references). + (gtk_item_factory_create_item): adapted the underline accelerator + installation code to properly feature gtk_menu_get_uline_accel_group(). + + * gtk/gtkmenu.[hc]: added gtk_menu_get_accel_group() to retrive + menu->accel_group, this may return NULL if the accelerator group + hasn't been set yet. + added gtk_menu_get_uline_accel_group() to retrive the underline + accelerator group of the menu, this will be created on demand + and proper care is taken about its reference count. + + * gtk/gtkitemfactory.h: + * gtk/gtkitemfactory.c: + dumped the approach of keeping a widgets by action list on the + factory since the factory<->widget destroy negotiation didn't work + and would be hard to get going at all. instead we keep a list of + GtkItemFactoryItem items on the factory (GtkItemFactoryItems are + persistant throughout a program's life time). + also, i removed the static const gchar *key_* variables, and made + them inline strings (they weren't actually used anyways). + (gtk_item_factory_add_item): update ifactory->items. + (gtk_item_factory_destroy): destroy ifactory->items (and remove + the item factory pointer from the remaining ifactory widgets). + (gtk_item_factory_get_widget_by_action): walk the GtkItemFactoryItem + list to find the widget. + (gtk_item_factory_get_item): new function that works around + gtk_item_factory_get_widget() limitations, this function will only + return menu items, even for entries. + Tue Mar 9 01:01:28 1999 Tim Janik * gdk/gdkfont.c (gdk_font_load): first lookup the xfont ID in our diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index c108495679..6da4b19804 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,48 @@ +Wed Mar 10 00:11:32 1999 Tim Janik + + * gtk/testgtk.c (create_item_factory): unref the item factory after + window's destruction. + + * gtk/gtkmenushell.c (gtk_menu_shell_activate_item): keep a reference + count on the menu shell around the menu item's activation, since the + signal emission may cause menu shell destruction. + + * gtk/gtkitemfactory.c: + the previous code leaked one accel group per menu. we use + gtk_menu_get_uline_accel_group() now to fix that, and with that + also create the underline accelerator group of the menus only if + required (i.e. an underline accelerator has been specified). + (gtk_item_factory_construct): + (gtk_item_factory_create_item): removed code that would create an + extra accel group for the menu (and leak references). + (gtk_item_factory_create_item): adapted the underline accelerator + installation code to properly feature gtk_menu_get_uline_accel_group(). + + * gtk/gtkmenu.[hc]: added gtk_menu_get_accel_group() to retrive + menu->accel_group, this may return NULL if the accelerator group + hasn't been set yet. + added gtk_menu_get_uline_accel_group() to retrive the underline + accelerator group of the menu, this will be created on demand + and proper care is taken about its reference count. + + * gtk/gtkitemfactory.h: + * gtk/gtkitemfactory.c: + dumped the approach of keeping a widgets by action list on the + factory since the factory<->widget destroy negotiation didn't work + and would be hard to get going at all. instead we keep a list of + GtkItemFactoryItem items on the factory (GtkItemFactoryItems are + persistant throughout a program's life time). + also, i removed the static const gchar *key_* variables, and made + them inline strings (they weren't actually used anyways). + (gtk_item_factory_add_item): update ifactory->items. + (gtk_item_factory_destroy): destroy ifactory->items (and remove + the item factory pointer from the remaining ifactory widgets). + (gtk_item_factory_get_widget_by_action): walk the GtkItemFactoryItem + list to find the widget. + (gtk_item_factory_get_item): new function that works around + gtk_item_factory_get_widget() limitations, this function will only + return menu items, even for entries. + Tue Mar 9 01:01:28 1999 Tim Janik * gdk/gdkfont.c (gdk_font_load): first lookup the xfont ID in our diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index c108495679..6da4b19804 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,48 @@ +Wed Mar 10 00:11:32 1999 Tim Janik + + * gtk/testgtk.c (create_item_factory): unref the item factory after + window's destruction. + + * gtk/gtkmenushell.c (gtk_menu_shell_activate_item): keep a reference + count on the menu shell around the menu item's activation, since the + signal emission may cause menu shell destruction. + + * gtk/gtkitemfactory.c: + the previous code leaked one accel group per menu. we use + gtk_menu_get_uline_accel_group() now to fix that, and with that + also create the underline accelerator group of the menus only if + required (i.e. an underline accelerator has been specified). + (gtk_item_factory_construct): + (gtk_item_factory_create_item): removed code that would create an + extra accel group for the menu (and leak references). + (gtk_item_factory_create_item): adapted the underline accelerator + installation code to properly feature gtk_menu_get_uline_accel_group(). + + * gtk/gtkmenu.[hc]: added gtk_menu_get_accel_group() to retrive + menu->accel_group, this may return NULL if the accelerator group + hasn't been set yet. + added gtk_menu_get_uline_accel_group() to retrive the underline + accelerator group of the menu, this will be created on demand + and proper care is taken about its reference count. + + * gtk/gtkitemfactory.h: + * gtk/gtkitemfactory.c: + dumped the approach of keeping a widgets by action list on the + factory since the factory<->widget destroy negotiation didn't work + and would be hard to get going at all. instead we keep a list of + GtkItemFactoryItem items on the factory (GtkItemFactoryItems are + persistant throughout a program's life time). + also, i removed the static const gchar *key_* variables, and made + them inline strings (they weren't actually used anyways). + (gtk_item_factory_add_item): update ifactory->items. + (gtk_item_factory_destroy): destroy ifactory->items (and remove + the item factory pointer from the remaining ifactory widgets). + (gtk_item_factory_get_widget_by_action): walk the GtkItemFactoryItem + list to find the widget. + (gtk_item_factory_get_item): new function that works around + gtk_item_factory_get_widget() limitations, this function will only + return menu items, even for entries. + Tue Mar 9 01:01:28 1999 Tim Janik * gdk/gdkfont.c (gdk_font_load): first lookup the xfont ID in our diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index c108495679..6da4b19804 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,48 @@ +Wed Mar 10 00:11:32 1999 Tim Janik + + * gtk/testgtk.c (create_item_factory): unref the item factory after + window's destruction. + + * gtk/gtkmenushell.c (gtk_menu_shell_activate_item): keep a reference + count on the menu shell around the menu item's activation, since the + signal emission may cause menu shell destruction. + + * gtk/gtkitemfactory.c: + the previous code leaked one accel group per menu. we use + gtk_menu_get_uline_accel_group() now to fix that, and with that + also create the underline accelerator group of the menus only if + required (i.e. an underline accelerator has been specified). + (gtk_item_factory_construct): + (gtk_item_factory_create_item): removed code that would create an + extra accel group for the menu (and leak references). + (gtk_item_factory_create_item): adapted the underline accelerator + installation code to properly feature gtk_menu_get_uline_accel_group(). + + * gtk/gtkmenu.[hc]: added gtk_menu_get_accel_group() to retrive + menu->accel_group, this may return NULL if the accelerator group + hasn't been set yet. + added gtk_menu_get_uline_accel_group() to retrive the underline + accelerator group of the menu, this will be created on demand + and proper care is taken about its reference count. + + * gtk/gtkitemfactory.h: + * gtk/gtkitemfactory.c: + dumped the approach of keeping a widgets by action list on the + factory since the factory<->widget destroy negotiation didn't work + and would be hard to get going at all. instead we keep a list of + GtkItemFactoryItem items on the factory (GtkItemFactoryItems are + persistant throughout a program's life time). + also, i removed the static const gchar *key_* variables, and made + them inline strings (they weren't actually used anyways). + (gtk_item_factory_add_item): update ifactory->items. + (gtk_item_factory_destroy): destroy ifactory->items (and remove + the item factory pointer from the remaining ifactory widgets). + (gtk_item_factory_get_widget_by_action): walk the GtkItemFactoryItem + list to find the widget. + (gtk_item_factory_get_item): new function that works around + gtk_item_factory_get_widget() limitations, this function will only + return menu items, even for entries. + Tue Mar 9 01:01:28 1999 Tim Janik * gdk/gdkfont.c (gdk_font_load): first lookup the xfont ID in our diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index c108495679..6da4b19804 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,48 @@ +Wed Mar 10 00:11:32 1999 Tim Janik + + * gtk/testgtk.c (create_item_factory): unref the item factory after + window's destruction. + + * gtk/gtkmenushell.c (gtk_menu_shell_activate_item): keep a reference + count on the menu shell around the menu item's activation, since the + signal emission may cause menu shell destruction. + + * gtk/gtkitemfactory.c: + the previous code leaked one accel group per menu. we use + gtk_menu_get_uline_accel_group() now to fix that, and with that + also create the underline accelerator group of the menus only if + required (i.e. an underline accelerator has been specified). + (gtk_item_factory_construct): + (gtk_item_factory_create_item): removed code that would create an + extra accel group for the menu (and leak references). + (gtk_item_factory_create_item): adapted the underline accelerator + installation code to properly feature gtk_menu_get_uline_accel_group(). + + * gtk/gtkmenu.[hc]: added gtk_menu_get_accel_group() to retrive + menu->accel_group, this may return NULL if the accelerator group + hasn't been set yet. + added gtk_menu_get_uline_accel_group() to retrive the underline + accelerator group of the menu, this will be created on demand + and proper care is taken about its reference count. + + * gtk/gtkitemfactory.h: + * gtk/gtkitemfactory.c: + dumped the approach of keeping a widgets by action list on the + factory since the factory<->widget destroy negotiation didn't work + and would be hard to get going at all. instead we keep a list of + GtkItemFactoryItem items on the factory (GtkItemFactoryItems are + persistant throughout a program's life time). + also, i removed the static const gchar *key_* variables, and made + them inline strings (they weren't actually used anyways). + (gtk_item_factory_add_item): update ifactory->items. + (gtk_item_factory_destroy): destroy ifactory->items (and remove + the item factory pointer from the remaining ifactory widgets). + (gtk_item_factory_get_widget_by_action): walk the GtkItemFactoryItem + list to find the widget. + (gtk_item_factory_get_item): new function that works around + gtk_item_factory_get_widget() limitations, this function will only + return menu items, even for entries. + Tue Mar 9 01:01:28 1999 Tim Janik * gdk/gdkfont.c (gdk_font_load): first lookup the xfont ID in our diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index c108495679..6da4b19804 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,48 @@ +Wed Mar 10 00:11:32 1999 Tim Janik + + * gtk/testgtk.c (create_item_factory): unref the item factory after + window's destruction. + + * gtk/gtkmenushell.c (gtk_menu_shell_activate_item): keep a reference + count on the menu shell around the menu item's activation, since the + signal emission may cause menu shell destruction. + + * gtk/gtkitemfactory.c: + the previous code leaked one accel group per menu. we use + gtk_menu_get_uline_accel_group() now to fix that, and with that + also create the underline accelerator group of the menus only if + required (i.e. an underline accelerator has been specified). + (gtk_item_factory_construct): + (gtk_item_factory_create_item): removed code that would create an + extra accel group for the menu (and leak references). + (gtk_item_factory_create_item): adapted the underline accelerator + installation code to properly feature gtk_menu_get_uline_accel_group(). + + * gtk/gtkmenu.[hc]: added gtk_menu_get_accel_group() to retrive + menu->accel_group, this may return NULL if the accelerator group + hasn't been set yet. + added gtk_menu_get_uline_accel_group() to retrive the underline + accelerator group of the menu, this will be created on demand + and proper care is taken about its reference count. + + * gtk/gtkitemfactory.h: + * gtk/gtkitemfactory.c: + dumped the approach of keeping a widgets by action list on the + factory since the factory<->widget destroy negotiation didn't work + and would be hard to get going at all. instead we keep a list of + GtkItemFactoryItem items on the factory (GtkItemFactoryItems are + persistant throughout a program's life time). + also, i removed the static const gchar *key_* variables, and made + them inline strings (they weren't actually used anyways). + (gtk_item_factory_add_item): update ifactory->items. + (gtk_item_factory_destroy): destroy ifactory->items (and remove + the item factory pointer from the remaining ifactory widgets). + (gtk_item_factory_get_widget_by_action): walk the GtkItemFactoryItem + list to find the widget. + (gtk_item_factory_get_item): new function that works around + gtk_item_factory_get_widget() limitations, this function will only + return menu items, even for entries. + Tue Mar 9 01:01:28 1999 Tim Janik * gdk/gdkfont.c (gdk_font_load): first lookup the xfont ID in our diff --git a/gtk/gtkitemfactory.c b/gtk/gtkitemfactory.c index 9273d5da89..016fdc94b8 100644 --- a/gtk/gtkitemfactory.c +++ b/gtk/gtkitemfactory.c @@ -53,7 +53,6 @@ /* --- structures --- */ typedef struct _GtkIFCBData GtkIFCBData; -typedef struct _GtkIFActionLink GtkIFActionLink; typedef struct _GtkIFDumpData GtkIFDumpData; struct _GtkIFCBData { @@ -62,11 +61,6 @@ struct _GtkIFCBData gpointer func_data; guint callback_action; }; -struct _GtkIFActionLink -{ - GtkWidget *widget; - guint callback_action; -}; struct _GtkIFDumpData { GtkPrintFunc print_func; @@ -89,31 +83,19 @@ static GtkObjectClass *parent_class = NULL; static const gchar *item_factory_string = "Gtk-"; static GMemChunk *ifactory_item_chunks = NULL; static GMemChunk *ifactory_cb_data_chunks = NULL; -static const gchar *key_popup_data = "GtkItemFactory-popup-data"; static GQuark quark_popup_data = 0; -static const gchar *key_if_menu_pos = "GtkItemFactory-menu-position"; static GQuark quark_if_menu_pos = 0; -static const gchar *key_item_factory = "GtkItemFactory"; static GQuark quark_item_factory = 0; -static const gchar *key_item_factory_path = "GtkItemFactory-path"; -static GQuark quark_item_factory_path = 0; -static const gchar *key_type_item = ""; +static GQuark quark_item_path = 0; +static GQuark quark_action = 0; static GQuark quark_type_item = 0; -static const gchar *key_type_title = ""; static GQuark quark_type_title = 0; -static const gchar *key_type_radio_item = "<RadioItem>"; static GQuark quark_type_radio_item = 0; -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>"; static GQuark quark_type_branch = 0; -static const gchar *key_type_last_branch = "<LastBranch>"; static GQuark quark_type_last_branch = 0; static GScannerConfig ifactory_scanner_config = { @@ -212,19 +194,20 @@ gtk_item_factory_class_init (GtkItemFactoryClass *class) sizeof (GtkIFCBData) * ITEM_BLOCK_SIZE, G_ALLOC_AND_FREE); - quark_popup_data = g_quark_from_static_string (key_popup_data); - quark_if_menu_pos = g_quark_from_static_string (key_if_menu_pos); - quark_item_factory = g_quark_from_static_string (key_item_factory); - quark_item_factory_path = g_quark_from_static_string (key_item_factory_path); - quark_type_item = g_quark_from_static_string (key_type_item); - quark_type_title = g_quark_from_static_string (key_type_title); - 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); + quark_popup_data = g_quark_from_static_string ("GtkItemFactory-popup-data"); + quark_if_menu_pos = g_quark_from_static_string ("GtkItemFactory-menu-position"); + quark_item_factory = g_quark_from_static_string ("GtkItemFactory"); + quark_item_path = g_quark_from_static_string ("GtkItemFactory-path"); + quark_action = g_quark_from_static_string ("GtkItemFactory-action"); + quark_type_item = g_quark_from_static_string ("<Item>"); + quark_type_title = g_quark_from_static_string ("<Title>"); + quark_type_radio_item = g_quark_from_static_string ("<RadioItem>"); + quark_type_check_item = g_quark_from_static_string ("<CheckItem>"); + quark_type_toggle_item = g_quark_from_static_string ("<ToggleItem>"); + quark_type_tearoff_item = g_quark_from_static_string ("<Tearoff>"); + quark_type_separator_item = g_quark_from_static_string ("<Separator>"); + quark_type_branch = g_quark_from_static_string ("<Branch>"); + quark_type_last_branch = g_quark_from_static_string ("<LastBranch>"); } static void @@ -237,7 +220,7 @@ gtk_item_factory_init (GtkItemFactory *ifactory) ifactory->path = NULL; ifactory->accel_group = NULL; ifactory->widget = NULL; - ifactory->widgets_by_action = NULL; + ifactory->items = NULL; } GtkItemFactory* @@ -402,7 +385,7 @@ gtk_item_factory_item_remove_widget (GtkWidget *widget, { item->widgets = g_slist_remove (item->widgets, widget); gtk_object_remove_data_by_id (GTK_OBJECT (widget), quark_item_factory); - gtk_object_remove_data_by_id (GTK_OBJECT (widget), quark_item_factory_path); + gtk_object_remove_data_by_id (GTK_OBJECT (widget), quark_item_path); } static void @@ -480,10 +463,16 @@ gtk_item_factory_add_item (GtkItemFactory *ifactory, GTK_SIGNAL_FUNC (gtk_item_factory_item_remove_widget), item); + /* asure the factory knows about the corresponding items + */ + if (!g_slist_find (ifactory->items, item)) + ifactory->items = g_slist_prepend (ifactory->items, item); + /* set back pointers for the widget */ gtk_object_set_data_by_id (GTK_OBJECT (widget), quark_item_factory, ifactory); - gtk_object_set_data_by_id (GTK_OBJECT (widget), quark_item_factory_path, item->path); + gtk_object_set_data_by_id (GTK_OBJECT (widget), quark_item_path, item->path); + gtk_object_set_data_by_id (GTK_OBJECT (widget), quark_action, GUINT_TO_POINTER (callback_action)); gtk_widget_set_name (widget, item->path); /* set accelerator group on menu widgets @@ -519,18 +508,6 @@ gtk_item_factory_add_item (GtkItemFactory *ifactory, GTK_SIGNAL_FUNC (gtk_item_factory_item_remove_accelerator), item); - /* keep a per-action list of the widgets on the factory - */ - if (callback) - { - GtkIFActionLink *link; - - link = g_new (GtkIFActionLink, 1); - link->widget = widget; - link->callback_action = callback_action; - ifactory->widgets_by_action = g_slist_prepend (ifactory->widgets_by_action, link); - } - /* connect callback if neccessary */ if (callback) @@ -559,7 +536,6 @@ gtk_item_factory_construct (GtkItemFactory *ifactory, const gchar *path, GtkAccelGroup *accel_group) { - GtkAccelGroup *menu_group; guint len; g_return_if_fail (ifactory != NULL); @@ -593,15 +569,6 @@ gtk_item_factory_construct (GtkItemFactory *ifactory, 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", - GTK_SIGNAL_FUNC (gtk_object_destroy), - GTK_OBJECT (ifactory)); - */ gtk_item_factory_add_item (ifactory, "", NULL, NULL, 0, NULL, 0, @@ -670,10 +637,17 @@ gtk_item_factory_destroy (GtkObject *object) ifactory->widget = NULL; } - for (slist = ifactory->widgets_by_action; slist; slist = slist->next) - g_free (slist->data); - g_slist_free (ifactory->widgets_by_action); - ifactory->widgets_by_action = NULL; + for (slist = ifactory->items; slist; slist = slist->next) + { + GtkItemFactoryItem *item = slist->data; + GSList *link; + + for (link = item->widgets; link; link = link->next) + if (gtk_object_get_data_by_id (link->data, quark_item_factory)) + gtk_object_remove_data_by_id (link->data, quark_item_factory); + } + g_slist_free (ifactory->items); + ifactory->items = NULL; parent_class->destroy (object); } @@ -713,7 +687,7 @@ gtk_item_factory_path_from_widget (GtkWidget *widget) g_return_val_if_fail (widget != NULL, NULL); g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - return gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_item_factory_path); + return gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_item_path); } static void @@ -813,20 +787,20 @@ gtk_item_factory_dump_rc (const gchar *file_name, } void -gtk_item_factory_create_items (GtkItemFactory *ifactory, - guint n_entries, - GtkItemFactoryEntry *entries, - gpointer callback_data) +gtk_item_factory_create_items (GtkItemFactory *ifactory, + guint n_entries, + GtkItemFactoryEntry *entries, + gpointer callback_data) { gtk_item_factory_create_items_ac (ifactory, n_entries, entries, callback_data, 1); } void -gtk_item_factory_create_items_ac (GtkItemFactory *ifactory, - guint n_entries, - GtkItemFactoryEntry *entries, - gpointer callback_data, - guint callback_type) +gtk_item_factory_create_items_ac (GtkItemFactory *ifactory, + guint n_entries, + GtkItemFactoryEntry *entries, + gpointer callback_data, + guint callback_type) { guint i; @@ -844,13 +818,12 @@ gtk_item_factory_create_items_ac (GtkItemFactory *ifactory, } GtkWidget* -gtk_item_factory_get_widget (GtkItemFactory *ifactory, - const gchar *path) +gtk_item_factory_get_widget (GtkItemFactory *ifactory, + const gchar *path) { GtkItemFactoryClass *class; GtkItemFactoryItem *item; - g_return_val_if_fail (ifactory != NULL, NULL); g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL); g_return_val_if_fail (path != NULL, NULL); @@ -882,27 +855,60 @@ gtk_item_factory_get_widget (GtkItemFactory *ifactory, } GtkWidget* -gtk_item_factory_get_widget_by_action (GtkItemFactory *ifactory, - guint action) +gtk_item_factory_get_widget_by_action (GtkItemFactory *ifactory, + guint action) { GSList *slist; - g_return_val_if_fail (ifactory != NULL, NULL); g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL); - for (slist = ifactory->widgets_by_action; slist; slist = slist->next) + for (slist = ifactory->items; slist; slist = slist->next) { - GtkIFActionLink *link; + GtkItemFactoryItem *item = slist->data; + GSList *link; - link = slist->data; - - if (link->callback_action == action) - return link->widget; + for (link = item->widgets; link; link = link->next) + if (gtk_object_get_data_by_id (link->data, quark_item_factory) == ifactory && + gtk_object_get_data_by_id (link->data, quark_action) == GUINT_TO_POINTER (action)) + return link->data; } return NULL; } +GtkWidget* +gtk_item_factory_get_item (GtkItemFactory *ifactory, + const gchar *path) +{ + GtkWidget *widget; + + g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL); + g_return_val_if_fail (path != NULL, NULL); + + widget = gtk_item_factory_get_widget (ifactory, path); + + if (GTK_IS_MENU (widget)) + widget = gtk_menu_get_attach_widget (GTK_MENU (widget)); + + return GTK_IS_ITEM (widget) ? widget : NULL; +} + +GtkWidget* +gtk_item_factory_get_item_by_action (GtkItemFactory *ifactory, + guint action) +{ + GtkWidget *widget; + + g_return_val_if_fail (GTK_IS_ITEM_FACTORY (ifactory), NULL); + + widget = gtk_item_factory_get_widget_by_action (ifactory, action); + + if (GTK_IS_MENU (widget)) + widget = gtk_menu_get_attach_widget (GTK_MENU (widget)); + + return GTK_IS_ITEM (widget) ? widget : NULL; +} + static gboolean gtk_item_factory_parse_path (GtkItemFactory *ifactory, gchar *str, @@ -964,8 +970,6 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory, 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)); @@ -977,7 +981,7 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory, if (!entry->item_type || entry->item_type[0] == 0) { - item_type_path = (gpointer) key_type_item; + item_type_path = "<Item>"; type_id = quark_type_item; } else @@ -1052,12 +1056,8 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory, } g_free (parent_path); - g_return_if_fail (parent != NULL); + g_return_if_fail (GTK_IS_CONTAINER (parent)); - 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, "GtkWidget::sensitive", (type_id != quark_type_separator_item && @@ -1069,64 +1069,58 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory, gtk_radio_menu_item_set_group (GTK_RADIO_MENU_ITEM (widget), radio_group); 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) && - (type_id != quark_type_tearoff_item) && + + /* install underline accelerators for this item + */ + if (type_id != quark_type_separator_item && + type_id != quark_type_tearoff_item && *name) { GtkWidget *label; - - label = - gtk_widget_new (GTK_TYPE_ACCEL_LABEL, - "GtkWidget::visible", TRUE, - "GtkWidget::parent", widget, - "GtkAccelLabel::accel_widget", widget, - "GtkMisc::xalign", 0.0, - NULL); - + + label = gtk_widget_new (GTK_TYPE_ACCEL_LABEL, + "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)) + + if (accel_key != GDK_VoidSymbol) { - gtk_widget_add_accelerator (widget, - "activate_item", - ifactory->accel_group, - accel_key, GDK_MOD1_MASK, - GTK_ACCEL_LOCKED); - } + if (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); + if (GTK_IS_MENU (parent)) + gtk_widget_add_accelerator (widget, + "activate_item", + gtk_menu_get_uline_accel_group (GTK_MENU (parent)), + accel_key, 0, + GTK_ACCEL_LOCKED); } } - + g_free (name); - + if (type_id == quark_type_branch || type_id == quark_type_last_branch) { - GtkAccelGroup *menu_group; - if (entry->callback) g_warning ("gtk_item_factory_create_item(): Can't specify a callback on a branch: \"%s\"", entry->path); - - menu_group = gtk_accel_group_new (); if (type_id == quark_type_last_branch) gtk_menu_item_right_justify (GTK_MENU_ITEM (widget)); - - parent = widget; - widget = - gtk_widget_new (GTK_TYPE_MENU, - NULL); - gtk_accel_group_attach (menu_group, GTK_OBJECT (widget)); + parent = widget; + widget = gtk_widget_new (GTK_TYPE_MENU, + NULL); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), widget); } @@ -1188,7 +1182,7 @@ gtk_item_factory_create_menu_entries (guint n_entries, entry.callback = entries[i].callback; entry.callback_action = 0; if (gtk_pattern_match_string (&pspec_separator, path)) - entry.item_type = (gpointer) key_type_separator_item; + entry.item_type = "<Separator>"; else if (!gtk_pattern_match_string (&pspec_check, path)) entry.item_type = NULL; else @@ -1209,7 +1203,7 @@ gtk_item_factory_create_menu_entries (guint n_entries, path++; } *c = 0; - entry.item_type = (gpointer) key_type_toggle_item; + entry.item_type = "<ToggleItem>"; entry.path = cpath; } diff --git a/gtk/gtkitemfactory.h b/gtk/gtkitemfactory.h index 74e7f34bbb..2525967383 100644 --- a/gtk/gtkitemfactory.h +++ b/gtk/gtkitemfactory.h @@ -69,7 +69,7 @@ struct _GtkItemFactory gchar *path; GtkAccelGroup *accel_group; GtkWidget *widget; - GSList *widgets_by_action; + GSList *items; GtkTranslateFunc translate_func; gpointer translate_data; @@ -146,10 +146,14 @@ void gtk_item_factory_parse_rc_scanner (GScanner *scanner); GtkItemFactory* gtk_item_factory_from_widget (GtkWidget *widget); gchar* gtk_item_factory_path_from_widget (GtkWidget *widget); -GtkWidget* gtk_item_factory_get_widget (GtkItemFactory *ifactory, - const gchar *path); +GtkWidget* gtk_item_factory_get_item (GtkItemFactory *ifactory, + const gchar *path); +GtkWidget* gtk_item_factory_get_widget (GtkItemFactory *ifactory, + const gchar *path); GtkWidget* gtk_item_factory_get_widget_by_action (GtkItemFactory *ifactory, guint action); +GtkWidget* gtk_item_factory_get_item_by_action (GtkItemFactory *ifactory, + guint action); /* If `path_pspec' is passed as `NULL', this function will iterate over * all hash entries. otherwise only those entries will be dumped for which diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 207f9cc0ce..dae1f8cd84 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -566,7 +566,6 @@ void gtk_menu_set_accel_group (GtkMenu *menu, GtkAccelGroup *accel_group) { - g_return_if_fail (menu != NULL); g_return_if_fail (GTK_IS_MENU (menu)); if (menu->accel_group != accel_group) @@ -579,6 +578,38 @@ gtk_menu_set_accel_group (GtkMenu *menu, } } +GtkAccelGroup* +gtk_menu_get_accel_group (GtkMenu *menu) +{ + g_return_val_if_fail (GTK_IS_MENU (menu), NULL); + + return menu->accel_group; +} + +GtkAccelGroup* +gtk_menu_get_uline_accel_group (GtkMenu *menu) +{ + static GQuark quark_uline_accel_group = 0; + GtkAccelGroup *accel_group; + + g_return_val_if_fail (GTK_IS_MENU (menu), NULL); + + if (!quark_uline_accel_group) + quark_uline_accel_group = g_quark_from_static_string ("GtkMenu-uline-accel-group"); + + accel_group = gtk_object_get_data_by_id (GTK_OBJECT (menu), quark_uline_accel_group); + if (!accel_group) + { + accel_group = gtk_accel_group_new (); + gtk_accel_group_attach (accel_group, GTK_OBJECT (menu)); + gtk_object_set_data_by_id_full (GTK_OBJECT (menu), + quark_uline_accel_group, + accel_group, + (GtkDestroyNotify) gtk_accel_group_unref); + } + + return accel_group; +} void gtk_menu_reposition (GtkMenu *menu) diff --git a/gtk/gtkmenu.h b/gtk/gtkmenu.h index 7e37a0bcd6..4a7d3d2c0d 100644 --- a/gtk/gtkmenu.h +++ b/gtk/gtkmenu.h @@ -117,8 +117,18 @@ GtkWidget* gtk_menu_get_active (GtkMenu *menu); void gtk_menu_set_active (GtkMenu *menu, guint index); -void gtk_menu_set_accel_group (GtkMenu *menu, +/* set/get the acclerator group that holds global accelerators (should + * be added to the corresponding toplevel with gtk_window_add_accel_group(). + */ +void gtk_menu_set_accel_group (GtkMenu *menu, GtkAccelGroup *accel_group); +GtkAccelGroup* gtk_menu_get_accel_group (GtkMenu *menu); + +/* get the accelerator group that is used internally by the menu for + * underline accelerators while the menu is popped up. + */ +GtkAccelGroup* gtk_menu_get_uline_accel_group (GtkMenu *menu); + /* A reference count is kept for a widget when it is attached to * a particular widget. This is typically a menu item; it may also diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c index 52ad415631..64a3a35283 100644 --- a/gtk/gtkmenushell.c +++ b/gtk/gtkmenushell.c @@ -831,10 +831,13 @@ gtk_menu_shell_activate_item (GtkMenuShell *menu_shell, */ gdk_flush (); } + + gtk_widget_ref (GTK_WIDGET (menu_shell)); gtk_widget_activate (menu_item); if (deactivate) gtk_signal_emit (GTK_OBJECT (menu_shell), menu_shell_signals[SELECTION_DONE]); + gtk_widget_unref (GTK_WIDGET (menu_shell)); } /* Distance should be +/- 1 */ diff --git a/gtk/testgtk.c b/gtk/testgtk.c index 3d979f5d69..5252f30262 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -2418,8 +2418,12 @@ create_item_factory (void) accel_group = gtk_accel_group_new (); item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group); - gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); + gtk_object_set_data_full (GTK_OBJECT (window), + "<main>", + item_factory, + (GtkDestroyNotify) gtk_object_unref); gtk_accel_group_attach (accel_group, GTK_OBJECT (window)); + gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); gtk_window_set_title (GTK_WINDOW (window), "Item Factory"); gtk_container_set_border_width (GTK_CONTAINER (window), 0); diff --git a/tests/testgtk.c b/tests/testgtk.c index 3d979f5d69..5252f30262 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -2418,8 +2418,12 @@ create_item_factory (void) accel_group = gtk_accel_group_new (); item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group); - gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); + gtk_object_set_data_full (GTK_OBJECT (window), + "<main>", + item_factory, + (GtkDestroyNotify) gtk_object_unref); gtk_accel_group_attach (accel_group, GTK_OBJECT (window)); + gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); gtk_window_set_title (GTK_WINDOW (window), "Item Factory"); gtk_container_set_border_width (GTK_CONTAINER (window), 0);