#include "config.h" #include #include #include 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 * create_context_for_path (GtkWidgetPath *path, GtkStyleContext *parent) { GtkStyleContext *context; context = gtk_style_context_new (); gtk_style_context_set_path (context, path); gtk_style_context_set_parent (context, parent); /* Unfortunately, we have to explicitly set the state again here * for it to take effect */ gtk_style_context_set_state (context, gtk_widget_path_iter_get_state (path, -1)); gtk_widget_path_unref (path); return context; } static GtkStyleContext * get_style (GtkStyleContext *parent, const char *selector) { GtkWidgetPath *path; if (parent) path = gtk_widget_path_copy (gtk_style_context_get_path (parent)); else path = gtk_widget_path_new (); append_element (path, selector); return create_context_for_path (path, parent); } int main(int argc, char *argv[] ) { gtk_init (&argc, &argv); if (g_getenv ("GTK_RTL")) gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL); { GtkCssProvider *prov = gtk_css_provider_new (); gtk_css_provider_load_from_data (prov, "button.itembar { color: green; }\nbutton:active.itembar { color: red; }\nbutton:hover.itembar { color: red; }", -1, NULL); gtk_style_context_add_provider_for_screen (gdk_screen_get_default(), GTK_STYLE_PROVIDER (prov), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); GtkStyleContext *ctxt = get_style (NULL, "button:active.itembar"); GdkRGBA c; gtk_style_context_get_color (ctxt, gtk_style_context_get_state (ctxt), &c); g_printerr ("colour=%s\n", gdk_rgba_to_string (&c)); gtk_style_context_save (ctxt); gtk_style_context_get_color (ctxt, gtk_style_context_get_state (ctxt), &c); g_printerr ("colour=%s\n", gdk_rgba_to_string (&c)); gtk_style_context_restore (ctxt); gtk_style_context_get_color (ctxt, gtk_style_context_get_state (ctxt), &c); g_printerr ("colour=%s\n", gdk_rgba_to_string (&c)); } //gtk_main(); return(0); } /* example-end */