[gtk/wip/kill-menu: 2/2] toolbar: Use a popover for overflow



commit b14b0efefe840b8ca1ce3077e1170e757bc12340
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Sep 14 16:55:06 2019 -0400

    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.

 gtk/gtktoolbar.c | 160 +++++++++++++++++++++++++------------------------------
 1 file changed, 72 insertions(+), 88 deletions(-)
---
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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]