[gtk+] inspector: Redo the CSS node page
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] inspector: Redo the CSS node page
- Date: Mon, 7 Dec 2015 04:08:21 +0000 (UTC)
commit 326f4739ca00c7a3b92990c9e747c71638935a85
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Dec 6 23:06:33 2015 -0500
inspector: Redo the CSS node page
Showing two lists in a paned was a bit awkward, and space was
getting too limited. Go back to showing just the node list at
first, and make the CSS properties available via a stack. At
the same time, add a right-click context menu to the node list
to make the name and class editing more easily available.
gtk/inspector/css-node-tree.c | 246 ++++++++++++++++++++++++++++++++++------
gtk/inspector/css-node-tree.ui | 176 +++++++++++++++++++++--------
2 files changed, 340 insertions(+), 82 deletions(-)
---
diff --git a/gtk/inspector/css-node-tree.c b/gtk/inspector/css-node-tree.c
index 5c6fc17..bd0ec29 100644
--- a/gtk/inspector/css-node-tree.c
+++ b/gtk/inspector/css-node-tree.c
@@ -41,6 +41,8 @@
#include "gtktreeview.h"
#include "gtktreeselection.h"
#include "gtktypebuiltins.h"
+#include "gtkmodelbutton.h"
+#include "gtkstack.h"
enum {
COLUMN_NODE_NAME,
@@ -63,6 +65,10 @@ enum
struct _GtkInspectorCssNodeTreePrivate
{
GtkWidget *node_tree;
+ GtkWidget *stack;
+ GtkWidget *node_list_button;
+ GtkWidget *prop_list_button;
+ GtkWidget *css_node_info;
GtkTreeModel *node_model;
GtkTreeViewColumn *node_name_column;
GtkTreeViewColumn *node_id_column;
@@ -77,6 +83,35 @@ struct _GtkInspectorCssNodeTreePrivate
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorCssNodeTree, gtk_inspector_css_node_tree, GTK_TYPE_BOX)
+typedef struct {
+ GtkCssNode *node;
+ const gchar *prop_name;
+ GdkRectangle rect;
+ GtkInspectorCssNodeTree *cnt;
+} NodePropEditor;
+
+static void
+show_node_prop_editor (NodePropEditor *npe)
+{
+ GtkWidget *popover;
+ GtkWidget *editor;
+
+ popover = gtk_popover_new (GTK_WIDGET (npe->cnt->priv->node_tree));
+ gtk_popover_set_pointing_to (GTK_POPOVER (popover), &npe->rect);
+
+ editor = gtk_inspector_prop_editor_new (G_OBJECT (npe->node), npe->prop_name, FALSE);
+ gtk_widget_show (editor);
+
+ gtk_container_add (GTK_CONTAINER (popover), editor);
+
+ if (gtk_inspector_prop_editor_should_expand (GTK_INSPECTOR_PROP_EDITOR (editor)))
+ gtk_widget_set_vexpand (popover, TRUE);
+
+ gtk_widget_show (popover);
+
+ g_signal_connect (popover, "unmap", G_CALLBACK (gtk_widget_destroy), NULL);
+}
+
static void
row_activated (GtkTreeView *tv,
GtkTreePath *path,
@@ -84,48 +119,162 @@ row_activated (GtkTreeView *tv,
GtkInspectorCssNodeTree *cnt)
{
GtkTreeIter iter;
- GdkRectangle rect;
- GtkWidget *editor;
- GtkWidget *popover;
- GtkCssNode *node;
- const gchar *prop_name;
+ NodePropEditor npe;
+
+ npe.cnt = cnt;
if (col == cnt->priv->node_name_column)
- prop_name = "name";
+ npe.prop_name = "name";
else if (col == cnt->priv->node_id_column)
- prop_name = "id";
+ npe.prop_name = "id";
else if (col == cnt->priv->node_classes_column)
- prop_name = "classes";
+ npe.prop_name = "classes";
else
return;
gtk_tree_model_get_iter (cnt->priv->node_model, &iter, path);
+ npe.node = gtk_tree_model_css_node_get_node_from_iter (GTK_TREE_MODEL_CSS_NODE (cnt->priv->node_model),
&iter);
+ gtk_tree_view_get_cell_area (tv, path, col, &npe.rect);
+ gtk_tree_view_convert_bin_window_to_widget_coords (tv, npe.rect.x, npe.rect.y, &npe.rect.x, &npe.rect.y);
+
+ show_node_prop_editor (&npe);
+}
+
+static void
+switch_to_node_list (GtkInspectorCssNodeTree *cnt)
+{
+ gtk_stack_set_visible_child_name (GTK_STACK (cnt->priv->stack), "node-list");
+ gtk_widget_show (cnt->priv->prop_list_button);
+ gtk_widget_hide (cnt->priv->node_list_button);
+}
+
+static void
+switch_to_prop_list (GtkInspectorCssNodeTree *cnt)
+{
+ gtk_stack_set_visible_child_name (GTK_STACK (cnt->priv->stack), "prop-list");
+ gtk_widget_show (cnt->priv->node_list_button);
+ gtk_widget_hide (cnt->priv->prop_list_button);
+}
+
+static void
+show_node_popover (GtkInspectorCssNodeTree *cnt,
+ gdouble x,
+ gdouble y)
+{
+ GtkTreeSelection *selection;
+ GdkRectangle rect;
+ GtkWidget *popover;
+ GtkWidget *box;
+ GtkWidget *button;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ NodePropEditor *npe;
+ GtkCssNode *node;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (cnt->priv->node_tree));
+ if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
+ return;
+
+ path = gtk_tree_model_get_path (cnt->priv->node_model, &iter);
+ gtk_tree_view_get_cell_area (GTK_TREE_VIEW (cnt->priv->node_tree), path, NULL, &rect);
+ gtk_tree_view_convert_bin_window_to_widget_coords (GTK_TREE_VIEW (cnt->priv->node_tree),
+ rect.x, rect.y, &rect.x, &rect.y);
+
+ rect.x = CLAMP (x - 20, 0, gtk_widget_get_allocated_width (cnt->priv->node_tree) - 40);
+ rect.width = 40;
+
node = gtk_tree_model_css_node_get_node_from_iter (GTK_TREE_MODEL_CSS_NODE (cnt->priv->node_model), &iter);
- gtk_tree_view_get_cell_area (tv, path, col, &rect);
- gtk_tree_view_convert_bin_window_to_widget_coords (tv, rect.x, rect.y, &rect.x, &rect.y);
- popover = gtk_popover_new (GTK_WIDGET (tv));
- gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rect);
+ npe = g_new0 (NodePropEditor, 1);
+ npe->node = node;
+ npe->prop_name = "name";
+ npe->rect = rect;
+ npe->cnt = cnt;
- editor = gtk_inspector_prop_editor_new (G_OBJECT (node), prop_name, FALSE);
- gtk_widget_show (editor);
+ popover = gtk_popover_new (GTK_WIDGET (cnt->priv->node_tree));
- gtk_container_add (GTK_CONTAINER (popover), editor);
+ gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rect);
+ box = g_object_new (GTK_TYPE_BOX,
+ "orientation", GTK_ORIENTATION_VERTICAL,
+ "visible", TRUE,
+ "margin", 10,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (popover), box);
+ button = g_object_new (GTK_TYPE_MODEL_BUTTON,
+ "visible", TRUE,
+ "text", _("Change name"),
+ NULL);
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (show_node_prop_editor), npe);
+ g_object_set_data_full (G_OBJECT (popover), "prop-name", npe, g_free);
+
+ gtk_container_add (GTK_CONTAINER (box), button);
+
+ npe = g_new0 (NodePropEditor, 1);
+ npe->node = node;
+ npe->prop_name = "classes";
+ npe->rect = rect;
+ npe->cnt = cnt;
+
+ button = g_object_new (GTK_TYPE_MODEL_BUTTON,
+ "visible", TRUE,
+ "text", _("Change classes"),
+ NULL);
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (show_node_prop_editor), npe);
+ g_object_set_data_full (G_OBJECT (popover), "prop-classes", npe, g_free);
+
+ gtk_container_add (GTK_CONTAINER (box), button);
+
+ button = g_object_new (GTK_TYPE_MODEL_BUTTON,
+ "visible", TRUE,
+ "text", _("CSS properties"),
+ NULL);
+ g_signal_connect_swapped (button, "clicked", G_CALLBACK (switch_to_prop_list), cnt);
+ gtk_container_add (GTK_CONTAINER (box), button);
- if (gtk_inspector_prop_editor_should_expand (GTK_INSPECTOR_PROP_EDITOR (editor)))
- gtk_widget_set_vexpand (popover, TRUE);
+ gtk_tree_path_free (path);
gtk_widget_show (popover);
g_signal_connect (popover, "unmap", G_CALLBACK (gtk_widget_destroy), NULL);
}
-static void populate_properties (GtkInspectorCssNodeTree *cnt);
+static gboolean
+button_pressed (GtkWidget *widget,
+ GdkEventButton *event,
+ GtkInspectorCssNodeTree *cnt)
+{
+ static gboolean in_press = FALSE;
+
+ if (in_press)
+ return FALSE;
+
+ if (!gdk_event_triggers_context_menu ((GdkEvent *)event))
+ return FALSE;
+
+ in_press = TRUE;
+ gtk_widget_event (cnt->priv->node_tree, (GdkEvent *) event);
+ in_press = FALSE;
+
+ show_node_popover (cnt, event->x, event->y);
+
+ return TRUE;
+}
+
+static void
+gtk_inspector_css_node_tree_set_node (GtkInspectorCssNodeTree *cnt,
+ GtkCssNode *node);
static void
selection_changed (GtkTreeSelection *selection, GtkInspectorCssNodeTree *cnt)
{
- populate_properties (cnt);
+ GtkTreeIter iter;
+ GtkCssNode *node;
+
+ if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
+ return;
+
+ node = gtk_tree_model_css_node_get_node_from_iter (GTK_TREE_MODEL_CSS_NODE (cnt->priv->node_model), &iter);
+ gtk_inspector_css_node_tree_set_node (cnt, node);
}
static void
@@ -189,9 +338,16 @@ gtk_inspector_css_node_tree_class_init (GtkInspectorCssNodeTreeClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorCssNodeTree, prop_name_column);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorCssNodeTree, prop_model);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorCssNodeTree, prop_name_column);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorCssNodeTree, stack);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorCssNodeTree, prop_list_button);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorCssNodeTree, node_list_button);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorCssNodeTree, css_node_info);
gtk_widget_class_bind_template_callback (widget_class, row_activated);
gtk_widget_class_bind_template_callback (widget_class, selection_changed);
+ gtk_widget_class_bind_template_callback (widget_class, button_pressed);
+ gtk_widget_class_bind_template_callback (widget_class, switch_to_node_list);
+ gtk_widget_class_bind_template_callback (widget_class, switch_to_prop_list);
}
static int
@@ -351,10 +507,14 @@ gtk_inspector_css_node_tree_set_object (GtkInspectorCssNodeTree *cnt,
if (!GTK_IS_WIDGET (object))
{
- gtk_tree_model_css_node_set_root_node (GTK_TREE_MODEL_CSS_NODE (priv->node_model), NULL);
+ gtk_widget_hide (GTK_WIDGET (cnt));
return;
}
+ gtk_widget_show (GTK_WIDGET (cnt));
+
+ switch_to_node_list (cnt);
+
root = node = gtk_widget_get_css_node (GTK_WIDGET (object));
while (gtk_css_node_get_parent (root))
root = gtk_css_node_get_parent (root);
@@ -426,6 +586,11 @@ gtk_inspector_css_node_tree_set_node (GtkInspectorCssNodeTree *cnt,
GtkCssNode *node)
{
GtkInspectorCssNodeTreePrivate *priv = cnt->priv;
+ GString *s;
+ GType type;
+ const gchar *name;
+ gchar **strv;
+ gint i;
if (priv->node == node)
return;
@@ -443,22 +608,37 @@ gtk_inspector_css_node_tree_set_node (GtkInspectorCssNodeTree *cnt,
priv->node = node;
g_signal_connect (node, "style-changed", G_CALLBACK (gtk_inspector_css_node_tree_update_style), cnt);
-}
-static void
-populate_properties (GtkInspectorCssNodeTree *cnt)
-{
- GtkInspectorCssNodeTreePrivate *priv = cnt->priv;
- GtkTreeSelection *selection;
- GtkTreeIter titer;
- GtkCssNode *node;
+ s = g_string_new ("");
+ type = gtk_css_node_get_widget_type (node);
+ if (type != G_TYPE_NONE && type != G_TYPE_INVALID)
+ g_string_append (s, g_type_name (type));
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->node_tree));
- if (!gtk_tree_selection_get_selected (selection, NULL, &titer))
- return;
+ name = gtk_css_node_get_name (node);
+ if (name)
+ {
+ if (s->len > 0)
+ g_string_append (s, " — ");
+ g_string_append (s, name);
+ }
- node = gtk_tree_model_css_node_get_node_from_iter (GTK_TREE_MODEL_CSS_NODE (priv->node_model), &titer);
- gtk_inspector_css_node_tree_set_node (cnt, node);
+ strv = gtk_css_node_get_classes (node);
+ if (strv[0] != NULL)
+ {
+ strv_sort (strv);
+ if (s->len > 0)
+ g_string_append (s, " — ");
+ for (i = 0; strv[i]; i++)
+ {
+ if (i > 0)
+ g_string_append (s, " ");
+ g_string_append (s, strv[i]);
+ }
+ g_strfreev (strv);
+ }
+
+ gtk_label_set_label (GTK_LABEL (cnt->priv->css_node_info), s->str);
+ g_string_free (s, TRUE);
}
// vim: set et sw=2 ts=2:
diff --git a/gtk/inspector/css-node-tree.ui b/gtk/inspector/css-node-tree.ui
index 09b40aa..f34a3ac 100644
--- a/gtk/inspector/css-node-tree.ui
+++ b/gtk/inspector/css-node-tree.ui
@@ -12,17 +12,65 @@
<template class="GtkInspectorCssNodeTree" parent="GtkBox">
<property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="object_title">
+ <object class="GtkBox">
<property name="visible">1</property>
- <property name="valign">center</property>
- <property name="margin-top">12</property>
- <property name="margin-bottom">12</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <child type="center">
+ <object class="GtkLabel" id="object_title">
+ <property name="visible">1</property>
+ <property name="valign">center</property>
+ <property name="margin">12</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="node_list_button">
+ <property name="valign">center</property>
+ <property name="no-show-all">1</property>
+ <property name="relief">none</property>
+ <property name="tooltip-text" translatable="yes">Show all CSS nodes</property>
+ <signal name="clicked" handler="switch_to_node_list" swapped="1"/>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">1</property>
+ <property name="icon-name">pan-start-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ <style>
+ <class name="image-button"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="prop_list_button">
+ <property name="visible">1</property>
+ <property name="valign">center</property>
+ <property name="no-show-all">1</property>
+ <property name="relief">none</property>
+ <property name="tooltip-text" translatable="yes">Show CSS properties</property>
+ <signal name="clicked" handler="switch_to_prop_list" swapped="1"/>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">1</property>
+ <property name="icon-name">pan-end-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ <style>
+ <class name="image-button"/>
+ </style>
+ </object>
+ <packing>
+ <property name="pack-type">end</property>
+ </packing>
+ </child>
</object>
</child>
<child>
- <object class="GtkPaned">
+ <object class="GtkStack" id="stack">
<property name="visible">1</property>
- <property name="orientation">vertical</property>
+ <property name="transition-type">slide-left-right</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">1</property>
@@ -34,9 +82,9 @@
<property name="search-column">0</property>
<property name="enable-search">0</property>
<signal name="row-activated" handler="row_activated"/>
+ <signal name="button-press-event" handler="button_pressed"/>
<child internal-child="selection">
<object class="GtkTreeSelection">
- <property name="mode">single</property>
<signal name="changed" handler="selection_changed"/>
</object>
</child>
@@ -108,68 +156,98 @@
</object>
</child>
</object>
+ <packing>
+ <property name="name">node-list</property>
+ </packing>
</child>
<child>
- <object class="GtkScrolledWindow">
+ <object class="GtkBox">
<property name="visible">1</property>
- <property name="expand">1</property>
- <property name="min-content-height">100</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkTreeView" id="prop_tree">
+ <object class="GtkBox">
<property name="visible">1</property>
- <property name="model">prop_model</property>
- <property name="search-column">0</property>
- <property name="enable-search">0</property>
+ <property name="orientation">horizontal</property>
+ <property name="margin">12</property>
<child>
- <object class="GtkTreeViewColumn" id="prop_name_column">
- <property name="title" translatable="yes">Property</property>
- <property name="resizable">1</property>
- <property name="sort-column-id">0</property>
- <child>
- <object class="GtkCellRendererText">
- <property name="scale">0.8</property>
- </object>
- <attributes>
- <attribute name="text">0</attribute>
- </attributes>
- </child>
+ <object class="GtkLabel">
+ <property name="visible">1</property>
+ <property name="label" translatable="yes">Node:</property>
</object>
</child>
+ <child type="center">
+ <object class="GtkLabel" id="css_node_info">
+ <property name="visible">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">1</property>
+ <property name="expand">1</property>
+ <property name="min-content-height">100</property>
<child>
- <object class="GtkTreeViewColumn">
- <property name="title" translatable="yes">Value</property>
- <property name="resizable">1</property>
+ <object class="GtkTreeView" id="prop_tree">
+ <property name="visible">1</property>
+ <property name="model">prop_model</property>
+ <property name="search-column">0</property>
+ <property name="enable-search">0</property>
<child>
- <object class="GtkCellRendererText">
- <property name="scale">0.8</property>
- <property name="width-chars">20</property>
- <property name="ellipsize">end</property>
+ <object class="GtkTreeViewColumn" id="prop_name_column">
+ <property name="title" translatable="yes">CSS Property</property>
+ <property name="resizable">1</property>
+ <property name="sort-column-id">0</property>
+ <child>
+ <object class="GtkCellRendererText">
+ <property name="scale">0.8</property>
+ </object>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
</object>
- <attributes>
- <attribute name="text">1</attribute>
- </attributes>
</child>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn">
- <property name="title" translatable="yes">Location</property>
- <property name="resizable">1</property>
<child>
- <object class="GtkCellRendererText">
- <property name="scale">0.8</property>
- <property name="width-chars">20</property>
- <property name="ellipsize">end</property>
+ <object class="GtkTreeViewColumn">
+ <property name="title" translatable="yes">Value</property>
+ <property name="resizable">1</property>
+ <child>
+ <object class="GtkCellRendererText">
+ <property name="scale">0.8</property>
+ <property name="width-chars">20</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn">
+ <property name="title" translatable="yes">Location</property>
+ <property name="resizable">1</property>
+ <child>
+ <object class="GtkCellRendererText">
+ <property name="scale">0.8</property>
+ <property name="width-chars">20</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <attributes>
+ <attribute name="text">2</attribute>
+ </attributes>
+ </child>
</object>
- <attributes>
- <attribute name="text">2</attribute>
- </attributes>
</child>
</object>
</child>
</object>
</child>
</object>
+ <packing>
+ <property name="name">prop-list</property>
+ </packing>
</child>
</object>
</child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]