From: Matthias Clasen Date: Sat, 14 Sep 2019 20:55:06 +0000 (-0400) Subject: toolbar: Use a popover for overflow X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~20^2~846^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=b14b0efefe840b8ca1ce3077e1170e757bc12340;p=gtk4.git toolbar: Use a popover for overflow We are phasing out menus. This is not quite complete, toolitems still create menuitems, which we translate on the fly. --- diff --git a/gtk/gtktoolbar.c b/gtk/gtktoolbar.c index 667d80961c..6d6d88e1ed 100644 --- a/gtk/gtktoolbar.c +++ b/gtk/gtktoolbar.c @@ -45,10 +45,14 @@ #include "gtklabel.h" #include "gtkmain.h" #include "gtkmarshalers.h" -#include "gtkmenu.h" #include "gtkorientable.h" #include "gtkorientableprivate.h" #include "gtkprivate.h" +#include "gtkpopovermenu.h" +#include "gtkmodelbutton.h" +#include "gtkseparator.h" +#include "gtkradiomenuitem.h" +#include "gtkcheckmenuitem.h" #include "gtkradiobutton.h" #include "gtkradiotoolbutton.h" #include "gtkseparatormenuitem.h" @@ -132,7 +136,8 @@ struct _GtkToolbarClass struct _GtkToolbarPrivate { - GtkMenu *menu; + GtkWidget *menu; + GtkWidget *menu_box; GtkSettings *settings; GtkToolbarStyle style; @@ -429,6 +434,7 @@ gtk_toolbar_class_init (GtkToolbarClass *klass) NULL, G_TYPE_NONE, 1, GTK_TYPE_TOOLBAR_STYLE); + /** * GtkToolbar::popup-context-menu: * @toolbar: the #GtkToolbar which emitted the signal @@ -1108,76 +1114,96 @@ menu_deactivated (GtkWidget *menu, } static void -menu_detached (GtkWidget *widget, - GtkMenu *menu) +button_clicked (GtkWidget *button, + GtkWidget *item) { - GtkToolbar *toolbar = GTK_TOOLBAR (widget); - GtkToolbarPrivate *priv = toolbar->priv; - - priv->menu = NULL; + gtk_popover_popdown (GTK_POPOVER (gtk_widget_get_ancestor (button, GTK_TYPE_POPOVER))); + if (GTK_IS_TOOL_BUTTON (item)) + g_signal_emit_by_name (_gtk_tool_button_get_button (GTK_TOOL_BUTTON (item)), "clicked"); } static void rebuild_menu (GtkToolbar *toolbar) { GtkToolbarPrivate *priv = toolbar->priv; - GList *list, *children; + GList *list; if (!priv->menu) { - priv->menu = GTK_MENU (gtk_menu_new ()); - gtk_menu_attach_to_widget (priv->menu, - GTK_WIDGET (toolbar), - menu_detached); + priv->menu = gtk_popover_menu_new (priv->arrow_button); + priv->menu_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_popover_menu_add_submenu (GTK_POPOVER_MENU (priv->menu), priv->menu_box, "main"); - g_signal_connect (priv->menu, "deactivate", + g_signal_connect (priv->menu, "closed", G_CALLBACK (menu_deactivated), toolbar); } - gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL); - + gtk_container_foreach (GTK_CONTAINER (priv->menu_box), remove_item, NULL); + for (list = priv->content; list != NULL; list = list->next) { ToolbarContent *content = list->data; - + if (toolbar_content_get_state (content) == OVERFLOWN && !toolbar_content_is_placeholder (content)) { GtkWidget *menu_item = toolbar_content_retrieve_menu_item (content); - + if (menu_item) { - g_assert (GTK_IS_MENU_ITEM (menu_item)); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item); - } - } - } - - /* Remove leading and trailing separator items */ - children = gtk_container_get_children (GTK_CONTAINER (priv->menu)); - - list = children; - while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data)) - { - GtkWidget *child = list->data; - - gtk_container_remove (GTK_CONTAINER (priv->menu), child); - list = list->next; - } - g_list_free (children); + GtkWidget *button, *widget; + const char *text; + GtkButtonRole role; + gboolean active; - /* Regenerate the list of children so we don't try to remove items twice */ - children = gtk_container_get_children (GTK_CONTAINER (priv->menu)); + g_assert (GTK_IS_MENU_ITEM (menu_item)); + text = gtk_menu_item_get_label (GTK_MENU_ITEM (menu_item)); + if (text == NULL) + { + GtkWidget *box, *child; + box = gtk_bin_get_child (GTK_BIN (menu_item)); + for (child = gtk_widget_get_first_child (box); + child; + child = gtk_widget_get_next_sibling (child)) + { + if (GTK_IS_LABEL (child)) + { + text = gtk_label_get_label (GTK_LABEL (child)); + break; + } + } + } - list = g_list_last (children); - while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data)) - { - GtkWidget *child = list->data; + if (GTK_IS_SEPARATOR_MENU_ITEM (menu_item)) + { + gtk_container_add (GTK_CONTAINER (priv->menu_box), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)); + continue; + } + else if (GTK_IS_RADIO_MENU_ITEM (menu_item)) + role = GTK_BUTTON_ROLE_RADIO; + else if (GTK_IS_CHECK_MENU_ITEM (menu_item)) + role = GTK_BUTTON_ROLE_CHECK; + else + role = GTK_BUTTON_ROLE_NORMAL; - gtk_container_remove (GTK_CONTAINER (priv->menu), child); - list = list->prev; + if (GTK_IS_CHECK_MENU_ITEM (menu_item)) + active = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menu_item)); + else + active = FALSE; + + button = gtk_model_button_new (); + g_object_set (button, + "text", text, + "role", role, + "active", active, + NULL); + widget = toolbar_content_get_widget (content); + g_signal_connect (button, "clicked", + G_CALLBACK (button_clicked), widget); + gtk_container_add (GTK_CONTAINER (priv->menu_box), button); + } + } } - g_list_free (children); priv->need_rebuild = FALSE; } @@ -2124,52 +2150,10 @@ show_menu (GtkToolbar *toolbar, GdkEventButton *event) { GtkToolbarPrivate *priv = toolbar->priv; - GtkRequisition minimum_size; rebuild_menu (toolbar); - gtk_widget_show (GTK_WIDGET (priv->menu)); - - switch (priv->orientation) - { - case GTK_ORIENTATION_HORIZONTAL: - gtk_widget_get_preferred_size (priv->arrow_button, &minimum_size, NULL); - - g_object_set (priv->menu, - "anchor-hints", (GDK_ANCHOR_FLIP_Y | - GDK_ANCHOR_SLIDE | - GDK_ANCHOR_RESIZE), - "menu-type-hint", GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU, - "rect-anchor-dx", -minimum_size.width, - NULL); - - gtk_menu_popup_at_widget (priv->menu, - priv->arrow_button, - GDK_GRAVITY_SOUTH_EAST, - GDK_GRAVITY_NORTH_WEST, - (GdkEvent *) event); - - break; - - case GTK_ORIENTATION_VERTICAL: - g_object_set (priv->menu, - "anchor-hints", (GDK_ANCHOR_FLIP_X | - GDK_ANCHOR_SLIDE | - GDK_ANCHOR_RESIZE), - NULL); - - gtk_menu_popup_at_widget (priv->menu, - priv->arrow_button, - GDK_GRAVITY_NORTH_EAST, - GDK_GRAVITY_NORTH_WEST, - (GdkEvent *) event); - - break; - - default: - g_assert_not_reached (); - break; - } + gtk_popover_popup (GTK_POPOVER (priv->menu)); } static void