summaryrefslogtreecommitdiff
path: root/gtk/gtkcssnode.c
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/gtkcssnode.c
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/gtkcssnode.c')
-rw-r--r--gtk/gtkcssnode.c190
1 files changed, 189 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);
+ }
+}