From 89db59a40d81f3e1cec168e0a4ada8900fb7f941 Mon Sep 17 00:00:00 2001 From: Mat Date: Sun, 17 Jul 2022 22:24:51 +0300 Subject: [PATCH] treepopover: Add support for scrolling Add support for scrolling large tree popovers in a similar fashion to GtkPopoverMenu. Fixes #3674 Fixes #4877 --- gtk/gtktreepopover.c | 31 ++++++++--- testsuite/css/nodes/combobox.nodes | 82 ++++++++++++++++++++++-------- 2 files changed, 85 insertions(+), 28 deletions(-) diff --git a/gtk/gtktreepopover.c b/gtk/gtktreepopover.c index 8ff89b00a4..7a0881b6e4 100644 --- a/gtk/gtktreepopover.c +++ b/gtk/gtktreepopover.c @@ -30,6 +30,8 @@ #include "gtkgizmoprivate.h" #include "gtkwidgetprivate.h" #include "gtkbuiltiniconprivate.h" +#include "gtkscrolledwindow.h" +#include "gtkviewport.h" // TODO // positioning + sizing @@ -222,12 +224,22 @@ gtk_tree_popover_class_init (GtkTreePopoverClass *class) G_TYPE_NONE, 1, G_TYPE_STRING); } +static GtkWidget * +gtk_tree_popover_get_stack (GtkTreePopover *popover) +{ + GtkWidget *sw = gtk_popover_get_child (GTK_POPOVER (popover)); + 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_tree_popover_add_submenu (GtkTreePopover *popover, GtkWidget *submenu, const char *name) { - GtkWidget *stack = gtk_popover_get_child (GTK_POPOVER (popover)); + GtkWidget *stack = gtk_tree_popover_get_stack (popover); gtk_stack_add_named (GTK_STACK (stack), submenu, name); } @@ -235,7 +247,7 @@ static GtkWidget * gtk_tree_popover_get_submenu (GtkTreePopover *popover, const char *name) { - GtkWidget *stack = gtk_popover_get_child (GTK_POPOVER (popover)); + GtkWidget *stack = gtk_tree_popover_get_stack (popover); return gtk_stack_get_child_by_name (GTK_STACK (stack), name); } @@ -243,20 +255,27 @@ void gtk_tree_popover_open_submenu (GtkTreePopover *popover, const char *name) { - GtkWidget *stack = gtk_popover_get_child (GTK_POPOVER (popover)); + GtkWidget *stack = gtk_tree_popover_get_stack (popover); gtk_stack_set_visible_child_name (GTK_STACK (stack), name); } static void gtk_tree_popover_init (GtkTreePopover *popover) { + GtkWidget *sw; GtkWidget *stack; + 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); gtk_widget_add_css_class (GTK_WIDGET (popover), "menu"); } @@ -461,7 +480,7 @@ static GtkWidget * gtk_tree_popover_get_path_item (GtkTreePopover *popover, GtkTreePath *search) { - GtkWidget *stack = gtk_popover_get_child (GTK_POPOVER (popover)); + GtkWidget *stack = gtk_tree_popover_get_stack (popover); GtkWidget *item = NULL; GtkWidget *stackchild; GtkWidget *child; @@ -775,7 +794,7 @@ rebuild_menu (GtkTreePopover *popover) GtkWidget *stack; GtkWidget *child; - stack = gtk_popover_get_child (GTK_POPOVER (popover)); + stack = gtk_tree_popover_get_stack (popover); while ((child = gtk_widget_get_first_child (stack))) gtk_stack_remove (GTK_STACK (stack), child); diff --git a/testsuite/css/nodes/combobox.nodes b/testsuite/css/nodes/combobox.nodes index e0ac7310fc..c18ead0413 100644 --- a/testsuite/css/nodes/combobox.nodes +++ b/testsuite/css/nodes/combobox.nodes @@ -8,17 +8,36 @@ window.background:dir(ltr) arrow:dir(ltr) [popover.background.menu:dir(ltr)] contents:dir(ltr) - stack:dir(ltr) - box.vertical:dir(ltr) - modelbutton.flat:dir(ltr) - cellview:dir(ltr) - none.right:dir(ltr) - modelbutton.flat:dir(ltr) - cellview:dir(ltr) - none.right:dir(ltr) - modelbutton.flat:dir(ltr) - cellview:dir(ltr) - none.right:dir(ltr) + scrolledwindow:dir(ltr) + viewport:dir(ltr) + stack:dir(ltr) + box.vertical:dir(ltr) + modelbutton.flat:dir(ltr) + cellview:dir(ltr) + none.right:dir(ltr) + modelbutton.flat:dir(ltr) + cellview:dir(ltr) + none.right:dir(ltr) + modelbutton.flat:dir(ltr) + cellview:dir(ltr) + none.right:dir(ltr) + scrollbar.bottom.horizontal:dir(ltr) + range.horizontal:dir(ltr) + trough:dir(ltr) + slider:dir(ltr) + scrollbar.right.vertical:dir(ltr) + range.vertical:dir(ltr) + trough:dir(ltr) + slider:dir(ltr) + overshoot.left:dir(ltr) + undershoot.left:dir(ltr) + overshoot.right:dir(ltr) + undershoot.right:dir(ltr) + overshoot.top:dir(ltr) + undershoot.top:dir(ltr) + overshoot.bottom:dir(ltr) + undershoot.bottom:dir(ltr) + junction:dir(ltr) arrow:dir(ltr) combobox:dir(ltr) box.horizontal.linked:dir(ltr) @@ -31,15 +50,34 @@ window.background:dir(ltr) arrow:dir(ltr) [popover.background.menu:dir(ltr)] contents:dir(ltr) - stack:dir(ltr) - box.vertical:dir(ltr) - modelbutton.flat:dir(ltr) - cellview:dir(ltr) - none.right:dir(ltr) - modelbutton.flat:dir(ltr) - cellview:dir(ltr) - none.right:dir(ltr) - modelbutton.flat:dir(ltr) - cellview:dir(ltr) - none.right:dir(ltr) + scrolledwindow:dir(ltr) + viewport:dir(ltr) + stack:dir(ltr) + box.vertical:dir(ltr) + modelbutton.flat:dir(ltr) + cellview:dir(ltr) + none.right:dir(ltr) + modelbutton.flat:dir(ltr) + cellview:dir(ltr) + none.right:dir(ltr) + modelbutton.flat:dir(ltr) + cellview:dir(ltr) + none.right:dir(ltr) + scrollbar.bottom.horizontal:dir(ltr) + range.horizontal:dir(ltr) + trough:dir(ltr) + slider:dir(ltr) + scrollbar.right.vertical:dir(ltr) + range.vertical:dir(ltr) + trough:dir(ltr) + slider:dir(ltr) + overshoot.left:dir(ltr) + undershoot.left:dir(ltr) + overshoot.right:dir(ltr) + undershoot.right:dir(ltr) + overshoot.top:dir(ltr) + undershoot.top:dir(ltr) + overshoot.bottom:dir(ltr) + undershoot.bottom:dir(ltr) + junction:dir(ltr) arrow:dir(ltr)