[gtk/scrolling-menus] popovermenu: Scroll when necessary




commit 804d9ee8283297edf429d535c88e267506d02622
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jul 2 13:19:02 2021 -0400

    popovermenu: Scroll when necessary
    
    Add a scrolled window to GtkPopoverMenu, so we can scroll
    long menus when there is not enough room.

 gtk/gtkmenusectionbox.c     |  2 +-
 gtk/gtkpopovermenu.c        | 39 +++++++++++++++++++++++++++++----------
 gtk/gtkpopovermenuprivate.h |  2 ++
 3 files changed, 32 insertions(+), 11 deletions(-)
---
diff --git a/gtk/gtkmenusectionbox.c b/gtk/gtkmenusectionbox.c
index 8dd8fe18f3..5033c13016 100644
--- a/gtk/gtkmenusectionbox.c
+++ b/gtk/gtkmenusectionbox.c
@@ -714,7 +714,7 @@ gtk_menu_section_box_add_custom (GtkPopoverMenu *popover,
   GtkMenuSectionBox *box;
   GtkWidget *slot;
 
-  stack = gtk_popover_get_child (GTK_POPOVER (popover));
+  stack = gtk_popover_menu_get_stack (popover);
   box = GTK_MENU_SECTION_BOX (gtk_stack_get_child_by_name (GTK_STACK (stack), "main"));
   if (box == NULL)
     return FALSE;
diff --git a/gtk/gtkpopovermenu.c b/gtk/gtkpopovermenu.c
index 28b96cf468..3f999fa90f 100644
--- a/gtk/gtkpopovermenu.c
+++ b/gtk/gtkpopovermenu.c
@@ -36,6 +36,8 @@
 #include "gtkshortcutmanager.h"
 #include "gtkshortcutcontroller.h"
 #include "gtkbuildable.h"
+#include "gtkscrolledwindow.h"
+#include "gtkviewport.h"
 
 
 /**
@@ -299,16 +301,23 @@ leave_cb (GtkEventController *controller,
 static void
 gtk_popover_menu_init (GtkPopoverMenu *popover)
 {
+  GtkWidget *sw;
   GtkWidget *stack;
   GtkEventController *controller;
   GtkEventController **controllers;
   guint n_controllers, i;
 
+  sw = gtk_scrolled_window_new ();
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+  gtk_scrolled_window_set_propagate_natural_width (GTK_SCROLLED_WINDOW (sw), TRUE);
+  gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (sw), TRUE);
+  gtk_popover_set_child (GTK_POPOVER (popover), sw);
+
   stack = gtk_stack_new ();
   gtk_stack_set_vhomogeneous (GTK_STACK (stack), FALSE);
   gtk_stack_set_transition_type (GTK_STACK (stack), GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT);
   gtk_stack_set_interpolate_size (GTK_STACK (stack), TRUE);
-  gtk_popover_set_child (GTK_POPOVER (popover), stack);
+  gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), stack);
   g_signal_connect (stack, "notify::visible-child-name",
                     G_CALLBACK (visible_submenu_changed), popover);
 
@@ -336,6 +345,16 @@ gtk_popover_menu_init (GtkPopoverMenu *popover)
   gtk_popover_set_cascade_popdown (GTK_POPOVER (popover), TRUE);
 }
 
+GtkWidget *
+gtk_popover_menu_get_stack (GtkPopoverMenu *menu)
+{
+  GtkWidget *sw = gtk_popover_get_child (GTK_POPOVER (menu));
+  GtkWidget *vp = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (sw));
+  GtkWidget *stack = gtk_viewport_get_child (GTK_VIEWPORT (vp));
+
+  return stack;
+}
+
 static void
 gtk_popover_menu_dispose (GObject *object)
 {
@@ -372,16 +391,16 @@ gtk_popover_menu_get_property (GObject    *object,
                                GValue     *value,
                                GParamSpec *pspec)
 {
-  GtkWidget *stack = gtk_popover_get_child (GTK_POPOVER (object));
+  GtkPopoverMenu *menu = GTK_POPOVER_MENU (object);
 
   switch (property_id)
     {
     case PROP_VISIBLE_SUBMENU:
-      g_value_set_string (value, gtk_stack_get_visible_child_name (GTK_STACK (stack)));
+      g_value_set_string (value, gtk_stack_get_visible_child_name (GTK_STACK (gtk_popover_menu_get_stack 
(menu))));
       break;
 
     case PROP_MENU_MODEL:
-      g_value_set_object (value, gtk_popover_menu_get_menu_model (GTK_POPOVER_MENU (object)));
+      g_value_set_object (value, gtk_popover_menu_get_menu_model (menu));
       break;
 
     default:
@@ -396,16 +415,16 @@ gtk_popover_menu_set_property (GObject      *object,
                                const GValue *value,
                                GParamSpec   *pspec)
 {
-  GtkWidget *stack = gtk_popover_get_child (GTK_POPOVER (object));
+  GtkPopoverMenu *menu = GTK_POPOVER_MENU (object);
 
   switch (property_id)
     {
     case PROP_VISIBLE_SUBMENU:
-      gtk_stack_set_visible_child_name (GTK_STACK (stack), g_value_get_string (value));
+      gtk_stack_set_visible_child_name (GTK_STACK (gtk_popover_menu_get_stack (menu)), g_value_get_string 
(value));
       break;
 
     case PROP_MENU_MODEL:
-      gtk_popover_menu_set_menu_model (GTK_POPOVER_MENU (object), g_value_get_object (value));
+      gtk_popover_menu_set_menu_model (menu, g_value_get_object (value));
       break;
 
     default:
@@ -676,7 +695,7 @@ gtk_popover_menu_open_submenu (GtkPopoverMenu *popover,
 
   g_return_if_fail (GTK_IS_POPOVER_MENU (popover));
 
-  stack = gtk_popover_get_child (GTK_POPOVER (popover));
+  stack = gtk_popover_menu_get_stack (popover);
   gtk_stack_set_visible_child_name (GTK_STACK (stack), name);
 }
 
@@ -685,7 +704,7 @@ gtk_popover_menu_add_submenu (GtkPopoverMenu *popover,
                               GtkWidget      *submenu,
                               const char     *name)
 {
-  GtkWidget *stack = gtk_popover_get_child (GTK_POPOVER (popover));
+  GtkWidget *stack = gtk_popover_menu_get_stack (popover);
   gtk_stack_add_named (GTK_STACK (stack), submenu, name);
 }
 
@@ -773,7 +792,7 @@ gtk_popover_menu_set_menu_model (GtkPopoverMenu *popover,
       GtkWidget *stack;
       GtkWidget *child;
 
-      stack = gtk_popover_get_child (GTK_POPOVER (popover));
+      stack = gtk_popover_menu_get_stack (popover);
       while ((child = gtk_widget_get_first_child (stack)))
         gtk_stack_remove (GTK_STACK (stack), child);
 
diff --git a/gtk/gtkpopovermenuprivate.h b/gtk/gtkpopovermenuprivate.h
index 4e69627ad4..0a862e0c06 100644
--- a/gtk/gtkpopovermenuprivate.h
+++ b/gtk/gtkpopovermenuprivate.h
@@ -42,6 +42,8 @@ void  gtk_popover_menu_add_submenu (GtkPopoverMenu *popover,
 void gtk_popover_menu_open_submenu (GtkPopoverMenu *popover,
                                     const char     *name);
 
+GtkWidget * gtk_popover_menu_get_stack (GtkPopoverMenu *menu);
+
 G_END_DECLS
 
 #endif /* __GTK_POPOVER_MENU_PRIVATE_H__ */


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