diff options
author | Matthias Clasen <mclasen@redhat.com> | 2016-01-04 15:34:50 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2016-01-04 15:39:48 -0500 |
commit | bc020fdeb73f6a906a867e1ad28a0886ea5361e7 (patch) | |
tree | a39328d29ad533f2f75e05603ac83f5e2674b75d /tests | |
parent | c5437125518cf04f3f25c3e2f4ca3593467a21a9 (diff) | |
download | gtk+-bc020fdeb73f6a906a867e1ad28a0886ea5361e7.tar.gz |
tests: Rework the way foreigndrawing works
Instead of the weird PathElt struct, generate a quick-n-dirty parser
that parses CSS selectors into GtkWidgetPath elements.
Based on a patch by Benjamin Otte.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/foreigndrawing.c | 160 |
1 files changed, 124 insertions, 36 deletions
diff --git a/tests/foreigndrawing.c b/tests/foreigndrawing.c index eb4a61a34a..3320cb6f8d 100644 --- a/tests/foreigndrawing.c +++ b/tests/foreigndrawing.c @@ -18,15 +18,107 @@ #include <gtk/gtk.h> -typedef struct { - GType type; - const gchar *name; - const gchar *class1; - const gchar *class2; -} PathElt; +#include <string.h> + +static void +append_element (GtkWidgetPath *path, + const char *selector) +{ + static const struct { + const char *name; + GtkStateFlags state_flag; + } pseudo_classes[] = { + { "active", GTK_STATE_FLAG_ACTIVE }, + { "hover", GTK_STATE_FLAG_PRELIGHT }, + { "selected", GTK_STATE_FLAG_SELECTED }, + { "disabled", GTK_STATE_FLAG_INSENSITIVE }, + { "indeterminate", GTK_STATE_FLAG_INCONSISTENT }, + { "focus", GTK_STATE_FLAG_FOCUSED }, + { "backdrop", GTK_STATE_FLAG_BACKDROP }, + { "dir(ltr)", GTK_STATE_FLAG_DIR_LTR }, + { "dir(rtl)", GTK_STATE_FLAG_DIR_RTL }, + { "link", GTK_STATE_FLAG_LINK }, + { "visited", GTK_STATE_FLAG_VISITED }, + { "checked", GTK_STATE_FLAG_CHECKED }, + { "drop(active)", GTK_STATE_FLAG_DROP_ACTIVE } + }; + const char *next; + char *name; + char type; + guint i; + + next = strpbrk (selector, "#.:"); + if (next == NULL) + next = selector + strlen (selector); + + name = g_strndup (selector, next - selector); + if (g_ascii_isupper (selector[0])) + { + GType gtype; + gtype = g_type_from_name (name); + if (gtype == G_TYPE_INVALID) + { + g_critical ("Unknown type name `%s'", name); + g_free (name); + return; + } + gtk_widget_path_append_type (path, gtype); + } + else + { + /* Omit type, we're using name */ + gtk_widget_path_append_type (path, G_TYPE_NONE); + gtk_widget_path_iter_set_object_name (path, -1, name); + } + g_free (name); + + while (*next != '\0') + { + type = *next; + selector = next + 1; + next = strpbrk (selector, "#.:"); + if (next == NULL) + next = selector + strlen (selector); + name = g_strndup (selector, next - selector); + + switch (type) + { + case '#': + gtk_widget_path_iter_set_name (path, -1, name); + break; + + case '.': + gtk_widget_path_iter_add_class (path, -1, name); + break; + + case ':': + for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++) + { + if (g_str_equal (pseudo_classes[i].name, name)) + { + gtk_widget_path_iter_set_state (path, + -1, + gtk_widget_path_iter_get_state (path, -1) + | pseudo_classes[i].state_flag); + break; + } + } + if (i == G_N_ELEMENTS (pseudo_classes)) + g_critical ("Unknown pseudo-class :%s", name); + break; + + default: + g_assert_not_reached (); + break; + } + + g_free (name); + } +} static GtkStyleContext * -get_style (PathElt *pelt, GtkStyleContext *parent) +get_style (GtkStyleContext *parent, + const char *selector) { GtkWidgetPath *path; GtkStyleContext *context; @@ -36,17 +128,13 @@ get_style (PathElt *pelt, GtkStyleContext *parent) else path = gtk_widget_path_new (); - gtk_widget_path_append_type (path, pelt->type); - if (pelt->name) - gtk_widget_path_iter_set_object_name (path, -1, pelt->name); - if (pelt->class1) - gtk_widget_path_iter_add_class (path, -1, pelt->class1); - if (pelt->class2) - gtk_widget_path_iter_add_class (path, -1, pelt->class2); + append_element (path, selector); context = gtk_style_context_new (); gtk_style_context_set_path (context, path); gtk_style_context_set_parent (context, parent); + /* XXX: Why is this necessary? */ + gtk_style_context_set_state (context, gtk_widget_path_iter_get_state (path, -1)); gtk_widget_path_unref (path); return context; @@ -67,15 +155,15 @@ draw_horizontal_scrollbar (GtkWidget *widget, GtkStyleContext *slider_context; /* This information is taken from the GtkScrollbar docs, see "CSS nodes" */ - PathElt path[3] = { - { GTK_TYPE_SCROLLBAR, "scrollbar", "horizontal", NULL }, - { G_TYPE_NONE, "trough", NULL, NULL }, - { G_TYPE_NONE, "slider", NULL, NULL } + const char *path[3] = { + "scrollbar.horizontal", + "trough", + "slider" }; - scrollbar_context = get_style (&path[0], NULL); - trough_context = get_style (&path[1], scrollbar_context); - slider_context = get_style (&path[2], trough_context); + scrollbar_context = get_style (NULL, path[0]); + trough_context = get_style (scrollbar_context, path[1]); + slider_context = get_style (trough_context, path[2]); gtk_style_context_set_state (scrollbar_context, state); gtk_style_context_set_state (trough_context, state); @@ -106,13 +194,13 @@ draw_text (GtkWidget *widget, PangoLayout *layout; /* This information is taken from the GtkLabel docs, see "CSS nodes" */ - PathElt path[2] = { - { GTK_TYPE_LABEL, "label", "view", NULL }, - { G_TYPE_NONE, "selection", NULL, NULL } + const char *path[2] = { + "label.view", + "selection" }; - label_context = get_style (&path[0], NULL); - selection_context = get_style (&path[1], label_context); + label_context = get_style (NULL, path[0]); + selection_context = get_style (label_context, path[1]); gtk_style_context_set_state (label_context, state); @@ -144,13 +232,13 @@ draw_check (GtkWidget *widget, GtkStyleContext *check_context; /* This information is taken from the GtkCheckButton docs, see "CSS nodes" */ - PathElt path[2] = { - { GTK_TYPE_LABEL, "checkbutton", NULL, NULL }, - { G_TYPE_NONE, "check", NULL, NULL } + const char *path[2] = { + "checkbutton", + "check" }; - button_context = get_style (&path[0], NULL); - check_context = get_style (&path[1], button_context); + button_context = get_style (NULL, path[0]); + check_context = get_style (button_context, path[1]); gtk_style_context_set_state (check_context, state); @@ -174,13 +262,13 @@ draw_radio (GtkWidget *widget, GtkStyleContext *check_context; /* This information is taken from the GtkRadioButton docs, see "CSS nodes" */ - PathElt path[2] = { - { GTK_TYPE_LABEL, "radiobutton", NULL, NULL }, - { G_TYPE_NONE, "radio", NULL, NULL } + const char *path[2] = { + "radiobutton", + "radio" }; - button_context = get_style (&path[0], NULL); - check_context = get_style (&path[1], button_context); + button_context = get_style (NULL, path[0]); + check_context = get_style (button_context, path[1]); gtk_style_context_set_state (check_context, state); |