From ab7a04d89f0e65981c32269ea67dca592e638339 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 4 Oct 2022 22:46:53 -0400 Subject: [PATCH] inspector: Stop using a treeview for menus Replace this with a GtkColumnView. --- gtk/inspector/menu.c | 274 +++++++++++++++++++++++++++++++++++------- gtk/inspector/menu.ui | 44 +------ 2 files changed, 235 insertions(+), 83 deletions(-) diff --git a/gtk/inspector/menu.c b/gtk/inspector/menu.c index ec7e6901e3..dc14fc5b66 100644 --- a/gtk/inspector/menu.c +++ b/gtk/inspector/menu.c @@ -20,48 +20,227 @@ #include "menu.h" -#include "gtktreestore.h" #include "gtkwidgetprivate.h" #include "gtklabel.h" #include "gtkstack.h" +#include "gtkcolumnview.h" +#include "gtkcolumnviewcolumn.h" +#include "gtktreelistmodel.h" +#include "gtknoselection.h" +#include "gtksignallistitemfactory.h" +#include "gtktreeexpander.h" +#include "gtklistitem.h" -enum +typedef struct _MenuItem MenuItem; + +G_DECLARE_FINAL_TYPE (MenuItem, menu_item, MENU, ITEM, GObject); + +struct _MenuItem { - COLUMN_TYPE, - COLUMN_LABEL, - COLUMN_ACTION, - COLUMN_TARGET, - COLUMN_ICON + GObject parent; + + char *label; + char *action; + char *target; + char *icon; + GMenuModel *model; }; +G_DEFINE_TYPE (MenuItem, menu_item, G_TYPE_OBJECT); + +static void +menu_item_init (MenuItem *self) +{ +} + +static void +menu_item_finalize (GObject *object) +{ + MenuItem *self = MENU_ITEM (object); + + g_free (self->label); + g_free (self->action); + g_free (self->target); + g_free (self->icon); + g_clear_object (&self->model); + + G_OBJECT_CLASS (menu_item_parent_class)->finalize (object); +} + +static void +menu_item_class_init (MenuItemClass *class) +{ + G_OBJECT_CLASS (class)->finalize = menu_item_finalize; +} + +static MenuItem * +menu_item_new (const char *label, + const char *action, + const char *target, + const char *icon, + GMenuModel *model) +{ + MenuItem *self; + + self = g_object_new (menu_item_get_type (), NULL); + self->label = g_strdup (label); + self->action = g_strdup (action); + self->target = g_strdup (target); + self->icon = g_strdup (icon); + g_set_object (&self->model, model); + + return self; +} + struct _GtkInspectorMenuPrivate { - GtkTreeStore *model; + GtkColumnView *view; + GtkTreeListModel *tree_model; }; G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorMenu, gtk_inspector_menu, GTK_TYPE_BOX) +static GListModel * create_model (gpointer item, gpointer user_data); + +static void +setup_label (GtkListItemFactory *factory, + GtkListItem *item) +{ + GtkWidget *expander; + GtkWidget *label; + + expander = gtk_tree_expander_new (); + label = gtk_label_new (NULL); + gtk_label_set_xalign (GTK_LABEL (label), 0.); + gtk_tree_expander_set_child (GTK_TREE_EXPANDER (expander), label); + + gtk_list_item_set_child (item, expander); +} + +static void +bind_label (GtkListItemFactory *factory, + GtkListItem *item) +{ + GtkWidget *expander; + GtkWidget *label; + GtkTreeListRow *row; + MenuItem *menu_item; + + row = gtk_list_item_get_item (item); + menu_item = gtk_tree_list_row_get_item (row); + + expander = gtk_list_item_get_child (item); + gtk_tree_expander_set_list_row (GTK_TREE_EXPANDER (expander), row); + + label = gtk_tree_expander_get_child (GTK_TREE_EXPANDER (expander)); + gtk_label_set_label (GTK_LABEL (label), menu_item->label); +} + +static void +setup_action (GtkListItemFactory *factory, + GtkListItem *item) +{ + GtkWidget *label; + + label = gtk_label_new (NULL); + gtk_label_set_xalign (GTK_LABEL (label), 0.); + + gtk_list_item_set_child (item, label); +} + +static void +bind_action (GtkListItemFactory *factory, + GtkListItem *item) +{ + GtkWidget *label; + GtkTreeListRow *row; + MenuItem *menu_item; + + row = gtk_list_item_get_item (item); + menu_item = gtk_tree_list_row_get_item (row); + + label = gtk_list_item_get_child (item); + gtk_label_set_label (GTK_LABEL (label), menu_item->action); +} + +static void +setup_target (GtkListItemFactory *factory, + GtkListItem *item) +{ + GtkWidget *label; + + label = gtk_label_new (NULL); + gtk_label_set_xalign (GTK_LABEL (label), 0.); + + gtk_list_item_set_child (item, label); +} + +static void +bind_target (GtkListItemFactory *factory, + GtkListItem *item) +{ + GtkWidget *label; + GtkTreeListRow *row; + MenuItem *menu_item; + + row = gtk_list_item_get_item (item); + menu_item = gtk_tree_list_row_get_item (row); + + label = gtk_list_item_get_child (item); + gtk_label_set_label (GTK_LABEL (label), menu_item->target); +} + static void gtk_inspector_menu_init (GtkInspectorMenu *sl) { + GtkTreeListModel *store; + GtkColumnViewColumn *column; + GtkListItemFactory *factory; + sl->priv = gtk_inspector_menu_get_instance_private (sl); gtk_widget_init_template (GTK_WIDGET (sl)); -} -static void add_menu (GtkInspectorMenu *sl, - GtkStackPage *page, - GMenuModel *menu, - GtkTreeIter *parent); + store = gtk_tree_list_model_new (G_LIST_MODEL (g_list_store_new (menu_item_get_type ())), + FALSE, FALSE, + create_model, + sl, NULL); + + gtk_column_view_set_model (sl->priv->view, GTK_SELECTION_MODEL (gtk_no_selection_new (G_LIST_MODEL (store)))); + + column = g_list_model_get_item (gtk_column_view_get_columns (sl->priv->view), 0); + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_label), NULL); + gtk_column_view_column_set_factory (column, factory); + g_object_unref (factory); + g_object_unref (column); + + column = g_list_model_get_item (gtk_column_view_get_columns (sl->priv->view), 1); + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_action), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_action), NULL); + gtk_column_view_column_set_factory (column, factory); + g_object_unref (factory); + g_object_unref (column); + + column = g_list_model_get_item (gtk_column_view_get_columns (sl->priv->view), 2); + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_target), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_target), NULL); + gtk_column_view_column_set_factory (column, factory); + g_object_unref (factory); + g_object_unref (column); + + sl->priv->tree_model = store; +} static void add_item (GtkInspectorMenu *sl, - GtkStackPage *page, GMenuModel *menu, int idx, - GtkTreeIter *parent) + GListStore *store) { - GtkTreeIter iter; GVariant *value; char *label = NULL; char *action = NULL; @@ -78,33 +257,18 @@ add_item (GtkInspectorMenu *sl, g_variant_unref (value); } - gtk_tree_store_append (sl->priv->model, &iter, parent); - gtk_tree_store_set (sl->priv->model, &iter, - COLUMN_TYPE, "item", - COLUMN_LABEL, label, - COLUMN_ACTION, action, - COLUMN_TARGET, target, - COLUMN_ICON, icon, - -1); - model = g_menu_model_get_item_link (menu, idx, G_MENU_LINK_SECTION); if (model) { if (label == NULL) - gtk_tree_store_set (sl->priv->model, &iter, - COLUMN_LABEL, _("Unnamed section"), - -1); - add_menu (sl, page, model, &iter); - g_object_unref (model); + label = g_strdup (_("Unnamed section")); } + else + model = g_menu_model_get_item_link (menu, idx, G_MENU_LINK_SUBMENU); - model = g_menu_model_get_item_link (menu, idx, G_MENU_LINK_SUBMENU); - if (model) - { - add_menu (sl, page, model, &iter); - g_object_unref (model); - } + g_list_store_append (store, menu_item_new (label, action, target, icon, model)); + g_clear_object (&model); g_free (label); g_free (action); g_free (target); @@ -113,18 +277,32 @@ add_item (GtkInspectorMenu *sl, static void add_menu (GtkInspectorMenu *sl, - GtkStackPage *page, GMenuModel *menu, - GtkTreeIter *parent) + GListStore *store) { int n_items; int i; - g_object_set (page, "visible", TRUE, NULL); - n_items = g_menu_model_get_n_items (menu); for (i = 0; i < n_items; i++) - add_item (sl, page, menu, i, parent); + add_item (sl, menu, i, store); +} + +static GListModel * +create_model (gpointer item, + gpointer user_data) +{ + MenuItem *self = item; + GtkInspectorMenu *sl = user_data; + GListStore *store; + + if (self->model == NULL) + return NULL; + + store = g_list_store_new (menu_item_get_type ()); + add_menu (sl, self->model, store); + + return G_LIST_MODEL (store); } void @@ -133,15 +311,21 @@ gtk_inspector_menu_set_object (GtkInspectorMenu *sl, { GtkWidget *stack; GtkStackPage *page; + GListStore *store; stack = gtk_widget_get_parent (GTK_WIDGET (sl)); page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl)); g_object_set (page, "visible", FALSE, NULL); - gtk_tree_store_clear (sl->priv->model); - + + store = G_LIST_STORE (gtk_tree_list_model_get_model (sl->priv->tree_model)); + g_list_store_remove_all (store); + if (G_IS_MENU_MODEL (object)) - add_menu (sl, page, G_MENU_MODEL (object), NULL); + { + g_object_set (page, "visible", TRUE, NULL); + add_menu (sl, G_MENU_MODEL (object), store); + } } static void @@ -150,7 +334,7 @@ gtk_inspector_menu_class_init (GtkInspectorMenuClass *klass) GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/menu.ui"); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMenu, model); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMenu, view); } // vim: set et sw=2 ts=2: diff --git a/gtk/inspector/menu.ui b/gtk/inspector/menu.ui index 2546256e84..4820f4f718 100644 --- a/gtk/inspector/menu.ui +++ b/gtk/inspector/menu.ui @@ -16,58 +16,26 @@ 1 always - - model + - + Label - - - 0.8 - - - 1 - - - + Action - - - 0.8 - - - 2 - - - + Target - - - 0.8 - - - 3 - - - + Icon - - - 0.8 - - - 4 - - + 1