[gtk+/wip/matthiasc/node-dump: 1/12] Add a function to dump CSS nodes and styles



commit 1535e2234419398d7a3bf15c719ba2d6ab2ae179
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Dec 28 01:09:54 2015 -0500

    Add a function to dump CSS nodes and styles
    
    Add a gtk_style_context_to_string function that can serialize
    a CSS node or tree of nodes, optionally including CSS properties
    as well.
    
    This will be useful in writing tests.

 docs/reference/gtk/gtk3-sections.txt |    2 +
 gtk/gtkcssnode.c                     |  163 +++++++++++++++++++++++++++++++++-
 gtk/gtkcssnodeprivate.h              |    5 +
 gtk/gtkstylecontext.c                |   45 +++++++++
 gtk/gtkstylecontext.h                |   11 +++
 5 files changed, 225 insertions(+), 1 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index e5cd1ef..6d5c590 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -6244,6 +6244,8 @@ gtk_style_context_set_frame_clock
 gtk_style_context_set_state
 gtk_style_context_set_scale
 gtk_style_context_get_scale
+GtkStyleContextPrintFlags
+gtk_style_context_to_string
 
 <SUBSECTION>
 GtkBorder
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index fca7de0..7aa31a6 100644
--- a/gtk/gtkcssnode.c
+++ b/gtk/gtkcssnode.c
@@ -25,6 +25,8 @@
 #include "gtkmarshalers.h"
 #include "gtksettingsprivate.h"
 #include "gtktypebuiltins.h"
+#include "gtkcssstylepropertyprivate.h"
+#include "gtkcsssectionprivate.h"
 
 /*
  * CSS nodes are the backbone of the GtkStyleContext implementation and
@@ -1510,7 +1512,7 @@ GtkStyleProviderPrivate *
 gtk_css_node_get_style_provider (GtkCssNode *cssnode)
 {
   GtkStyleProviderPrivate *result;
-  
+
   result = gtk_css_node_get_style_provider_or_null (cssnode);
   if (result)
     return result;
@@ -1520,3 +1522,162 @@ gtk_css_node_get_style_provider (GtkCssNode *cssnode)
 
   return GTK_STYLE_PROVIDER_PRIVATE (_gtk_settings_get_style_cascade (gtk_settings_get_default (), 1));
 }
+
+static void
+append_id (GtkCssNode *cssnode,
+           GString    *string)
+{
+  const char *id;
+
+  id = gtk_css_node_get_id (cssnode);
+  if (id)
+    {
+      g_string_append (string, " id=");
+      g_string_append (string, id);
+    }
+}
+
+static void
+append_visible (GtkCssNode *cssnode,
+                GString    *string)
+{
+  g_string_append_printf (string, " visible=%d", gtk_css_node_get_visible (cssnode));
+}
+
+static void
+append_state (GtkCssNode *cssnode,
+              GString    *string)
+
+{
+  GtkStateFlags state;
+
+  state = gtk_css_node_get_state (cssnode);
+  if (state)
+    {
+      GFlagsClass *fclass;
+      gint i;
+      gboolean first = TRUE;
+
+      g_string_append (string, " state=");
+      fclass = g_type_class_ref (GTK_TYPE_STATE_FLAGS);
+      for (i = 0; i < fclass->n_values; i++)
+        {
+          if (state & fclass->values[i].value)
+            {
+              if (first)
+                first = FALSE;
+              else
+                g_string_append_c (string, '|');
+              g_string_append (string, fclass->values[i].value_nick);
+            }
+        }
+      g_type_class_unref (fclass);
+    }
+}
+
+static void
+append_classes (GtkCssNode *cssnode,
+                GString    *string)
+{
+  const GQuark *classes;
+  guint n_classes;
+
+  classes = gtk_css_node_list_classes (cssnode, &n_classes);
+  if (n_classes > 0)
+    {
+      int i;
+
+      g_string_append (string, " classes=");
+      for (i = 0; i < n_classes; i++)
+        {
+          if (i > 0)
+            g_string_append_c (string, ',');
+          g_string_append (string, g_quark_to_string (classes[i]));
+        }
+    }
+}
+
+static void
+append_style (GtkCssNode                *cssnode,
+              GtkStyleContextPrintFlags  flags,
+              GString                   *string,
+              guint                      indent)
+{
+  int i;
+  GtkCssStyle *style;
+
+  if (!(flags & GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE))
+    return;
+
+  style = gtk_css_node_get_style (cssnode);
+
+  for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++)
+    {
+      GtkCssStyleProperty *prop;
+      GtkCssValue *value;
+      GtkCssSection *section;
+      const char *name;
+
+      prop = _gtk_css_style_property_lookup_by_id (i);
+      name = _gtk_style_property_get_name (GTK_STYLE_PROPERTY (prop));
+      value = gtk_css_style_get_value (style, i);
+
+      if (!(flags & GTK_STYLE_CONTEXT_PRINT_SHOW_INITIAL))
+        {
+          GtkCssValue *initial, *computed;
+          GtkCssNode *parent_node;
+          GtkCssStyle *parent_style;
+
+          parent_node = gtk_css_node_get_parent (cssnode);
+          parent_style = parent_node ? gtk_css_node_get_style (parent_node) : NULL;
+          initial = _gtk_css_style_property_get_initial_value (prop);
+          computed = _gtk_css_value_compute (initial,
+                                             i,
+                                             gtk_css_node_get_style_provider (cssnode),
+                                             style,
+                                             parent_style);
+          if (_gtk_css_value_equal (value, computed))
+            continue;
+        }
+
+      g_string_append_printf (string, "%*s%s: ", indent, "", name);
+      _gtk_css_value_print (value, string);
+
+      section = gtk_css_style_get_section (style, i);
+      if (section)
+        {
+          g_string_append (string, " (");
+          _gtk_css_section_print (section, string);
+          g_string_append (string, ")");
+        }
+      g_string_append_c (string, '\n');
+    }
+}
+
+void
+gtk_css_node_print (GtkCssNode                *cssnode,
+                    GtkStyleContextPrintFlags  flags,
+                    GString                   *string,
+                    guint                      indent)
+{
+  GtkCssNode *node;
+
+  g_string_append_printf (string, "%*s", indent, "");
+  if (gtk_css_node_get_name (cssnode))
+    g_string_append (string, gtk_css_node_get_name (cssnode));
+  else
+    g_string_append (string, g_type_name (gtk_css_node_get_widget_type (cssnode)));
+  append_id (cssnode, string);
+  append_visible (cssnode, string);
+  append_state (cssnode, string);
+  append_classes (cssnode, string);
+  g_string_append_c (string, '\n');
+
+  append_style (cssnode, flags, string, indent + 2);
+
+  if (flags & GTK_STYLE_CONTEXT_PRINT_RECURSE)
+    {
+      for (node = gtk_css_node_get_first_child (cssnode); node; node = gtk_css_node_get_next_sibling (node))
+        gtk_css_node_print (node, flags, string, indent + 2);
+    }
+}
diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h
index 8624a51..065b8e7 100644
--- a/gtk/gtkcssnodeprivate.h
+++ b/gtk/gtkcssnodeprivate.h
@@ -171,6 +171,11 @@ GtkWidgetPath *         gtk_css_node_create_widget_path (GtkCssNode            *
 const GtkWidgetPath *   gtk_css_node_get_widget_path    (GtkCssNode            *cssnode);
 GtkStyleProviderPrivate *gtk_css_node_get_style_provider(GtkCssNode            *cssnode);
 
+void                    gtk_css_node_print              (GtkCssNode                *cssnode,
+                                                         GtkStyleContextPrintFlags  flags,
+                                                         GString                   *string,
+                                                         guint                      indent);
+
 G_END_DECLS
 
 #endif /* __GTK_CSS_NODE_PRIVATE_H__ */
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index 7fe5f3c..a6b5295 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -3219,3 +3219,48 @@ _gtk_style_context_is_background_opaque (GtkStyleContext *context)
           corner_value_is_right_angle (_gtk_style_context_peek_property (context, 
GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS)) &&
           corner_value_is_right_angle (_gtk_style_context_peek_property (context, 
GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS)));
 }
