diff options
author | Matthias Clasen <mclasen@redhat.com> | 2015-12-28 01:09:54 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2016-01-03 09:19:30 -0500 |
commit | 68edc47f6a1585c90d8cace2f65c61a2a413b79e (patch) | |
tree | 58bf74ba106dcea1d070440e676970092beb450b /gtk | |
parent | a6624d803ece178e467230e285cd9d4561b09ca1 (diff) | |
download | gtk+-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.c | 190 | ||||
-rw-r--r-- | gtk/gtkcssnodeprivate.h | 5 | ||||
-rw-r--r-- | gtk/gtkstylecontext.c | 50 | ||||
-rw-r--r-- | gtk/gtkstylecontext.h | 11 |
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__ */ |