From: Daniel Boles Date: Thu, 17 Aug 2023 09:52:21 +0000 (+0100) Subject: PopoverMenu: Make :flags a property for use in UI… X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2^2~18 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=acd874ec5507f45ad22de7a91478433d27f640a4;p=gtk4.git PopoverMenu: Make :flags a property for use in UI… …files, or other cases other than calling new_from_model_full(), which generally makes it far easier to experiment with the effect of flags, including by changing the value of the property in the Inspector. fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/6030#note_1818229 --- diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h index bcc1373a6f..10543c4cb3 100644 --- a/gtk/gtkenums.h +++ b/gtk/gtkenums.h @@ -1728,5 +1728,18 @@ typedef enum { /*< prefix=GTK_ACCESSIBLE_SORT >*/ GTK_ACCESSIBLE_SORT_OTHER } GtkAccessibleSort; +/** + * GtkPopoverMenuFlags: + * @GTK_POPOVER_MENU_NESTED: Create submenus as nested + * popovers. Without this flag, submenus are created as + * sliding pages that replace the main menu. + * + * Flags that affect how [class@Gtk.PopoverMenu] widgets built from + * a [class@Gio.MenuModel] are created and displayed. + */ +typedef enum { /*< prefix=GTK_POPOVER_MENU >*/ + GTK_POPOVER_MENU_NESTED = 1 << 0 +} GtkPopoverMenuFlags; + G_END_DECLS diff --git a/gtk/gtkpopovermenu.c b/gtk/gtkpopovermenu.c index 52951f65aa..b5b05065a1 100644 --- a/gtk/gtkpopovermenu.c +++ b/gtk/gtkpopovermenu.c @@ -38,7 +38,6 @@ #include "gtkscrolledwindow.h" #include "gtkviewport.h" - /** * GtkPopoverMenu: * @@ -50,6 +49,7 @@ * `GtkPopoverMenu` treats its children like menus and allows switching * between them. It can open submenus as traditional, nested submenus, * or in a more touch-friendly sliding fashion. + * The property [property@Gtk.PopoverMenu:flags] controls this appearance. * * `GtkPopoverMenu` is meant to be used primarily with menu models, * using [ctor@Gtk.PopoverMenu.new_from_model]. If you need to put @@ -173,7 +173,8 @@ struct _GtkPopoverMenuClass enum { PROP_VISIBLE_SUBMENU = 1, - PROP_MENU_MODEL + PROP_MENU_MODEL, + PROP_FLAGS }; static void gtk_popover_menu_buildable_iface_init (GtkBuildableIface *iface); @@ -410,6 +411,10 @@ gtk_popover_menu_get_property (GObject *object, g_value_set_object (value, gtk_popover_menu_get_menu_model (menu)); break; + case PROP_FLAGS: + g_value_set_flags (value, gtk_popover_menu_get_flags (menu)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -434,6 +439,10 @@ gtk_popover_menu_set_property (GObject *object, gtk_popover_menu_set_menu_model (menu, g_value_get_object (value)); break; + case PROP_FLAGS: + gtk_popover_menu_set_flags (menu, g_value_get_flags (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -515,7 +524,6 @@ gtk_popover_menu_focus (GtkWidget *widget, return FALSE; } - static void add_tab_bindings (GtkWidgetClass *widget_class, GdkModifierType modifiers, @@ -616,6 +624,23 @@ gtk_popover_menu_class_init (GtkPopoverMenuClass *klass) G_TYPE_MENU_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GtkPopoverMenu:flags: (attributes org.gtk.Property.get=gtk_popover_menu_get_flags org.gtk.Property.set=gtk_popover_menu_set_flags) + * + * The flags that @popover uses to create/display a menu from its model. + * + * If a model is set and the flags change, contents are rebuilt, so if setting + * properties individually, set flags before model to avoid a redundant rebuild. + * + * Since: 4.14 + */ + g_object_class_install_property (object_class, + PROP_FLAGS, + g_param_spec_flags ("flags", NULL, NULL, + GTK_TYPE_POPOVER_MENU_FLAGS, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS + | G_PARAM_EXPLICIT_NOTIFY)); + add_arrow_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP); add_arrow_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN); add_arrow_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT); @@ -665,6 +690,20 @@ gtk_popover_menu_buildable_iface_init (GtkBuildableIface *iface) iface->add_child = gtk_popover_menu_buildable_add_child; } +static void +gtk_popover_menu_rebuild_contents (GtkPopoverMenu *popover) +{ + GtkWidget *stack; + GtkWidget *child; + + stack = gtk_popover_menu_get_stack (popover); + while ((child = gtk_widget_get_first_child (stack))) + gtk_stack_remove (GTK_STACK (stack), child); + + if (popover->model) + gtk_menu_section_box_new_toplevel (popover, popover->model, popover->flags); +} + /** * gtk_popover_menu_new: * @@ -775,7 +814,7 @@ gtk_popover_menu_new_from_model_full (GMenuModel *model, g_return_val_if_fail (model == NULL || G_IS_MENU_MODEL (model), NULL); popover = gtk_popover_menu_new (); - GTK_POPOVER_MENU (popover)->flags = flags; + gtk_popover_menu_set_flags (GTK_POPOVER_MENU (popover), flags); gtk_popover_menu_set_menu_model (GTK_POPOVER_MENU (popover), model); return popover; @@ -801,18 +840,39 @@ gtk_popover_menu_set_menu_model (GtkPopoverMenu *popover, if (g_set_object (&popover->model, model)) { - GtkWidget *stack; - GtkWidget *child; + gtk_popover_menu_rebuild_contents (popover); + g_object_notify (G_OBJECT (popover), "menu-model"); + } +} - stack = gtk_popover_menu_get_stack (popover); - while ((child = gtk_widget_get_first_child (stack))) - gtk_stack_remove (GTK_STACK (stack), child); +/** + * gtk_popover_menu_set_flags: (attributes org.gtk.Method.set_property=flags) + * @popover: a `GtkPopoverMenu` + * @flags: a set of `GtkPopoverMenuFlags` + * + * Sets the flags that @popover uses to create/display a menu from its model. + * + * If a model is set and the flags change, contents are rebuilt, so if setting + * properties individually, set flags before model to avoid a redundant rebuild. + * + * Since: 4.14 + */ +void +gtk_popover_menu_set_flags (GtkPopoverMenu *popover, + GtkPopoverMenuFlags flags) +{ + g_return_if_fail (GTK_IS_POPOVER_MENU (popover)); - if (model) - gtk_menu_section_box_new_toplevel (popover, model, popover->flags); + if (popover->flags == flags) + return; - g_object_notify (G_OBJECT (popover), "menu-model"); - } + popover->flags = flags; + + /* This shouldn’t happen IRL, but notify test unsets :child, so dodge error */ + if (gtk_popover_get_child (GTK_POPOVER (popover)) != NULL) + gtk_popover_menu_rebuild_contents (popover); + + g_object_notify (G_OBJECT (popover), "flags"); } /** @@ -831,6 +891,24 @@ gtk_popover_menu_get_menu_model (GtkPopoverMenu *popover) return popover->model; } +/** + * gtk_popover_menu_get_flags: (attributes org.gtk.Method.get_property=flags) + * @popover: a `GtkPopoverMenu` + * + * Returns the flags that @popover uses to create/display a menu from its model. + * + * Returns: the `GtkPopoverMenuFlags` + * + * Since: 4.14 + */ +GtkPopoverMenuFlags +gtk_popover_menu_get_flags (GtkPopoverMenu *popover) +{ + g_return_val_if_fail (GTK_IS_POPOVER_MENU (popover), 0); + + return popover->flags; +} + /** * gtk_popover_menu_add_child: * @popover: a `GtkPopoverMenu` diff --git a/gtk/gtkpopovermenu.h b/gtk/gtkpopovermenu.h index 003d2da888..83354405d5 100644 --- a/gtk/gtkpopovermenu.h +++ b/gtk/gtkpopovermenu.h @@ -37,19 +37,6 @@ GType gtk_popover_menu_get_type (void) G_GNUC_CONST; GDK_AVAILABLE_IN_ALL GtkWidget * gtk_popover_menu_new_from_model (GMenuModel *model); -/** - * GtkPopoverMenuFlags: - * @GTK_POPOVER_MENU_NESTED: Create submenus as nested - * popovers. Without this flag, submenus are created as - * sliding pages that replace the main menu. - * - * Flags that affect how popover menus are created from - * a menu model. - */ -typedef enum { - GTK_POPOVER_MENU_NESTED = 1 << 0 -} GtkPopoverMenuFlags; - GDK_AVAILABLE_IN_ALL GtkWidget * gtk_popover_menu_new_from_model_full (GMenuModel *model, GtkPopoverMenuFlags flags); @@ -60,6 +47,12 @@ void gtk_popover_menu_set_menu_model (GtkPopoverMenu *popover, GDK_AVAILABLE_IN_ALL GMenuModel *gtk_popover_menu_get_menu_model (GtkPopoverMenu *popover); +GDK_AVAILABLE_IN_4_14 +void gtk_popover_menu_set_flags (GtkPopoverMenu *popover, + GtkPopoverMenuFlags flags); +GDK_AVAILABLE_IN_4_14 +GtkPopoverMenuFlags gtk_popover_menu_get_flags (GtkPopoverMenu *popover); + GDK_AVAILABLE_IN_ALL gboolean gtk_popover_menu_add_child (GtkPopoverMenu *popover, GtkWidget *child,