+
+/**
+ * GtkStyleContextPrintFlags:
+ * @GTK_STYLE_CONTEXT_PRINT_RECURSE: Print the entire tree of
+ *     CSS nodes starting at the style context's node
+ * @GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE: Show the values of the
+ *     CSS properties for each node
+ * @GTK_STYLE_CONTEXT_PRINT_SHOW_INITIAL: Show the values of the
+ *     CSS properties even if they match the initial value. By default,
+ *     values are only shown if they are different from the initial
+ *     value.
+ *
+ * Flags that modify the behavior of gtk_style_context_to_string().
+ */
+
+/**
+ * gtk_style_context_to_string:
+ * @context: a #GtkStyleContext
+ * @flags: Flags that determine what to print
+ *
+ * Converts the style context into a string representation.
+ *
+ * The string representation always includes information about
+ * the name, state, id, visibility and style classes of the CSS
+ * node that is backing @context. Depending on the flags, more
+ * information may be included.
+ *
+ * Returns: a newly allocated string representing @context
+ *
+ * Since: 3.20
+ */
+char *
+gtk_style_context_to_string (GtkStyleContext           *context,
+                             GtkStyleContextPrintFlags  flags)
+{
+  GString *string;
+
+  g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
+
+  string = g_string_new ("");
+
+  gtk_css_node_print (context->priv->cssnode, flags, string, 0);
+
+  return g_string_free (string, FALSE);
+}
diff --git a/gtk/gtkstylecontext.h b/gtk/gtkstylecontext.h
index 8428213..d6fe575 100644
--- a/gtk/gtkstylecontext.h
+++ b/gtk/gtkstylecontext.h
@@ -1208,6 +1208,17 @@ void   gtk_draw_insertion_cursor    (GtkWidget          *widget,
                                      GtkTextDirection    direction,
                                      gboolean            draw_arrow);
 
+typedef enum {
+  GTK_STYLE_CONTEXT_PRINT_NONE         = 0,
+  GTK_STYLE_CONTEXT_PRINT_RECURSE      = 1 << 0,
+  GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE   = 1 << 1,
+  GTK_STYLE_CONTEXT_PRINT_SHOW_INITIAL = 1 << 2
+} GtkStyleContextPrintFlags;
+
+GDK_AVAILABLE_IN_3_20
+char * gtk_style_context_to_string (GtkStyleContext           *context,
+                                    GtkStyleContextPrintFlags  flags);
+
 G_END_DECLS
 
 #endif /* __GTK_STYLE_CONTEXT_H__ */


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