[gtk/prop-list: 3/33] inspector: Use a column view for properties



commit 0b235d1adeb8dd0c1bf699f37f52aacece99b346
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Dec 2 21:00:22 2019 -0500

    inspector: Use a column view for properties
    
    Just a straight conversion from list box to column view.

 gtk/inspector/meson.build   |   1 +
 gtk/inspector/prop-holder.c | 145 ++++++++++++++++
 gtk/inspector/prop-holder.h |  17 ++
 gtk/inspector/prop-list.c   | 414 ++++++++++++++++++++++----------------------
 gtk/inspector/prop-list.ui  | 129 +++++---------
 5 files changed, 412 insertions(+), 294 deletions(-)
---
diff --git a/gtk/inspector/meson.build b/gtk/inspector/meson.build
index a26d67ed87..f297fe2d0a 100644
--- a/gtk/inspector/meson.build
+++ b/gtk/inspector/meson.build
@@ -35,4 +35,5 @@ inspector_sources = files(
   'updatesoverlay.c',
   'visual.c',
   'window.c',
+  'prop-holder.c'
 )
diff --git a/gtk/inspector/prop-holder.c b/gtk/inspector/prop-holder.c
new file mode 100644
index 0000000000..b6541052de
--- /dev/null
+++ b/gtk/inspector/prop-holder.c
@@ -0,0 +1,145 @@
+#include "prop-holder.h"
+
+enum {
+  PROP_OBJECT = 1,
+  PROP_PSPEC,
+  PROP_NAME,
+  NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES];
+
+struct _PropHolder {
+  GObject instance;
+
+  GObject *object;
+  GParamSpec *pspec;
+};
+
+G_DEFINE_TYPE (PropHolder, prop_holder, G_TYPE_OBJECT)
+
+static void
+prop_holder_init (PropHolder *holder)
+{
+}
+
+static void
+prop_holder_set_property (GObject      *object,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+  PropHolder *holder = PROP_HOLDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      holder->object = g_value_dup_object (value);
+      break;
+
+    case PROP_PSPEC:
+      holder->pspec = g_value_get_param (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+prop_holder_get_property (GObject    *object,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+  PropHolder *holder = PROP_HOLDER (object);
+
+  switch (prop_id)
+    {
+    case PROP_OBJECT:
+      g_value_set_object (value, holder->object);
+      break;
+
+    case PROP_PSPEC:
+      g_value_set_param (value, holder->pspec);
+      break;
+
+    case PROP_NAME:
+      g_value_set_string (value, holder->pspec->name);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+prop_holder_finalize (GObject *object)
+{
+  PropHolder *holder = PROP_HOLDER (object);
+
+  g_object_unref (holder->object);
+
+  G_OBJECT_CLASS (prop_holder_parent_class)->finalize (object);
+}
+
+static void
+prop_holder_class_init (PropHolderClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->finalize = prop_holder_finalize;
+  object_class->set_property = prop_holder_set_property;
+  object_class->get_property = prop_holder_get_property;
+
+  properties[PROP_OBJECT] =
+      g_param_spec_object ("object", "object", "object",
+                           G_TYPE_OBJECT,
+                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_PSPEC] =
+      g_param_spec_param ("pspec", "pspec", "pspec",
+                          G_TYPE_PARAM,
+                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_NAME] =
+      g_param_spec_string ("name", "name", "name",
+                           NULL,
+                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
+}
+
+PropHolder *
+prop_holder_new (GObject    *object,
+                 GParamSpec *pspec)
+{
+  PropHolder *holder;
+
+  holder = g_object_new (PROP_TYPE_HOLDER,
+                         "object", object,
+                         "pspec", pspec,
+                         NULL);
+
+  return holder;
+}
+
+GObject *
+prop_holder_get_object (PropHolder *holder)
+{
+  return holder->object;
+}
+
+GParamSpec *
+prop_holder_get_pspec (PropHolder *holder)
+{
+  return holder->pspec;
+}
+
+const char *
+prop_holder_get_name (PropHolder *holder)
+{
+  return holder->pspec->name;
+}
diff --git a/gtk/inspector/prop-holder.h b/gtk/inspector/prop-holder.h
new file mode 100644
index 0000000000..2e4e637e5c
--- /dev/null
+++ b/gtk/inspector/prop-holder.h
@@ -0,0 +1,17 @@
+#ifndef __PROP_HOLDER_H__
+#define __PROP_HOLDER_H__
+
+#include <gtk/gtk.h>
+
+#define PROP_TYPE_HOLDER (prop_holder_get_type ())
+
+G_DECLARE_FINAL_TYPE (PropHolder, prop_holder, PROP, HOLDER, GObject)
+
+PropHolder * prop_holder_new         (GObject    *object,
+                                      GParamSpec *pspeC);
+
+GObject    *prop_holder_get_object   (PropHolder *holder);
+GParamSpec *prop_holder_get_pspec    (PropHolder *holder);
+const char *prop_holder_get_name     (PropHolder *holder);
+
+#endif /* __PROP_HOLDER_H__ */
diff --git a/gtk/inspector/prop-list.c b/gtk/inspector/prop-list.c
index 69282bd7ce..9ba203258f 100644
--- a/gtk/inspector/prop-list.c
+++ b/gtk/inspector/prop-list.c
@@ -44,6 +44,7 @@
 #include "gtkroot.h"
 #include "gtkgestureclick.h"
 #include "gtkstylecontext.h"
+#include "prop-holder.h"
 
 enum
 {
@@ -52,11 +53,6 @@ enum
   PROP_SEARCH_ENTRY
 };
 
-typedef enum {
-  COLUMN_NAME,
-  COLUMN_ORIGIN
-} SortColumn;
-
 struct _GtkInspectorPropListPrivate
 {
   GObject *object;
@@ -64,17 +60,11 @@ struct _GtkInspectorPropListPrivate
   GtkInspectorObjectTree *object_tree;
   GtkWidget *search_entry;
   GtkWidget *search_stack;
-  GtkWidget *list2;
-  GtkWidget *name_sort_indicator;
-  GtkWidget *origin_sort_indicator;
-  GtkWidget *name_heading;
-  GtkWidget *origin_heading;
-  SortColumn sort_column;
-  GtkSortType sort_direction;
-  GtkSizeGroup *names;
-  GtkSizeGroup *types;
-  GtkSizeGroup *values;
-  GtkSizeGroup *origins;
+  GtkWidget *list;
+  GtkFilter *filter;
+  GtkColumnViewColumn *name;
+  GtkColumnViewColumn *type;
+  GtkColumnViewColumn *origin;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorPropList, gtk_inspector_prop_list, GTK_TYPE_BOX)
@@ -94,103 +84,66 @@ show_search_entry (GtkInspectorPropList *pl)
                                pl->priv->search_entry);
 }
 
-static void
-apply_sort (GtkInspectorPropList *pl,
-            SortColumn            column,
-            GtkSortType           direction)
+static char *
+holder_prop (gpointer item)
 {
-  const char *icon_name;
+  GParamSpec *prop = prop_holder_get_pspec (PROP_HOLDER (item));
 
-  icon_name = direction == GTK_SORT_ASCENDING ? "pan-down-symbolic"
-                                              : "pan-up-symbolic";
-
-  if (column == COLUMN_NAME)
-    {
-      gtk_image_clear (GTK_IMAGE (pl->priv->origin_sort_indicator));
-      gtk_image_set_from_icon_name (GTK_IMAGE (pl->priv->name_sort_indicator),
-                                    icon_name);
-    }
-  else
-    {
-      gtk_image_clear (GTK_IMAGE (pl->priv->name_sort_indicator));
-      gtk_image_set_from_icon_name (GTK_IMAGE (pl->priv->origin_sort_indicator),
-                                    icon_name);
-    }
-
-  pl->priv->sort_column = column;
-  pl->priv->sort_direction = direction;
-
-  gtk_list_box_invalidate_sort (GTK_LIST_BOX (pl->priv->list2));
+  return g_strdup (prop->name);
 }
 
-static void
-sort_changed (GtkGestureClick      *gesture,
-              int                   n_press,
-              double                x,
-              double                y,
-              GtkInspectorPropList *pl)
-{
-  SortColumn column;
-  GtkSortType direction;
-  GtkWidget *widget;
-
-  widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
-  if (widget == pl->priv->name_heading)
-    column = COLUMN_NAME;
-  else
-    column = COLUMN_ORIGIN;
-
-  if (pl->priv->sort_column == column &&
-      pl->priv->sort_direction == GTK_SORT_ASCENDING)
-    direction = GTK_SORT_DESCENDING;
-  else
-    direction = GTK_SORT_ASCENDING;
-
-  apply_sort (pl, column, direction);
-}
-
-static const char *
-row_get_column (GtkListBoxRow *row,
-                SortColumn     column)
+static char *
+holder_type (gpointer item)
 {
-  GParamSpec *prop = g_object_get_data (G_OBJECT (row), "pspec");
+  GParamSpec *prop = prop_holder_get_pspec (PROP_HOLDER (item));
 
-  if (column == COLUMN_NAME)
-    return prop->name;
-  else
-    return g_type_name (prop->owner_type);
+  return g_strdup (g_type_name (prop->value_type));
 }
 
-static int
-sort_func (GtkListBoxRow *row1,
-           GtkListBoxRow *row2,
-           gpointer       user_data)
+static char *
+holder_origin (gpointer item)
 {
-  GtkInspectorPropList *pl = user_data;
-  const char *s1 = row_get_column (row1, pl->priv->sort_column);
-  const char *s2 = row_get_column (row2, pl->priv->sort_column);
-  int ret = strcmp (s1, s2);
-
-  return pl->priv->sort_direction == GTK_SORT_ASCENDING ? ret : -ret;
-}
+  GParamSpec *prop = prop_holder_get_pspec (PROP_HOLDER (item));
 
-static gboolean
-filter_func (GtkListBoxRow *row,
-             gpointer       data)
-{
-  GtkInspectorPropList *pl = data;
-  GParamSpec *pspec = (GParamSpec *)g_object_get_data (G_OBJECT (row), "pspec");
-  const char *text = gtk_editable_get_text (GTK_EDITABLE (pl->priv->search_entry));
-  
-  return g_str_has_prefix (pspec->name, text);
+  return g_strdup (g_type_name (prop->owner_type));
 }
 
 static void
 gtk_inspector_prop_list_init (GtkInspectorPropList *pl)
 {
+  GtkSorter *sorter;
+
   pl->priv = gtk_inspector_prop_list_get_instance_private (pl);
   gtk_widget_init_template (GTK_WIDGET (pl));
-  apply_sort (pl, COLUMN_NAME, GTK_SORT_ASCENDING);
+  pl->priv->filter = gtk_string_filter_new ();
+  gtk_string_filter_set_match_mode (GTK_STRING_FILTER (pl->priv->filter), 
GTK_STRING_FILTER_MATCH_MODE_PREFIX);
+
+  sorter = gtk_string_sorter_new (gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
+                                                               0, NULL,
+                                                               (GCallback)holder_prop,
+                                                               NULL, NULL));
+ 
+  gtk_string_filter_set_expression (GTK_STRING_FILTER (pl->priv->filter),
+                                    gtk_string_sorter_get_expression (GTK_STRING_SORTER (sorter)));
+
+  gtk_column_view_column_set_sorter (pl->priv->name, sorter);
+  g_object_unref (sorter);
+
+  sorter = gtk_string_sorter_new (gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
+                                                               0, NULL,
+                                                               (GCallback)holder_type,
+                                                               NULL, NULL));
+
+  gtk_column_view_column_set_sorter (pl->priv->type, sorter);
+  g_object_unref (sorter);
+
+  sorter = gtk_string_sorter_new (gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
+                                                               0, NULL,
+                                                               (GCallback)holder_origin,
+                                                               NULL, NULL));
+
+  gtk_column_view_column_set_sorter (pl->priv->origin, sorter);
+  g_object_unref (sorter);
 }
 
 static void
