diff options
author | Matthias Clasen <mclasen@redhat.com> | 2015-12-28 01:09:54 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2015-12-29 07:46:30 -0500 |
commit | 1535e2234419398d7a3bf15c719ba2d6ab2ae179 (patch) | |
tree | 70839aaecf93f9cb0c36095913ddab66e68432ad | |
parent | 1e1af62beed4f89722a6c88a23a344a6e0828244 (diff) | |
download | gtk+-1535e2234419398d7a3bf15c719ba2d6ab2ae179.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.
-rw-r--r-- | docs/reference/gtk/gtk3-sections.txt | 2 | ||||
-rw-r--r-- | gtk/gtkcssnode.c | 163 | ||||
-rw-r--r-- | gtk/gtkcssnodeprivate.h | 5 | ||||
-rw-r--r-- | gtk/gtkstylecontext.c | 45 | ||||
-rw-r--r-- | 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 e5cd1ef7e7..6d5c590de5 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 fca7de0cec..7aa31a601f 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 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..a6b52951f3 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 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__ */ |