diff options
author | Benjamin Otte <otte@redhat.com> | 2015-03-03 00:02:25 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2015-03-18 15:23:33 +0100 |
commit | d55c261079370e3ddd61f3dab6bea9067380480e (patch) | |
tree | d2be530faa70e96dab84f0e59449dec42164d93e /gtk | |
parent | 8640bc47b1e7208bc5e3b7a77ef5cf321c74db88 (diff) | |
download | gtk+-d55c261079370e3ddd61f3dab6bea9067380480e.tar.gz |
inspector: Add a new page that lists the CSS node tree
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/Makefile.am | 2 | ||||
-rw-r--r-- | gtk/inspector/Makefile.inc | 5 | ||||
-rw-r--r-- | gtk/inspector/css-node-tree.c | 168 | ||||
-rw-r--r-- | gtk/inspector/css-node-tree.h | 61 | ||||
-rw-r--r-- | gtk/inspector/css-node-tree.ui | 58 | ||||
-rw-r--r-- | gtk/inspector/gtktreemodelcssnode.c | 626 | ||||
-rw-r--r-- | gtk/inspector/gtktreemodelcssnode.h | 80 | ||||
-rw-r--r-- | gtk/inspector/init.c | 2 | ||||
-rw-r--r-- | gtk/inspector/window.c | 3 | ||||
-rw-r--r-- | gtk/inspector/window.h | 1 | ||||
-rw-r--r-- | gtk/inspector/window.ui | 9 | ||||
-rw-r--r-- | gtk/inspector/window.ui.h | 1 |
12 files changed, 1015 insertions, 1 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 1af8ecb677..c59f63e8c1 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -1130,7 +1130,7 @@ gtktypebuiltins.c: $(gtk_public_h_sources) $(a11y_h_sources) $(deprecated_h_sour && cp xgen-gtbc gtktypebuiltins.c \ && rm -f xgen-gtbc -gtk.gresource.xml: Makefile.am +gtk.gresource.xml: Makefile.am inspector/Makefile.inc $(AM_V_GEN) echo "<?xml version='1.0' encoding='UTF-8'?>" > $@; \ echo "<gresources>" >> $@; \ echo " <gresource prefix='/org/gtk/libgtk'>" >> $@; \ diff --git a/gtk/inspector/Makefile.inc b/gtk/inspector/Makefile.inc index 464e809497..92fb1b9743 100644 --- a/gtk/inspector/Makefile.inc +++ b/gtk/inspector/Makefile.inc @@ -4,10 +4,12 @@ inspector_c_sources = \ inspector/cellrenderergraph.c \ inspector/classes-list.c \ inspector/css-editor.c \ + inspector/css-node-tree.c \ inspector/data-list.c \ inspector/general.c \ inspector/gestures.c \ inspector/graphdata.c \ + inspector/gtktreemodelcssnode.c \ inspector/init.c \ inspector/inspect-button.c \ inspector/magnifier.c \ @@ -33,10 +35,12 @@ inspector_h_sources = \ inspector/cellrenderergraph.h \ inspector/classes-list.h \ inspector/css-editor.h \ + inspector/css-node-tree.h \ inspector/data-list.h \ inspector/general.h \ inspector/gestures.h \ inspector/graphdata.h \ + inspector/gtktreemodelcssnode.h \ inspector/init.h \ inspector/magnifier.h \ inspector/menu.h \ @@ -59,6 +63,7 @@ inspector_templates = \ inspector/actions.ui \ inspector/classes-list.ui \ inspector/css-editor.ui \ + inspector/css-node-tree.ui \ inspector/data-list.ui \ inspector/general.ui \ inspector/magnifier.ui \ diff --git a/gtk/inspector/css-node-tree.c b/gtk/inspector/css-node-tree.c new file mode 100644 index 0000000000..ca48f2b729 --- /dev/null +++ b/gtk/inspector/css-node-tree.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2014 Benjamin Otte <otte@gnome.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicntnse, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright noticnt and this permission noticnt shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "config.h" +#include <glib/gi18n-lib.h> + +#include "css-node-tree.h" + +#include <strings.h> + +#include "gtktreemodelcssnode.h" +#include <gtk/gtktreeview.h> +#include "gtk/gtkwidgetprivate.h" + +enum { + COLUMN_NAME, + COLUMN_VISIBLE, + COLUMN_CLASSES, + COLUMN_ID, + /* add more */ + N_COLUMNS +}; + +struct _GtkInspectorCssNodeTreePrivate +{ + GtkWidget *tree_view; + GtkTreeModel *model; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorCssNodeTree, gtk_inspector_css_node_tree, GTK_TYPE_BOX) + +static void +gtk_inspector_css_node_tree_finalize (GObject *object) +{ + //GtkInspectorCssNodeTree *cnt = GTK_INSPECTOR_CSS_NODE_TREE (object); + + G_OBJECT_CLASS (gtk_inspector_css_node_tree_parent_class)->finalize (object); +} + +static void +gtk_inspector_css_node_tree_class_init (GtkInspectorCssNodeTreeClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->finalize = gtk_inspector_css_node_tree_finalize; + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/css-node-tree.ui"); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorCssNodeTree, tree_view); +} + +static int +sort_strv (gconstpointer a, + gconstpointer b, + gpointer data) +{ + char **ap = (char **) a; + char **bp = (char **) b; + + return strcasecmp (*ap, *bp); +} + +static void +strv_sort (char **strv) +{ + g_qsort_with_data (strv, + g_strv_length (strv), + sizeof (char *), + sort_strv, + NULL); +} + +static void +gtk_inspector_css_node_tree_get_node_value (GtkTreeModelCssNode *model, + GtkCssNode *node, + int column, + GValue *value) +{ + char **strv; + char *s; + + switch (column) + { + case COLUMN_NAME: + g_value_set_string (value, g_type_name (gtk_css_node_get_widget_type (node))); + break; + + case COLUMN_VISIBLE: + g_value_set_boolean (value, gtk_css_node_get_visible (node)); + break; + + case COLUMN_CLASSES: + strv = gtk_css_node_get_classes (node); + strv_sort (strv); + s = g_strjoinv (" ", strv); + g_value_take_string (value, s); + g_strfreev (strv); + break; + + case COLUMN_ID: + g_value_set_string (value, gtk_css_node_get_id (node)); + break; + + default: + g_assert_not_reached (); + break; + } +} + +static void +gtk_inspector_css_node_tree_init (GtkInspectorCssNodeTree *cnt) +{ + GtkInspectorCssNodeTreePrivate *priv; + + cnt->priv = gtk_inspector_css_node_tree_get_instance_private (cnt); + gtk_widget_init_template (GTK_WIDGET (cnt)); + priv = cnt->priv; + + priv->model = gtk_tree_model_css_node_new (gtk_inspector_css_node_tree_get_node_value, + N_COLUMNS, + G_TYPE_STRING, + G_TYPE_BOOLEAN, + G_TYPE_STRING, + G_TYPE_STRING); + gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), priv->model); + g_object_unref (priv->model); +} + +void +gtk_inspector_css_node_tree_set_object (GtkInspectorCssNodeTree *cnt, + GObject *object) +{ + GtkInspectorCssNodeTreePrivate *priv; + + g_return_if_fail (GTK_INSPECTOR_IS_CSS_NODE_TREE (cnt)); + + priv = cnt->priv; + + if (!GTK_IS_WIDGET (object)) + { + gtk_tree_model_css_node_set_root_node (GTK_TREE_MODEL_CSS_NODE (priv->model), NULL); + return; + } + + gtk_tree_model_css_node_set_root_node (GTK_TREE_MODEL_CSS_NODE (priv->model), + gtk_widget_get_css_node (GTK_WIDGET (object))); +} + +// vim: set et sw=2 ts=2: diff --git a/gtk/inspector/css-node-tree.h b/gtk/inspector/css-node-tree.h new file mode 100644 index 0000000000..8de2c8e6b8 --- /dev/null +++ b/gtk/inspector/css-node-tree.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014 Benjamin Otte <otte@gnome.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _GTK_INSPECTOR_CSS_NODE_TREE_H_ +#define _GTK_INSPECTOR_CSS_NODE_TREE_H_ + +#include <gtk/gtkbox.h> + +#include "gtk/gtkcssnodeprivate.h" + +#define GTK_TYPE_INSPECTOR_CSS_NODE_TREE (gtk_inspector_css_node_tree_get_type()) +#define GTK_INSPECTOR_CSS_NODE_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_INSPECTOR_CSS_NODE_TREE, GtkInspectorCssNodeTree)) +#define GTK_INSPECTOR_CSS_NODE_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_INSPECTOR_CSS_NODE_TREE, GtkInspectorCssNodeTreeClass)) +#define GTK_INSPECTOR_IS_CSS_NODE_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_INSPECTOR_CSS_NODE_TREE)) +#define GTK_INSPECTOR_IS_CSS_NODE_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_INSPECTOR_CSS_NODE_TREE)) +#define GTK_INSPECTOR_CSS_NODE_TREE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_INSPECTOR_CSS_NODE_TREE, GtkInspectorCssNodeTreeClass)) + + +typedef struct _GtkInspectorCssNodeTreePrivate GtkInspectorCssNodeTreePrivate; + +typedef struct _GtkInspectorCssNodeTree +{ + GtkBox parent; + GtkInspectorCssNodeTreePrivate *priv; +} GtkInspectorCssNodeTree; + +typedef struct _GtkInspectorCssNodeTreeClass +{ + GtkBoxClass parent; +} GtkInspectorCssNodeTreeClass; + +G_BEGIN_DECLS + +GType gtk_inspector_css_node_tree_get_type (void); +void gtk_inspector_css_node_tree_set_object (GtkInspectorCssNodeTree *cnt, + GObject *object); + +G_END_DECLS + +#endif // _GTK_INSPECTOR_CSS_NODE_TREE_H_ + +// vim: set et sw=2 ts=2: diff --git a/gtk/inspector/css-node-tree.ui b/gtk/inspector/css-node-tree.ui new file mode 100644 index 0000000000..f2cbab0d91 --- /dev/null +++ b/gtk/inspector/css-node-tree.ui @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface domain="gtk30"> + <template class="GtkInspectorCssNodeTree" parent="GtkBox"> + <property name="orientation">vertical</property> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="hscrollbar-policy">never</property> + <property name="vscrollbar-policy">automatic</property> + <property name="expand">True</property> + <child> + <object class="GtkTreeView" id="tree_view"> + <property name="visible">True</property> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn1"> + <property name="resizable">True</property> + <property name="title" translatable="yes">Name</property> + <child> + <object class="GtkCellRendererText"/> + <attributes> + <attribute name="text">0</attribute> + <attribute name="sensitive">1</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn2"> + <property name="resizable">True</property> + <property name="title" translatable="yes">ID</property> + <child> + <object class="GtkCellRendererText"/> + <attributes> + <attribute name="text">3</attribute> + <attribute name="sensitive">1</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn3"> + <property name="resizable">True</property> + <property name="title" translatable="yes">Classes</property> + <child> + <object class="GtkCellRendererText"/> + <attributes> + <attribute name="text">2</attribute> + <attribute name="sensitive">1</attribute> + </attributes> + </child> + </object> + </child> + </object> + </child> + </object> + </child> + </template> +</interface> diff --git a/gtk/inspector/gtktreemodelcssnode.c b/gtk/inspector/gtktreemodelcssnode.c new file mode 100644 index 0000000000..196335e3da --- /dev/null +++ b/gtk/inspector/gtktreemodelcssnode.c @@ -0,0 +1,626 @@ +/* gtktreestore.c + * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include "gtktreemodelcssnode.h" + +struct _GtkTreeModelCssNodePrivate +{ + GtkTreeModelCssNodeGetFunc get_func; + gint n_columns; + GType *column_types; + + GtkCssNode *root; +}; + +static void gtk_tree_model_css_node_connect_node (GtkTreeModelCssNode *model, + GtkCssNode *node, + gboolean emit_signal); + +static void gtk_tree_model_css_node_disconnect_node (GtkTreeModelCssNode *model, + GtkCssNode *node, + gboolean emit_signal, + GtkCssNode *parent, + GtkCssNode *previous); + +static void gtk_tree_model_css_node_tree_model_init (GtkTreeModelIface *iface); + +G_DEFINE_TYPE_WITH_CODE (GtkTreeModelCssNode, gtk_tree_model_css_node, G_TYPE_OBJECT, + G_ADD_PRIVATE (GtkTreeModelCssNode) + G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, + gtk_tree_model_css_node_tree_model_init)) + +static GtkCssNode * +get_nth_child (GtkCssNode *node, + gint i) +{ + for (node = gtk_css_node_get_first_child (node); + node != NULL && i > 0; + node = gtk_css_node_get_next_sibling (node)) + i--; + + return node; +} + +static int +get_node_index (GtkCssNode *node) +{ + int result = 0; + + while ((node = gtk_css_node_get_previous_sibling (node))) + result++; + + return result; +} + +static GtkTreeModelFlags +gtk_tree_model_css_node_get_flags (GtkTreeModel *tree_model) +{ + return GTK_TREE_MODEL_ITERS_PERSIST; +} + +static gint +gtk_tree_model_css_node_get_n_columns (GtkTreeModel *tree_model) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + + return priv->n_columns; +} + +static GType +gtk_tree_model_css_node_get_column_type (GtkTreeModel *tree_model, + gint column) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + + g_return_val_if_fail (column < priv->n_columns, G_TYPE_INVALID); + + return priv->column_types[column]; +} + +static gboolean +gtk_tree_model_css_node_get_iter (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreePath *path) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + GtkCssNode *node; + int *indices; + int depth, i; + + if (priv->root == NULL) + return FALSE; + + indices = gtk_tree_path_get_indices (path); + depth = gtk_tree_path_get_depth (path); + + if (depth < 1 || indices[0] != 0) + return FALSE; + + node = priv->root; + for (i = 1; i < depth; i++) + { + node = get_nth_child (node, indices[i]); + if (node == NULL) + return FALSE; + } + + gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node); + return TRUE; +} + +static GtkTreePath * +gtk_tree_model_css_node_get_path (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + GtkCssNode *node; + GtkTreePath *path; + + g_return_val_if_fail (priv->root != NULL, NULL); + + path = gtk_tree_path_new (); + node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter); + + while (node != priv->root) + { + gtk_tree_path_prepend_index (path, get_node_index (node)); + node = gtk_css_node_get_parent (node); + } + + gtk_tree_path_prepend_index (path, 0); + + return path; +} + +static void +gtk_tree_model_css_node_get_value (GtkTreeModel *tree_model, + GtkTreeIter *iter, + gint column, + GValue *value) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + + g_value_init (value, priv->column_types[column]); + priv->get_func (nodemodel, + gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter), + column, + value); +} + +static gboolean +gtk_tree_model_css_node_iter_next (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + GtkCssNode *node; + + node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter); + if (node == priv->root) + return FALSE; + + node = gtk_css_node_get_next_sibling (node); + if (node == NULL) + return FALSE; + + gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node); + return TRUE; +} + +static gboolean +gtk_tree_model_css_node_iter_previous (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + GtkCssNode *node; + + node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter); + if (node == priv->root) + return FALSE; + + node = gtk_css_node_get_previous_sibling (node); + if (node == NULL) + return FALSE; + + gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node); + return TRUE; +} + +static gboolean +gtk_tree_model_css_node_iter_children (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + GtkCssNode *node; + + if (parent == NULL) + { + node = priv->root; + } + else + { + node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, parent); + node = gtk_css_node_get_first_child (node); + } + if (node == NULL) + return FALSE; + + gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node); + return TRUE; +} + +static gboolean +gtk_tree_model_css_node_iter_has_child (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkCssNode *node; + + node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter); + + return gtk_css_node_get_first_child (node) != NULL; +} + +static gint +gtk_tree_model_css_node_iter_n_children (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + GtkCssNode *node; + + if (iter == NULL) + return priv->root ? 1 : 0; + + node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, iter); + + node = gtk_css_node_get_last_child (node); + if (node == NULL) + return 0; + + return get_node_index (node) + 1; +} + +static gboolean +gtk_tree_model_css_node_iter_nth_child (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent, + gint n) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + GtkCssNode *node; + + if (parent == NULL) + { + if (n > 0) + return FALSE; + + node = priv->root; + } + else + { + node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, parent); + node = get_nth_child (node, n); + } + + if (node == NULL) + return FALSE; + + gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node); + return TRUE; +} + +static gboolean +gtk_tree_model_css_node_iter_parent (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *child) +{ + GtkTreeModelCssNode *nodemodel = GTK_TREE_MODEL_CSS_NODE (tree_model); + GtkTreeModelCssNodePrivate *priv = nodemodel->priv; + GtkCssNode *node; + + node = gtk_tree_model_css_node_get_node_from_iter (nodemodel, child); + if (node == priv->root) + return FALSE; + + node = gtk_css_node_get_parent (node); + + gtk_tree_model_css_node_get_iter_from_node (nodemodel, iter, node); + return TRUE; +} + +static void +gtk_tree_model_css_node_tree_model_init (GtkTreeModelIface *iface) +{ + iface->get_flags = gtk_tree_model_css_node_get_flags; + iface->get_n_columns = gtk_tree_model_css_node_get_n_columns; + iface->get_column_type = gtk_tree_model_css_node_get_column_type; + iface->get_iter = gtk_tree_model_css_node_get_iter; + iface->get_path = gtk_tree_model_css_node_get_path; + iface->get_value = gtk_tree_model_css_node_get_value; + iface->iter_next = gtk_tree_model_css_node_iter_next; + iface->iter_previous = gtk_tree_model_css_node_iter_previous; + iface->iter_children = gtk_tree_model_css_node_iter_children; + iface->iter_has_child = gtk_tree_model_css_node_iter_has_child; + iface->iter_n_children = gtk_tree_model_css_node_iter_n_children; + iface->iter_nth_child = gtk_tree_model_css_node_iter_nth_child; + iface->iter_parent = gtk_tree_model_css_node_iter_parent; +} + +static void +gtk_tree_model_css_node_finalize (GObject *object) +{ + GtkTreeModelCssNode *model = GTK_TREE_MODEL_CSS_NODE (object); + GtkTreeModelCssNodePrivate *priv = model->priv; + + if (priv->root) + { + gtk_tree_model_css_node_disconnect_node (model, priv->root, FALSE, NULL, NULL); + priv->root = NULL; + } + + G_OBJECT_CLASS (gtk_tree_model_css_node_parent_class)->finalize (object); +} + +static void +gtk_tree_model_css_node_class_init (GtkTreeModelCssNodeClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = gtk_tree_model_css_node_finalize; +} + +static void +gtk_tree_model_css_node_init (GtkTreeModelCssNode *nodemodel) +{ + nodemodel->priv = gtk_tree_model_css_node_get_instance_private (nodemodel); +} + +GtkTreeModel * +gtk_tree_model_css_node_new (GtkTreeModelCssNodeGetFunc get_func, + gint n_columns, + ...) +{ + GtkTreeModel *result; + va_list args; + GType *types; + gint i; + + g_return_val_if_fail (get_func != NULL, NULL); + g_return_val_if_fail (n_columns > 0, NULL); + + types = g_new (GType, n_columns); + va_start (args, n_columns); + + for (i = 0; i < n_columns; i++) + { + types[i] = va_arg (args, GType); + } + + va_end (args); + + result = gtk_tree_model_css_node_newv (get_func, n_columns, types); + + g_free (types); + + return result; +} + +GtkTreeModel * +gtk_tree_model_css_node_newv (GtkTreeModelCssNodeGetFunc get_func, + gint n_columns, + GType *types) +{ + GtkTreeModelCssNode *result; + GtkTreeModelCssNodePrivate *priv; + + g_return_val_if_fail (get_func != NULL, NULL); + g_return_val_if_fail (n_columns > 0, NULL); + g_return_val_if_fail (types != NULL, NULL); + + result = g_object_new (GTK_TYPE_TREE_MODEL_CSS_NODE, NULL); + priv = result->priv; + + priv->get_func = get_func; + priv->n_columns = n_columns; + priv->column_types = g_memdup (types, sizeof (GType) * n_columns); + + return GTK_TREE_MODEL (result); +} + +static void +child_added_cb (GtkCssNode *node, + GtkCssNode *child, + GtkCssNode *previous, + GtkTreeModelCssNode *model) +{ + gtk_tree_model_css_node_connect_node (model, child, TRUE); +} + +static void +child_removed_cb (GtkCssNode *node, + GtkCssNode *child, + GtkCssNode *previous, + GtkTreeModelCssNode *model) +{ + gtk_tree_model_css_node_disconnect_node (model, child, TRUE, node, previous); +} + +static void +notify_cb (GtkCssNode *node, + GParamSpec *pspec, + GtkTreeModelCssNode *model) +{ + GtkTreeIter iter; + GtkTreePath *path; + + gtk_tree_model_css_node_get_iter_from_node (model, &iter, node); + path = gtk_tree_model_css_node_get_path (GTK_TREE_MODEL (model), &iter); + + gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter); + + gtk_tree_path_free (path); +} + +static void +style_changed_cb (GtkCssNode *node, + GtkCssStyle *old_style, + GtkCssStyle *new_style, + GtkTreeModelCssNode *model) +{ + GtkTreeIter iter; + GtkTreePath *path; + + gtk_tree_model_css_node_get_iter_from_node (model, &iter, node); + path = gtk_tree_model_css_node_get_path (GTK_TREE_MODEL (model), &iter); + + gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter); + + gtk_tree_path_free (path); +} + +static void +gtk_tree_model_css_node_connect_node (GtkTreeModelCssNode *model, + GtkCssNode *node, + gboolean emit_signal) +{ + GtkCssNode *child; + + g_object_ref (node); + + g_signal_connect_after (node, "node-added", G_CALLBACK (child_added_cb), model); + g_signal_connect_after (node, "node-removed", G_CALLBACK (child_removed_cb), model); + g_signal_connect_after (node, "notify", G_CALLBACK (notify_cb), model); + g_signal_connect_after (node, "style-changed", G_CALLBACK (style_changed_cb), model); + + for (child = gtk_css_node_get_first_child (node); + child; + child = gtk_css_node_get_next_sibling (child)) + { + gtk_tree_model_css_node_connect_node (model, child, FALSE); + } + + if (emit_signal) + { + GtkTreeIter iter; + GtkTreePath *path; + + if (node != model->priv->root && + gtk_css_node_get_previous_sibling (node) == NULL && + gtk_css_node_get_next_sibling (node) == NULL) + { + /* We're the first child of the parent */ + gtk_tree_model_css_node_get_iter_from_node (model, &iter, gtk_css_node_get_parent (node)); + path = gtk_tree_model_css_node_get_path (GTK_TREE_MODEL (model), &iter); + gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model), path, &iter); + gtk_tree_path_free (path); + } + + gtk_tree_model_css_node_get_iter_from_node (model, &iter, node); + path = gtk_tree_model_css_node_get_path (GTK_TREE_MODEL (model), &iter); + gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter); + if (gtk_css_node_get_first_child (node)) + gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model), path, &iter); + + gtk_tree_path_free (path); + } +} + +static void +gtk_tree_model_css_node_disconnect_node (GtkTreeModelCssNode *model, + GtkCssNode *node, + gboolean emit_signal, + GtkCssNode *parent, + GtkCssNode *previous) +{ + GtkCssNode *child; + + g_signal_handlers_disconnect_by_func (node, G_CALLBACK (child_added_cb), model); + g_signal_handlers_disconnect_by_func (node, G_CALLBACK (child_removed_cb), model); + g_signal_handlers_disconnect_by_func (node, G_CALLBACK (notify_cb), model); + g_signal_handlers_disconnect_by_func (node, G_CALLBACK (style_changed_cb), model); + + for (child = gtk_css_node_get_first_child (node); + child; + child = gtk_css_node_get_next_sibling (child)) + { + gtk_tree_model_css_node_disconnect_node (model, child, FALSE, NULL, NULL); + } + + if (emit_signal) + { + GtkTreeIter iter; + GtkTreePath *path; + + if (parent) + { + gtk_tree_model_css_node_get_iter_from_node (model, &iter, parent); + path = gtk_tree_model_css_node_get_path (GTK_TREE_MODEL (model), &iter); + } + else + { + path = gtk_tree_path_new (); + } + if (previous) + gtk_tree_path_append_index (path, get_node_index (previous) + 1); + else + gtk_tree_path_append_index (path, 0); + + gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path); + + if (parent && gtk_css_node_get_first_child (parent) == NULL) + { + gtk_tree_path_up (path); + gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model), path, &iter); + } + + gtk_tree_path_free (path); + } + + g_object_unref (node); +} + +void +gtk_tree_model_css_node_set_root_node (GtkTreeModelCssNode *model, + GtkCssNode *node) +{ + GtkTreeModelCssNodePrivate *priv; + + g_return_if_fail (GTK_IS_TREE_MODEL_CSS_NODE (model)); + g_return_if_fail (node == NULL || GTK_IS_CSS_NODE (node)); + + priv = model->priv; + + if (priv->root == node) + return; + + if (priv->root) + { + gtk_tree_model_css_node_disconnect_node (model, priv->root, TRUE, NULL, NULL); + priv->root = NULL; + } + + if (node) + { + priv->root = node; + gtk_tree_model_css_node_connect_node (model, node, TRUE); + } +} + +GtkCssNode * +gtk_tree_model_css_node_get_root_node (GtkTreeModelCssNode *model) +{ + g_return_val_if_fail (GTK_IS_TREE_MODEL_CSS_NODE (model), NULL); + + return model->priv->root; +} + +GtkCssNode * +gtk_tree_model_css_node_get_node_from_iter (GtkTreeModelCssNode *model, + GtkTreeIter *iter) +{ + g_return_val_if_fail (GTK_IS_TREE_MODEL_CSS_NODE (model), NULL); + g_return_val_if_fail (iter != NULL, NULL); + g_return_val_if_fail (iter->user_data == model, NULL); + g_return_val_if_fail (GTK_IS_CSS_NODE (iter->user_data2), NULL); + + return iter->user_data2; +} + +void +gtk_tree_model_css_node_get_iter_from_node (GtkTreeModelCssNode *model, + GtkTreeIter *iter, + GtkCssNode *node) +{ + g_return_if_fail (GTK_IS_TREE_MODEL_CSS_NODE (model)); + g_return_if_fail (iter != NULL); + g_return_if_fail (GTK_IS_CSS_NODE (node)); + + iter->user_data = model; + iter->user_data2 = node; +} diff --git a/gtk/inspector/gtktreemodelcssnode.h b/gtk/inspector/gtktreemodelcssnode.h new file mode 100644 index 0000000000..d6cabe14c7 --- /dev/null +++ b/gtk/inspector/gtktreemodelcssnode.h @@ -0,0 +1,80 @@ +/* gtktreestore.h + * Copyright (C) 2014 Benjamin Otte <otte@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GTK_TREE_MODEL_CSS_NODE_H__ +#define __GTK_TREE_MODEL_CSS_NODE_H__ + +#include <gtk/gtktreemodel.h> + +#include "gtk/gtkcssnodeprivate.h" + + +G_BEGIN_DECLS + + +#define GTK_TYPE_TREE_MODEL_CSS_NODE (gtk_tree_model_css_node_get_type ()) +#define GTK_TREE_MODEL_CSS_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TREE_MODEL_CSS_NODE, GtkTreeModelCssNode)) +#define GTK_TREE_MODEL_CSS_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TREE_MODEL_CSS_NODE, GtkTreeModelCssNodeClass)) +#define GTK_IS_TREE_MODEL_CSS_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TREE_MODEL_CSS_NODE)) +#define GTK_IS_TREE_MODEL_CSS_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TREE_MODEL_CSS_NODE)) +#define GTK_TREE_MODEL_CSS_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TREE_MODEL_CSS_NODE, GtkTreeModelCssNodeClass)) + +typedef struct _GtkTreeModelCssNode GtkTreeModelCssNode; +typedef struct _GtkTreeModelCssNodeClass GtkTreeModelCssNodeClass; +typedef struct _GtkTreeModelCssNodePrivate GtkTreeModelCssNodePrivate; + +typedef void (* GtkTreeModelCssNodeGetFunc) (GtkTreeModelCssNode *model, + GtkCssNode *node, + int column, + GValue *value); + +struct _GtkTreeModelCssNode +{ + GObject parent; + + GtkTreeModelCssNodePrivate *priv; +}; + +struct _GtkTreeModelCssNodeClass +{ + GObjectClass parent_class; +}; + + +GType gtk_tree_model_css_node_get_type (void) G_GNUC_CONST; + +GtkTreeModel *gtk_tree_model_css_node_new (GtkTreeModelCssNodeGetFunc get_func, + gint n_columns, + ...); +GtkTreeModel *gtk_tree_model_css_node_newv (GtkTreeModelCssNodeGetFunc get_func, + gint n_columns, + GType *types); + +void gtk_tree_model_css_node_set_root_node (GtkTreeModelCssNode *model, + GtkCssNode *node); +GtkCssNode *gtk_tree_model_css_node_get_root_node (GtkTreeModelCssNode *model); +GtkCssNode *gtk_tree_model_css_node_get_node_from_iter(GtkTreeModelCssNode *model, + GtkTreeIter *iter); +void gtk_tree_model_css_node_get_iter_from_node(GtkTreeModelCssNode *model, + GtkTreeIter *iter, + GtkCssNode *node); + + +G_END_DECLS + + +#endif /* __GTK_TREE_MODEL_CSS_NODE_H__ */ diff --git a/gtk/inspector/init.c b/gtk/inspector/init.c index 14acd8e66e..ed8180e67a 100644 --- a/gtk/inspector/init.c +++ b/gtk/inspector/init.c @@ -28,6 +28,7 @@ #include "cellrenderergraph.h" #include "classes-list.h" #include "css-editor.h" +#include "css-node-tree.h" #include "data-list.h" #include "general.h" #include "gestures.h" @@ -61,6 +62,7 @@ gtk_inspector_init (void) g_type_ensure (GTK_TYPE_INSPECTOR_ACTIONS); g_type_ensure (GTK_TYPE_INSPECTOR_CLASSES_LIST); g_type_ensure (GTK_TYPE_INSPECTOR_CSS_EDITOR); + g_type_ensure (GTK_TYPE_INSPECTOR_CSS_NODE_TREE); g_type_ensure (GTK_TYPE_INSPECTOR_DATA_LIST); g_type_ensure (GTK_TYPE_INSPECTOR_GENERAL); g_type_ensure (GTK_TYPE_INSPECTOR_GESTURES); diff --git a/gtk/inspector/window.c b/gtk/inspector/window.c index 3846ecdcdd..d7b6d22405 100644 --- a/gtk/inspector/window.c +++ b/gtk/inspector/window.c @@ -31,6 +31,7 @@ #include "prop-list.h" #include "classes-list.h" #include "css-editor.h" +#include "css-node-tree.h" #include "object-hierarchy.h" #include "object-tree.h" #include "selector.h" @@ -71,6 +72,7 @@ set_selected_object (GtkInspectorWindow *iw, gtk_inspector_misc_info_set_object (GTK_INSPECTOR_MISC_INFO (iw->misc_info), selected); gtk_inspector_classes_list_set_object (GTK_INSPECTOR_CLASSES_LIST (iw->classes_list), selected); gtk_inspector_css_editor_set_object (GTK_INSPECTOR_CSS_EDITOR (iw->widget_css_editor), selected); + gtk_inspector_css_node_tree_set_object (GTK_INSPECTOR_CSS_NODE_TREE (iw->widget_css_node_tree), selected); gtk_inspector_size_groups_set_object (GTK_INSPECTOR_SIZE_GROUPS (iw->size_groups), selected); gtk_inspector_data_list_set_object (GTK_INSPECTOR_DATA_LIST (iw->data_list), selected); gtk_inspector_actions_set_object (GTK_INSPECTOR_ACTIONS (iw->actions), selected); @@ -228,6 +230,7 @@ gtk_inspector_window_class_init (GtkInspectorWindowClass *klass) gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, classes_list); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, style_prop_list); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, widget_css_editor); + gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, widget_css_node_tree); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, object_hierarchy); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, selector); gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, size_groups); diff --git a/gtk/inspector/window.h b/gtk/inspector/window.h index 07a469d8eb..80de702088 100644 --- a/gtk/inspector/window.h +++ b/gtk/inspector/window.h @@ -57,6 +57,7 @@ typedef struct GtkWidget *style_prop_list; GtkWidget *classes_list; GtkWidget *widget_css_editor; + GtkWidget *widget_css_node_tree; GtkWidget *object_hierarchy; GtkWidget *size_groups; GtkWidget *data_list; diff --git a/gtk/inspector/window.ui b/gtk/inspector/window.ui index 272959c727..f01dc7c944 100644 --- a/gtk/inspector/window.ui +++ b/gtk/inspector/window.ui @@ -320,6 +320,15 @@ </packing> </child> <child> + <object class="GtkInspectorCssNodeTree" id="widget_css_node_tree"> + <property name="visible">True</property> + </object> + <packing> + <property name="name">css-nodes</property> + <property name="title" translatable="yes">CSS nodes</property> + </packing> + </child> + <child> <object class="GtkInspectorCssEditor" id="widget_css_editor"> <property name="global">False</property> </object> diff --git a/gtk/inspector/window.ui.h b/gtk/inspector/window.ui.h index 05c6b2126c..a0a356a62d 100644 --- a/gtk/inspector/window.ui.h +++ b/gtk/inspector/window.ui.h @@ -12,6 +12,7 @@ N_("Hierarchy"); N_("Selector"); N_("Style Classes"); N_("Style Properties"); +N_("CSS nodes"); N_("CSS"); N_("Size Groups"); N_("Data"); |