@@ -253,6 +206,7 @@ show_object (GtkInspectorPropEditor *editor,
   gtk_inspector_object_tree_activate_object (pl->priv->object_tree, object);
 }
 
+
 static void cleanup_object (GtkInspectorPropList *pl);
 
 static void
@@ -262,14 +216,19 @@ finalize (GObject *object)
 
   cleanup_object (pl);
 
-  g_object_unref (pl->priv->names);
-  g_object_unref (pl->priv->types);
-  g_object_unref (pl->priv->values);
-  g_object_unref (pl->priv->origins);
-
   G_OBJECT_CLASS (gtk_inspector_prop_list_parent_class)->finalize (object);
 }
 
+static void
+update_filter (GtkInspectorPropList *pl,
+               GtkSearchEntry *entry)
+{
+  const char *text;
+
+  text = gtk_editable_get_text (GTK_EDITABLE (entry));
+  gtk_string_filter_set_search (GTK_STRING_FILTER (pl->priv->filter), text);
+}
+
 static void
 constructed (GObject *object)
 {
@@ -283,10 +242,7 @@ constructed (GObject *object)
   g_signal_connect_swapped (pl->priv->search_entry, "search-started",
                             G_CALLBACK (show_search_entry), pl);
   g_signal_connect_swapped (pl->priv->search_entry, "search-changed",
-                            G_CALLBACK (gtk_list_box_invalidate_filter), pl->priv->list2);
-
-  gtk_list_box_set_filter_func (GTK_LIST_BOX (pl->priv->list2), filter_func, pl, NULL);
-  gtk_list_box_set_sort_func (GTK_LIST_BOX (pl->priv->list2), sort_func, pl, NULL);
+                            G_CALLBACK (update_filter), pl);
 }
 
 static void
