diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-10-20 14:26:45 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-10-26 22:41:33 -0400 |
commit | 8157abe591059116cbea1a8ad7007fdd061ab0ba (patch) | |
tree | 711bd87b8232a85f6faf5de5aff47b0db0e4fc79 /gtk/gtkmenusectionbox.c | |
parent | 61e08baec1d55ee533a20ec5fffd91b797daa5d1 (diff) | |
download | gtk+-8157abe591059116cbea1a8ad7007fdd061ab0ba.tar.gz |
popovermenu: Allow custom items
Add a way to add children at certain places in
the generated menu for both GtkPopoverMenu and
GtkPopoverMenuBar.
New apis:
gtk_popover_menu_add_child
gtk_popover_menu_remove_child
gtk_popover_menu_bar_add_child
gtk_popover_menu_bar_remove_child
Fixes: #3260
Diffstat (limited to 'gtk/gtkmenusectionbox.c')
-rw-r--r-- | gtk/gtkmenusectionbox.c | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/gtk/gtkmenusectionbox.c b/gtk/gtkmenusectionbox.c index 08f5ca1288..9f988d98f5 100644 --- a/gtk/gtkmenusectionbox.c +++ b/gtk/gtkmenusectionbox.c @@ -32,6 +32,8 @@ #include "gtkpopovermenuprivate.h" #include "gtkorientable.h" #include "gtkbuiltiniconprivate.h" +#include "gtkgizmoprivate.h" +#include "gtkbinlayout.h" typedef GtkBoxClass GtkMenuSectionBoxClass; @@ -50,6 +52,7 @@ struct _GtkMenuSectionBox int depth; GtkPopoverMenuFlags flags; GtkSizeGroup *indicators; + GHashTable *custom_slots; }; typedef struct @@ -341,6 +344,22 @@ gtk_menu_section_box_insert_func (GtkMenuTrackerItem *item, g_free (name); } } + else if (gtk_menu_tracker_item_get_custom (item)) + { + const char *id = gtk_menu_tracker_item_get_custom (item); + + widget = gtk_gizmo_new ("widget", NULL, NULL, NULL, NULL, NULL, NULL); + gtk_widget_set_layout_manager (widget, gtk_bin_layout_new ()); + + if (g_hash_table_lookup (box->custom_slots, id)) + g_warning ("Duplicate custom ID: %s", id); + else + { + char *slot_id = g_strdup (id); + g_object_set_data_full (G_OBJECT (widget), "slot-id", slot_id, g_free); + g_hash_table_insert (box->custom_slots, slot_id, widget); + } + } else { widget = g_object_new (GTK_TYPE_MODEL_BUTTON, @@ -458,6 +477,7 @@ gtk_menu_section_box_dispose (GObject *object) } g_clear_object (&box->indicators); + g_clear_pointer (&box->custom_slots, g_hash_table_unref); G_OBJECT_CLASS (gtk_menu_section_box_parent_class)->dispose (object); } @@ -499,8 +519,9 @@ gtk_menu_section_box_new_toplevel (GtkPopoverMenu *popover, { GtkMenuSectionBox *box; - box = g_object_new (GTK_TYPE_MENU_SECTION_BOX, NULL); + box = g_object_new (GTK_TYPE_MENU_SECTION_BOX, NULL); box->indicators = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + box->custom_slots = g_hash_table_new (g_str_hash, g_str_equal); box->flags = flags; gtk_popover_menu_add_submenu (popover, GTK_WIDGET (box), "main"); @@ -524,6 +545,7 @@ gtk_menu_section_box_new_submenu (GtkMenuTrackerItem *item, box = g_object_new (GTK_TYPE_MENU_SECTION_BOX, NULL); box->indicators = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + box->custom_slots = g_hash_table_ref (toplevel->custom_slots); box->flags = toplevel->flags; button = g_object_new (GTK_TYPE_MODEL_BUTTON, @@ -562,6 +584,7 @@ gtk_menu_section_box_new_section (GtkMenuTrackerItem *item, box = g_object_new (GTK_TYPE_MENU_SECTION_BOX, NULL); box->indicators = g_object_ref (parent->indicators); + box->custom_slots = g_hash_table_ref (parent->toplevel->custom_slots); box->toplevel = parent->toplevel; box->depth = parent->depth + 1; box->flags = parent->flags; @@ -661,3 +684,54 @@ gtk_menu_section_box_new_section (GtkMenuTrackerItem *item, return GTK_WIDGET (box); } + +gboolean +gtk_menu_section_box_add_custom (GtkPopoverMenu *popover, + GtkWidget *child, + const char *id) +{ + GtkWidget *stack; + GtkMenuSectionBox *box; + GtkWidget *slot; + + stack = gtk_popover_get_child (GTK_POPOVER (popover)); + box = GTK_MENU_SECTION_BOX (gtk_stack_get_child_by_name (GTK_STACK (stack), "main")); + + slot = (GtkWidget *)g_hash_table_lookup (box->custom_slots, id); + + if (slot == NULL) + return FALSE; + + if (gtk_widget_get_first_child (slot)) + return FALSE; + + gtk_widget_insert_before (child, slot, NULL); + return TRUE; +} + +gboolean +gtk_menu_section_box_remove_custom (GtkPopoverMenu *popover, + GtkWidget *child) +{ + GtkWidget *stack; + GtkMenuSectionBox *box; + GtkWidget *parent; + const char *id; + GtkWidget *slot; + + stack = gtk_popover_get_child (GTK_POPOVER (popover)); + box = GTK_MENU_SECTION_BOX (gtk_stack_get_child_by_name (GTK_STACK (stack), "main")); + parent = gtk_widget_get_parent (child); + + id = (const char *) g_object_get_data (G_OBJECT (parent), "slot-id"); + g_return_val_if_fail (id != NULL, FALSE); + + slot = (GtkWidget *)g_hash_table_lookup (box->custom_slots, id); + + if (slot != parent) + return FALSE; + + gtk_widget_unparent (child); + + return TRUE; +} |