From b1f022f144f154257b5a69e643fef46d3a48b58d Mon Sep 17 00:00:00 2001 From: Jehan Date: Mon, 27 Feb 2023 18:49:45 +0100 Subject: [PATCH] app, menus: now support the child menu of the GimpDockbook menu. I only translated the undo menu into GtkBuilder's .ui format for now. The only missing part is that the icon is now shown. Note that in various parts, I don't rely anymore on a bogus menu action (i.e. "undo-popup" action in this case) which does nothing but has an associated label and icon. I simply add the label and icon as submenu attribute directly in the .ui file, which is translatable and whose strings should be parsed by gettext. Eventually I'll just get rid of all the various "*-popup" or "*-menu" bogus actions. --- app/display/gimpdisplayshell-callbacks.c | 1 + app/display/gimpdisplayshell.c | 1 + app/widgets/gimpdockbook.c | 96 +----------------------- app/widgets/gimpmenushell.c | 27 +++++++ app/widgets/gimpmenushell.h | 3 + app/widgets/gimptooloptionseditor.c | 2 +- app/widgets/gimpuimanager.c | 15 ++++ app/widgets/gimpuimanager.h | 2 + menus/meson.build | 1 + menus/undo-menu.ui | 13 ++++ 10 files changed, 66 insertions(+), 95 deletions(-) create mode 100644 menus/undo-menu.ui diff --git a/app/display/gimpdisplayshell-callbacks.c b/app/display/gimpdisplayshell-callbacks.c index 48f69035db..8c17e7f9e6 100644 --- a/app/display/gimpdisplayshell-callbacks.c +++ b/app/display/gimpdisplayshell-callbacks.c @@ -353,6 +353,7 @@ gimp_display_shell_quick_mask_button_press (GtkWidget *widget, gimp_ui_manager_ui_popup_at_widget (manager, "/quick-mask-popup", + NULL, NULL, widget, GDK_GRAVITY_EAST, GDK_GRAVITY_SOUTH_WEST, diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c index 138f0107c5..3bb7f3dbd2 100644 --- a/app/display/gimpdisplayshell.c +++ b/app/display/gimpdisplayshell.c @@ -989,6 +989,7 @@ gimp_display_shell_popup_menu (GtkWidget *widget) gimp_ui_manager_ui_popup_at_widget (shell->popup_manager, "/image-menubar", + NULL, NULL, shell->origin, GDK_GRAVITY_EAST, GDK_GRAVITY_NORTH_WEST, diff --git a/app/widgets/gimpdockbook.c b/app/widgets/gimpdockbook.c index c4d3b5372a..8df831feae 100644 --- a/app/widgets/gimpdockbook.c +++ b/app/widgets/gimpdockbook.c @@ -551,8 +551,6 @@ gimp_dockbook_show_menu (GimpDockbook *dockbook) GimpUIManager *dialog_ui_manager; const gchar *dialog_ui_path; gpointer dialog_popup_data; - GtkWidget *parent_menu_widget; - GimpAction *parent_menu_action; GimpDockable *dockable; gint page_num; @@ -561,16 +559,6 @@ gimp_dockbook_show_menu (GimpDockbook *dockbook) if (! dockbook_ui_manager) return FALSE; - parent_menu_widget = - gimp_ui_manager_get_widget (dockbook_ui_manager, - "/dockable-popup/dockable-menu"); - parent_menu_action = - gimp_ui_manager_get_action (dockbook_ui_manager, - "/dockable-popup/dockable-menu"); - - if (! parent_menu_widget || ! parent_menu_action) - return FALSE; - page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook)); dockable = GIMP_DOCKABLE (gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num)); @@ -582,69 +570,6 @@ gimp_dockbook_show_menu (GimpDockbook *dockbook) &dialog_ui_path, &dialog_popup_data); - if (dialog_ui_manager && dialog_ui_path) - { - GtkWidget *child_menu_widget; - GimpAction *child_menu_action; - gchar *label; - - child_menu_widget = - gimp_ui_manager_get_widget (dialog_ui_manager, dialog_ui_path); - - if (! child_menu_widget) - { - g_warning ("%s: UI manager '%s' has no widget at path '%s'", - G_STRFUNC, dialog_ui_manager->name, dialog_ui_path); - return FALSE; - } - - child_menu_action = - gimp_ui_manager_get_action (dialog_ui_manager, - dialog_ui_path); - - if (! child_menu_action) - { - g_warning ("%s: UI manager '%s' has no action at path '%s'", - G_STRFUNC, dialog_ui_manager->name, dialog_ui_path); - return FALSE; - } - - g_object_get (child_menu_action, - "label", &label, - NULL); - - g_object_set (parent_menu_action, - "label", label, - "icon-name", gimp_dockable_get_icon_name (dockable), - "visible", TRUE, - NULL); - - g_free (label); - - if (! GTK_IS_MENU (child_menu_widget)) - { - g_warning ("%s: child_menu_widget (%p) is not a GtkMenu", - G_STRFUNC, child_menu_widget); - return FALSE; - } - - { - GtkWidget *image = gimp_dockable_get_icon (dockable, - GTK_ICON_SIZE_MENU); - gimp_menu_item_set_image (GTK_MENU_ITEM (parent_menu_widget), image, NULL); - gtk_widget_show (image); - } - - gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent_menu_widget), - child_menu_widget); - - gimp_ui_manager_update (dialog_ui_manager, dialog_popup_data); - } - else - { - g_object_set (parent_menu_action, "visible", FALSE, NULL); - } - /* an action callback may destroy both dockable and dockbook, so * reference them for gimp_dockbook_menu_end() */ @@ -653,10 +578,10 @@ gimp_dockbook_show_menu (GimpDockbook *dockbook) g_object_ref (dockbook), g_object_unref); - gimp_ui_manager_update (dockbook_ui_manager, dockable); - gimp_ui_manager_ui_popup_at_widget (dockbook_ui_manager, "/dockable-popup", + dialog_ui_manager, + dialog_ui_path, dockbook->p->menu_button, GDK_GRAVITY_WEST, GDK_GRAVITY_NORTH_EAST, @@ -670,23 +595,6 @@ gimp_dockbook_show_menu (GimpDockbook *dockbook) static void gimp_dockbook_menu_end (GimpDockable *dockable) { - GimpUIManager *dialog_ui_manager; - const gchar *dialog_ui_path; - gpointer dialog_popup_data; - - dialog_ui_manager = gimp_dockable_get_menu (dockable, - &dialog_ui_path, - &dialog_popup_data); - - if (dialog_ui_manager && dialog_ui_path) - { - GtkWidget *child_menu_widget = - gimp_ui_manager_get_widget (dialog_ui_manager, dialog_ui_path); - - if (child_menu_widget) - gtk_menu_detach (GTK_MENU (child_menu_widget)); - } - /* release gimp_dockbook_show_menu()'s references */ g_object_set_data (G_OBJECT (dockable), GIMP_DOCKABLE_DETACH_REF_KEY, NULL); g_object_unref (dockable); diff --git a/app/widgets/gimpmenushell.c b/app/widgets/gimpmenushell.c index cde476e75c..7116a91c03 100644 --- a/app/widgets/gimpmenushell.c +++ b/app/widgets/gimpmenushell.c @@ -157,6 +157,33 @@ gimp_menu_shell_fill (GimpMenuShell *shell, } } +void +gimp_menu_shell_merge (GimpMenuShell *shell, + GimpMenuShell *shell2, + gboolean top) +{ + GList *children; + GList *iter; + + children = gtk_container_get_children (GTK_CONTAINER (shell2)); + iter = top ? g_list_last (children) : children; + for (; iter; iter = top ? iter->prev : iter->next) + { + GtkWidget *item = iter->data; + + g_object_ref (item); + gtk_container_remove (GTK_CONTAINER (shell2), item); + if (top) + gtk_menu_shell_prepend (GTK_MENU_SHELL (shell), item); + else + gtk_menu_shell_append (GTK_MENU_SHELL (shell), item); + g_object_unref (item); + } + + g_list_free (children); + gtk_widget_destroy (GTK_WIDGET (shell2)); +} + /* Protected functions. */ diff --git a/app/widgets/gimpmenushell.h b/app/widgets/gimpmenushell.h index 419df138cb..3983432828 100644 --- a/app/widgets/gimpmenushell.h +++ b/app/widgets/gimpmenushell.h @@ -49,6 +49,9 @@ GType gimp_menu_shell_get_type (void) G_GNUC_CONST; void gimp_menu_shell_fill (GimpMenuShell *shell, GMenuModel *model, const gchar *update_signal); +void gimp_menu_shell_merge (GimpMenuShell *shell, + GimpMenuShell *shell2, + gboolean top); /* Protected functions. */ diff --git a/app/widgets/gimptooloptionseditor.c b/app/widgets/gimptooloptionseditor.c index d04e7fb045..16558333f6 100644 --- a/app/widgets/gimptooloptionseditor.c +++ b/app/widgets/gimptooloptionseditor.c @@ -383,7 +383,7 @@ gimp_tool_options_editor_menu_popup (GimpToolOptionsEditor *editor, gimp_editor_get_popup_data (gimp_editor)); gimp_ui_manager_ui_popup_at_widget (gimp_editor_get_ui_manager (gimp_editor), - path, + path, NULL, NULL, button, GDK_GRAVITY_WEST, GDK_GRAVITY_NORTH_EAST, diff --git a/app/widgets/gimpuimanager.c b/app/widgets/gimpuimanager.c index 1669a01eb6..4854adfc39 100644 --- a/app/widgets/gimpuimanager.c +++ b/app/widgets/gimpuimanager.c @@ -723,6 +723,8 @@ gimp_ui_manager_ui_register (GimpUIManager *manager, void gimp_ui_manager_ui_popup_at_widget (GimpUIManager *manager, const gchar *ui_path, + GimpUIManager *child_ui_manager, + const gchar *child_ui_path, GtkWidget *widget, GdkGravity widget_anchor, GdkGravity menu_anchor, @@ -745,6 +747,19 @@ gimp_ui_manager_ui_popup_at_widget (GimpUIManager *manager, if (! menu) return; + if (child_ui_manager != NULL && child_ui_path != NULL) + { + GMenuModel *child_model; + GtkWidget *child_menu; + + /* TODO GMenu: the "icon" attribute set in the .ui file should be visible. */ + child_model = gimp_ui_manager_get_model (child_ui_manager, child_ui_path); + child_menu = gimp_menu_new (child_ui_manager); + gimp_menu_shell_fill (GIMP_MENU_SHELL (child_menu), child_model, NULL); + + gimp_menu_shell_merge (GIMP_MENU_SHELL (menu), GIMP_MENU_SHELL (child_menu), TRUE); + } + if (popdown_func && popdown_data) { g_object_set_data_full (G_OBJECT (manager), "popdown-data", diff --git a/app/widgets/gimpuimanager.h b/app/widgets/gimpuimanager.h index 9cb0cd2e70..e38a9e0904 100644 --- a/app/widgets/gimpuimanager.h +++ b/app/widgets/gimpuimanager.h @@ -155,6 +155,8 @@ void gimp_ui_manager_ui_register (GimpUIManager *manager, void gimp_ui_manager_ui_popup_at_widget (GimpUIManager *manager, const gchar *ui_path, + GimpUIManager *child_ui_manager, + const gchar *child_ui_path, GtkWidget *widget, GdkGravity widget_anchor, GdkGravity menu_anchor, diff --git a/menus/meson.build b/menus/meson.build index 54f1349f1f..e8283c1e23 100644 --- a/menus/meson.build +++ b/menus/meson.build @@ -56,6 +56,7 @@ ui_menus_files = files( 'patterns-menu.ui', 'quick-mask-menu.ui', 'templates-menu.ui', + 'undo-menu.ui', 'vectors-menu.ui', ) diff --git a/menus/undo-menu.ui b/menus/undo-menu.ui new file mode 100644 index 0000000000..4c2bb78e58 --- /dev/null +++ b/menus/undo-menu.ui @@ -0,0 +1,13 @@ + + + + + + Undo History Menu + edit-undo + app.edit-undo + app.edit-redo + app.edit-undo-clear + + +