@@ -303,7 +259,7 @@ update_key_capture (GtkInspectorPropList *pl)
       focus = gtk_root_get_focus (GTK_ROOT (toplevel));
 
       if (GTK_IS_EDITABLE (focus) &&
-          gtk_widget_is_ancestor (focus, pl->priv->list2))
+          gtk_widget_is_ancestor (focus, pl->priv->list))
         capture_widget = NULL;
       else
         capture_widget = toplevel;
@@ -349,6 +305,120 @@ unroot (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_inspector_prop_list_parent_class)->unroot (widget);
 }
 
+static void
+setup_name_cb (GtkSignalListItemFactory *factory,
+               GtkListItem              *list_item)
+{
+  GtkWidget *label;
+
+  label = gtk_label_new (NULL);
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_list_item_set_child (list_item, label);
+  gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
+}
+
+static void
+bind_name_cb (GtkSignalListItemFactory *factory,
+              GtkListItem              *list_item)
+{
+  GObject *item;
+  GtkWidget *label;
+
+  item = gtk_list_item_get_item (list_item);
+  label = gtk_list_item_get_child (list_item);
+
+  gtk_label_set_label (GTK_LABEL (label), prop_holder_get_name (PROP_HOLDER (item)));
+}
+
+static void
+setup_type_cb (GtkSignalListItemFactory *factory,
+               GtkListItem              *list_item)
+{
+  GtkWidget *label;
+
+  label = gtk_label_new (NULL);
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_list_item_set_child (list_item, label);
+  gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
+}
+
+static void
+bind_type_cb (GtkSignalListItemFactory *factory,
+              GtkListItem              *list_item)
+{
+  GObject *item;
+  GtkWidget *label;
+  GParamSpec *prop;
+  const char *type;
+
+  item = gtk_list_item_get_item (list_item);
+  label = gtk_list_item_get_child (list_item);
+
+  prop = prop_holder_get_pspec (PROP_HOLDER (item));
+  type = g_type_name (G_PARAM_SPEC_VALUE_TYPE (prop));
+
+  gtk_label_set_label (GTK_LABEL (label), type);
+}
+
+static void
+setup_origin_cb (GtkSignalListItemFactory *factory,
+                 GtkListItem              *list_item)
+{
+  GtkWidget *label;
+
+  label = gtk_label_new (NULL);
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_list_item_set_child (list_item, label);
+  gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
+}
+
+static void
+bind_origin_cb (GtkSignalListItemFactory *factory,
+                GtkListItem              *list_item)
+{
+  GObject *item;
+  GtkWidget *label;
+  GParamSpec *prop;
+  const char *origin;
+
+  item = gtk_list_item_get_item (list_item);
+  label = gtk_list_item_get_child (list_item);
+
+  prop = prop_holder_get_pspec (PROP_HOLDER (item));
+  origin = g_type_name (prop->owner_type);
+
+  gtk_label_set_label (GTK_LABEL (label), origin);
+}
+
+static void
+bind_value_cb (GtkSignalListItemFactory *factory,
+               GtkListItem              *list_item,
+               gpointer                  data)
+{
+  GObject *item;
+  GtkWidget *widget;
+  GObject *object;
+  const char *name;
+
+  item = gtk_list_item_get_item (list_item);
+
+  object = prop_holder_get_object (PROP_HOLDER (item));
+  name = prop_holder_get_name (PROP_HOLDER (item));
+
+  widget = gtk_inspector_prop_editor_new (object, name, NULL);
+  g_signal_connect (widget, "show-object", G_CALLBACK (show_object), data);
+  gtk_list_item_set_child (list_item, widget);
+  gtk_style_context_add_class (gtk_widget_get_style_context (widget), "cell");
+}
+
+static void
+unbind_value_cb (GtkSignalListItemFactory *factory,
+                 GtkListItem              *list_item,
+                 gpointer                  data)
+{
+  gtk_list_item_set_child (list_item, NULL);
+}
+
 static void
 gtk_inspector_prop_list_class_init (GtkInspectorPropListClass *klass)
 {
@@ -374,16 +444,18 @@ gtk_inspector_prop_list_class_init (GtkInspectorPropListClass *klass)
                            GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/prop-list.ui");
-  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, list2);
-  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, names);
-  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, types);
-  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, values);
-  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, origins);
-  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, name_heading);
-  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, name_sort_indicator);
-  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, origin_heading);
-  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, origin_sort_indicator);
-  gtk_widget_class_bind_template_callback (widget_class, sort_changed);
+  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, list);
+  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, name);
+  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, type);
+  gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, origin);
+  gtk_widget_class_bind_template_callback (widget_class, setup_name_cb);
+  gtk_widget_class_bind_template_callback (widget_class, bind_name_cb);
+  gtk_widget_class_bind_template_callback (widget_class, setup_type_cb);
+  gtk_widget_class_bind_template_callback (widget_class, bind_type_cb);
+  gtk_widget_class_bind_template_callback (widget_class, setup_origin_cb);
+  gtk_widget_class_bind_template_callback (widget_class, bind_origin_cb);
+  gtk_widget_class_bind_template_callback (widget_class, bind_value_cb);
+  gtk_widget_class_bind_template_callback (widget_class, unbind_value_cb);
 }
 
 /* Like g_strdup_value_contents, but keeps the type name separate */
