summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2015-12-28 01:09:54 -0500
committerMatthias Clasen <mclasen@redhat.com>2016-01-03 09:19:30 -0500
commit68edc47f6a1585c90d8cace2f65c61a2a413b79e (patch)
tree58bf74ba106dcea1d070440e676970092beb450b /gtk
parenta6624d803ece178e467230e285cd9d4561b09ca1 (diff)
downloadgtk+-68edc47f6a1585c90d8cace2f65c61a2a413b79e.tar.gz
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.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtkcssnode.c190
-rw-r--r--gtk/gtkcssnodeprivate.h5
-rw-r--r--gtk/gtkstylecontext.c50
-rw-r--r--gtk/gtkstylecontext.h11
4 files changed, 255 insertions, 1 deletions
diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c
index fca7de0cec..4bae4e51ea 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,189 @@ 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 gboolean
+gtk_css_node_has_initial_value (GtkCssNode *cssnode,
+ GtkCssStyleProperty *prop)
+{
+ GtkCssNode *parent_node;
+ GtkCssStyle *style, *parent_style;
+ GtkCssValue *value, *initial, *computed;
+ GtkCssProvider *provider;
+ gboolean is_initial;
+ guint id;
+
+ id = _gtk_css_style_property_get_id (prop);
+ style = gtk_css_node_get_style (cssnode);
+ value = gtk_css_style_get_value (style, id);
+
+ parent_node = gtk_css_node_get_parent (cssnode);
+ parent_style = parent_node ? gtk_css_node_get_style (parent_node) : NULL;
+ provider = gtk_css_node_get_style_provider (cssnode);
+
+ initial = _gtk_css_style_property_get_initial_value (prop);
+ computed = _gtk_css_value_compute (initial, id, provider, style, parent_style);
+
+ is_initial = _gtk_css_value_equal (value, computed);
+
+ _gtk_css_value_unref (computed);
+
+ return is_initial;
+}
+
+static void
+append_value (GtkCssNode *cssnode,
+ GtkCssStyleProperty *prop,
+ GString *string,
+ guint indent)
+{
+ GtkCssValue *value;
+ GtkCssStyle *style;
+ GtkCssSection *section;
+ const char *name;
+ guint id;
+
+ id = _gtk_css_style_property_get_id (prop);
+ name = _gtk_style_property_get_name (GTK_STYLE_PROPERTY (prop));
+ style = gtk_css_node_get_style (cssnode);
+ value = gtk_css_style_get_value (style, id);
+
+ g_string_append_printf (string, "%*s%s: ", indent, "", name);
+
+ _gtk_css_value_print (value, string);
+
+ section = gtk_css_style_get_section (style, id);
+ if (section)
+ {
+ g_string_append (string, " (");
+ _gtk_css_section_print (section, string);
+ g_string_append (string, ")");
+ }
+
+ g_string_append_c (string, '\n');
+}
+
+static void
+append_style (GtkCssNode *cssnode,
+ GtkStyleContextPrintFlags flags,
+ GString *string,
+ guint indent)
+{
+ int i;
+
+ if (!(flags & GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE))
+ return;
+
+ for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++)
+ {
+ GtkCssStyleProperty *prop;
+
+ prop = _gtk_css_style_property_lookup_by_id (i);
+
+ if ((flags & GTK_STYLE_CONTEXT_PRINT_SHOW_INITIAL) ||
+ !gtk_css_node_has_initial_value (cssnode, prop))
+ append_value (cssnode, prop, string, indent);
+ }
+}
+
+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 8624a51678..065b8e72a0 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 7fe5f3cf8a..30173c7c15 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -3219,3 +3219,53 @@ _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().
+ * New values may be added to this enumeration.
+ */
+
+/**
+ * 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.
+ *
+ * This function is intended for testing and debugging of the
+ * CSS implementation in GTK+. There are no guarantees about
+ * the format of the returned string, it may change.
+ *
+ * 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 8428213b26..d6fe5754f7 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__ */