@@ -488,88 +560,6 @@ strdup_value_contents (const GValue  *value,
     }
 }
 
-static GtkWidget *
-gtk_inspector_prop_list_create_row (GtkInspectorPropList *pl,
-                                    GParamSpec           *prop)
-{
-  GValue gvalue = {0};
-  gchar *value;
-  gchar *type;
-  gchar *attribute = NULL;
-  gboolean writable;
-  GtkWidget *row;
-  GtkWidget *box;
-  GtkWidget *label;
-  GtkWidget *widget;
-
-  g_value_init (&gvalue, prop->value_type);
-  g_object_get_property (pl->priv->object, prop->name, &gvalue);
-
-  strdup_value_contents (&gvalue, &value, &type);
-
-  if (GTK_IS_CELL_RENDERER (pl->priv->object))
-    {
-      gpointer *layout;
-      GtkCellArea *area;
-      gint column = -1;
-
-      area = NULL;
-      layout = g_object_get_data (pl->priv->object, "gtk-inspector-cell-layout");
-      if (layout)
-        area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (layout));
-      if (area)
-        column = gtk_cell_area_attribute_get_column (area,
-                                                     GTK_CELL_RENDERER (pl->priv->object),
-                                                     prop->name);
-
-       if (column != -1)
-         attribute = g_strdup_printf ("%d", column);
-    }
-
-  writable = ((prop->flags & G_PARAM_WRITABLE) != 0) &&
-             ((prop->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
-
-  row = gtk_list_box_row_new ();
-  gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
-  g_object_set_data (G_OBJECT (row), "pspec", prop);
-
-  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-  gtk_container_add (GTK_CONTAINER (row), box);
-
-  label = gtk_label_new (prop->name);
-  gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
-  gtk_widget_set_sensitive (label, writable);
-  gtk_label_set_xalign (GTK_LABEL (label), 0);
-  gtk_size_group_add_widget (pl->priv->names, label);
-  gtk_container_add (GTK_CONTAINER (box), label);
-
-  label = gtk_label_new (type ? type : "");
-  gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
-  gtk_widget_set_sensitive (label, writable);
-  gtk_label_set_xalign (GTK_LABEL (label), 0);
-  gtk_size_group_add_widget (pl->priv->types, label);
-  gtk_container_add (GTK_CONTAINER (box), label);
-
-  label = gtk_label_new (g_type_name (prop->owner_type));
-  gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
-  gtk_widget_set_sensitive (label, writable);
-  gtk_label_set_xalign (GTK_LABEL (label), 0);
-  gtk_size_group_add_widget (pl->priv->origins, label);
-  gtk_container_add (GTK_CONTAINER (box), label);
-
-  widget = gtk_inspector_prop_editor_new (pl->priv->object, prop->name, pl->priv->values);
-  gtk_style_context_add_class (gtk_widget_get_style_context (widget), "cell");
-  gtk_container_add (GTK_CONTAINER (box), widget);
-  g_signal_connect (widget, "show-object", G_CALLBACK (show_object), pl);
-
-  g_free (value);
-  g_free (type);
-  g_free (attribute);
-  g_value_unset (&gvalue);
-
-  return row;
-}
-
 static void
 cleanup_object (GtkInspectorPropList *pl)
 {
@@ -588,7 +578,10 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl,
   GParamSpec **props;
   guint num_properties;
   guint i;
-  GtkWidget *w;
+  GListStore *store;
+  GListModel *list;
+  GListModel *filtered;
+  GtkSortListModel *sorted;
 
   if (!object)
     return FALSE;
@@ -605,19 +598,19 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl,
 
   pl->priv->object = object;
 
-  while ((w = gtk_widget_get_first_child (pl->priv->list2)) != NULL)
-    gtk_widget_destroy (w);
+  store = g_list_store_new (PROP_TYPE_HOLDER);
 
   for (i = 0; i < num_properties; i++)
     {
       GParamSpec *prop = props[i];
-      GtkWidget *row;
+      PropHolder *holder;
 
       if (! (prop->flags & G_PARAM_READABLE))
         continue;
 
-      row = gtk_inspector_prop_list_create_row (pl, prop);
-      gtk_container_add (GTK_CONTAINER (pl->priv->list2), row);
+      holder = prop_holder_new (object, prop);
+      g_list_store_append (store, holder);
+      g_object_unref (holder);
     }
 
   g_free (props);
@@ -625,8 +618,21 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl,
   if (GTK_IS_WIDGET (object))
     g_signal_connect_object (object, "destroy", G_CALLBACK (cleanup_object), pl, G_CONNECT_SWAPPED);
 
+  filtered = G_LIST_MODEL (gtk_filter_list_model_new (G_LIST_MODEL (store), pl->priv->filter));
+  sorted = gtk_sort_list_model_new (filtered, NULL);
+  list = G_LIST_MODEL (gtk_no_selection_new (G_LIST_MODEL (sorted)));
+
+  gtk_column_view_set_model (GTK_COLUMN_VIEW (pl->priv->list), list);
+  gtk_sort_list_model_set_sorter (sorted, gtk_column_view_get_sorter (GTK_COLUMN_VIEW (pl->priv->list)));
+  gtk_column_view_sort_by_column (GTK_COLUMN_VIEW (pl->priv->list), pl->priv->name, GTK_SORT_ASCENDING);
+
   gtk_widget_show (GTK_WIDGET (pl));
 
+  g_object_unref (list);
+  g_object_unref (sorted);
+  g_object_unref (filtered);
+  g_object_unref (store);
+
   return TRUE;
 }
 
diff --git a/gtk/inspector/prop-list.ui b/gtk/inspector/prop-list.ui
index f1898cf5b5..87cb51fc73 100644
--- a/gtk/inspector/prop-list.ui
+++ b/gtk/inspector/prop-list.ui
@@ -9,85 +9,58 @@
           <class name="view"/>
         </style>
         <child>
-          <object class="GtkBox">
-            <style>
-              <class name="header"/>
-            </style>
+          <object class="GtkScrolledWindow">
+            <property name="expand">1</property>
+            <property name="hscrollbar-policy">never</property>
             <child>
-              <object class="GtkBox" id="name_heading">
-                <property name="hexpand">0</property>
+              <object class="GtkColumnView" id="list">
+                <style>
+                  <class name="list"/>
+                </style>
                 <child>
-                  <object class="GtkGestureClick">
-                    <signal name="pressed" handler="sort_changed" swapped="no"/>
-
+                  <object class="GtkColumnViewColumn" id="name">
+                    <property name="title" translatable="yes">Name</property>
+                    <property name="factory">
+                      <object class="GtkSignalListItemFactory">
+                        <signal name="setup" handler="setup_name_cb"/>
+                        <signal name="bind" handler="bind_name_cb"/>
+                      </object>
+                    </property>
                   </object>
                 </child>
                 <child>
-                  <object class="GtkLabel">
-                    <property name="label">Name</property>
-                    <property name="xalign">0</property>
-                    <property name="hexpand">1</property>
+                  <object class="GtkColumnViewColumn" id="type">
+                    <property name="title" translatable="yes">Type</property>
+                    <property name="factory">
+                      <object class="GtkSignalListItemFactory">
+                        <signal name="setup" handler="setup_type_cb"/>
+                        <signal name="bind" handler="bind_type_cb"/>
+                      </object>
+                    </property>
                   </object>
                 </child>
                 <child>
-                  <object class="GtkImage" id="name_sort_indicator">
-                    <style>
-                      <class name="sort_indicator"/>
-                    </style>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkLabel" id="type_heading">
-                <property name="label">Type</property>
-                <property name="xalign">0</property>
-              </object>
-            </child>
-            <child>
-              <object class="GtkBox" id="origin_heading">
-                <property name="hexpand">0</property>
-                <child>
-                  <object class="GtkGestureClick">
-                    <signal name="pressed" handler="sort_changed" swapped="no"/>
-
+                  <object class="GtkColumnViewColumn" id="origin">
+                    <property name="title" translatable="yes">Defined At</property>
+                    <property name="factory">
+                      <object class="GtkSignalListItemFactory">
+                        <signal name="setup" handler="setup_origin_cb"/>
+                        <signal name="bind" handler="bind_origin_cb"/>
+                      </object>
+                    </property>
                   </object>
                 </child>
                 <child>
-                  <object class="GtkLabel">
-                    <property name="label">Defined at</property>
-                    <property name="xalign">0</property>
-                    <property name="hexpand">1</property>
+                  <object class="GtkColumnViewColumn">
+                    <property name="title" translatable="yes">Value</property>
+                    <property name="factory">
+                      <object class="GtkSignalListItemFactory">
+                        <signal name="bind" handler="bind_value_cb"/>
+                        <signal name="unbind" handler="unbind_value_cb"/>
+                      </object>
+                    </property>
                   </object>
                 </child>
-                <child>
-                  <object class="GtkImage" id="origin_sort_indicator">
-                    <style>
-                      <class name="sort_indicator"/>
-                    </style>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkLabel" id="value_heading">
-                <property name="label">Value</property>
-                <property name="xalign">0</property>
-                <property name="hexpand">0</property>
-              </object>
-            </child>
-          </object>
-        </child>
-        <child>
-          <object class="GtkScrolledWindow">
-            <property name="expand">1</property>
-            <property name="hscrollbar-policy">never</property>
-            <child>
-              <object class="GtkListBox" id="list2">
-                <style>
-                  <class name="list"/>
-                </style>
-                <property name="selection-mode">none</property>
               </object>
             </child>
           </object>
@@ -95,28 +68,4 @@
       </object>
     </child>
   </template>
-  <object class="GtkSizeGroup" id="names">
-    <property name="mode">horizontal</property>
-    <widgets>
-      <widget name="name_heading"/>
-    </widgets>
-  </object>
-  <object class="GtkSizeGroup" id="types">
-    <property name="mode">horizontal</property>
-    <widgets>
-      <widget name="type_heading"/>
-    </widgets>
-  </object>
-  <object class="GtkSizeGroup" id="origins">
-    <property name="mode">horizontal</property>
-    <widgets>
-      <widget name="origin_heading"/>
-    </widgets>
-  </object>
-  <object class="GtkSizeGroup" id="values">
-    <property name="mode">horizontal</property>
-    <widgets>
-      <widget name="value_heading"/>
-    </widgets>
-  </object>
 </interface>


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