[gtk+] style cascade: Allow cascades with more ancestors
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] style cascade: Allow cascades with more ancestors
- Date: Mon, 20 Jun 2016 00:03:52 +0000 (UTC)
commit 76bacfde6e5305021c765ae690972efb1832682d
Author: Philip Chimento <philip endlessm com>
Date: Wed Jun 15 23:02:11 2016 -0400
style cascade: Allow cascades with more ancestors
Previously a style cascade's parent could not have a parent itself. That
represented the two levels at which you could add a style provider: at
the screen level, with gtk_style_context_add_provider_for_screen(), and
at the style context level, with gtk_style_context_add_provider().
This commit changes no functionality, but this change will be necessary
for adding style providers in the future that apply to a subtree of the
widget tree. It relaxes the requirement that a style cascade's parent
must not have a parent, since in the future a style context may be
affected by any number of parent widgets' style contexts.
https://bugzilla.gnome.org/show_bug.cgi?id=751409
gtk/gtkstylecascade.c | 99 +++++++++++--------
testsuite/gtk/stylecontext.c | 230 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 288 insertions(+), 41 deletions(-)
---
diff --git a/gtk/gtkstylecascade.c b/gtk/gtkstylecascade.c
index 6afa40c..2c890f5 100644
--- a/gtk/gtkstylecascade.c
+++ b/gtk/gtkstylecascade.c
@@ -27,8 +27,9 @@ typedef struct _GtkStyleCascadeIter GtkStyleCascadeIter;
typedef struct _GtkStyleProviderData GtkStyleProviderData;
struct _GtkStyleCascadeIter {
- int parent_index; /* pointing at last index that was returned, not next one that should be returned */
- int index; /* pointing at last index that was returned, not next one that should be returned */
+ int n_cascades;
+ int *cascade_index; /* each one points at last index that was returned, */
+ /* not next one that should be returned */
};
struct _GtkStyleProviderData
@@ -42,56 +43,57 @@ static GtkStyleProvider *
gtk_style_cascade_iter_next (GtkStyleCascade *cascade,
GtkStyleCascadeIter *iter)
{
- if (iter->parent_index > 0)
- {
- if (iter->index > 0)
- {
- GtkStyleProviderData *data, *parent_data;
+ GtkStyleCascade *cas;
+ int ix, highest_priority_index = 0;
+ GtkStyleProviderData *highest_priority_data = NULL;
- data = &g_array_index (cascade->providers, GtkStyleProviderData, iter->index - 1);
- parent_data = &g_array_index (cascade->parent->providers, GtkStyleProviderData, iter->parent_index
- 1);
+ for (cas = cascade, ix = 0; ix < iter->n_cascades; cas = cas->parent, ix++)
+ {
+ if (iter->cascade_index[ix] <= 0)
+ continue;
- if (data->priority >= parent_data->priority)
- {
- iter->index--;
- return data->provider;
- }
- else
- {
- iter->parent_index--;
- return parent_data->provider;
- }
- }
- else
+ GtkStyleProviderData *data = &g_array_index (cas->providers,
+ GtkStyleProviderData,
+ iter->cascade_index[ix] - 1);
+ if (highest_priority_data == NULL || data->priority > highest_priority_data->priority)
{
- iter->parent_index--;
- return g_array_index (cascade->parent->providers, GtkStyleProviderData,
iter->parent_index).provider;
+ highest_priority_index = ix;
+ highest_priority_data = data;
}
}
- else
+
+ if (highest_priority_data != NULL)
{
- if (iter->index > 0)
- {
- iter->index--;
- return g_array_index (cascade->providers, GtkStyleProviderData, iter->index).provider;
- }
- else
- {
- return NULL;
- }
+ iter->cascade_index[highest_priority_index]--;
+ return highest_priority_data->provider;
}
+ return NULL;
}
static GtkStyleProvider *
gtk_style_cascade_iter_init (GtkStyleCascade *cascade,
GtkStyleCascadeIter *iter)
{
- iter->parent_index = cascade->parent ? cascade->parent->providers->len : 0;
- iter->index = cascade->providers->len;
+ GtkStyleCascade *cas = cascade;
+ int ix;
+
+ iter->n_cascades = 1;
+ while ((cas = cas->parent) != NULL)
+ iter->n_cascades++;
+
+ iter->cascade_index = g_new (int, iter->n_cascades);
+ for (cas = cascade, ix = 0; ix < iter->n_cascades; cas = cas->parent, ix++)
+ iter->cascade_index[ix] = cas->providers->len;
return gtk_style_cascade_iter_next (cascade, iter);
}
+static void
+gtk_style_cascade_iter_clear (GtkStyleCascadeIter *iter)
+{
+ g_free (iter->cascade_index);
+}
+
static gboolean
gtk_style_cascade_get_style_property (GtkStyleProvider *provider,
GtkWidgetPath *path,
@@ -112,9 +114,13 @@ gtk_style_cascade_get_style_property (GtkStyleProvider *provider,
state,
pspec,
value))
- return TRUE;
+ {
+ gtk_style_cascade_iter_clear (&iter);
+ return TRUE;
+ }
}
+ gtk_style_cascade_iter_clear (&iter);
return FALSE;
}
@@ -141,9 +147,13 @@ gtk_style_cascade_get_settings (GtkStyleProviderPrivate *provider)
settings = _gtk_style_provider_private_get_settings (GTK_STYLE_PROVIDER_PRIVATE (item));
if (settings)
- return settings;
+ {
+ gtk_style_cascade_iter_clear (&iter);
+ return settings;
+ }
}
+ gtk_style_cascade_iter_clear (&iter);
return NULL;
}
@@ -164,7 +174,10 @@ gtk_style_cascade_get_color (GtkStyleProviderPrivate *provider,
{
color = _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (item), name);
if (color)
- return color;
+ {
+ gtk_style_cascade_iter_clear (&iter);
+ return color;
+ }
}
else
{
@@ -172,6 +185,7 @@ gtk_style_cascade_get_color (GtkStyleProviderPrivate *provider,
}
}
+ gtk_style_cascade_iter_clear (&iter);
return NULL;
}
@@ -201,9 +215,13 @@ gtk_style_cascade_get_keyframes (GtkStyleProviderPrivate *provider,
keyframes = _gtk_style_provider_private_get_keyframes (GTK_STYLE_PROVIDER_PRIVATE (item), name);
if (keyframes)
- return keyframes;
+ {
+ gtk_style_cascade_iter_clear (&iter);
+ return keyframes;
+ }
}
+ gtk_style_cascade_iter_clear (&iter);
return NULL;
}
@@ -236,6 +254,7 @@ gtk_style_cascade_lookup (GtkStyleProviderPrivate *provider,
g_warn_if_reached ();
}
}
+ gtk_style_cascade_iter_clear (&iter);
}
static void
@@ -303,8 +322,6 @@ _gtk_style_cascade_set_parent (GtkStyleCascade *cascade,
{
gtk_internal_return_if_fail (GTK_IS_STYLE_CASCADE (cascade));
gtk_internal_return_if_fail (parent == NULL || GTK_IS_STYLE_CASCADE (parent));
- if (parent)
- gtk_internal_return_if_fail (parent->parent == NULL);
if (cascade->parent == parent)
return;
diff --git a/testsuite/gtk/stylecontext.c b/testsuite/gtk/stylecontext.c
index cf0e0a2..6ae7ff9 100644
--- a/testsuite/gtk/stylecontext.c
+++ b/testsuite/gtk/stylecontext.c
@@ -1,5 +1,12 @@
#include <gtk/gtk.h>
+typedef struct {
+ GtkStyleContext *context;
+ GtkCssProvider *blue_provider;
+ GtkCssProvider *red_provider;
+ GtkCssProvider *green_provider;
+} PrioritiesFixture;
+
static void
test_parse_selectors (void)
{
@@ -362,6 +369,213 @@ test_style_classes (void)
g_object_unref (context);
}
+static void
+test_style_priorities_setup (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ GError *error = NULL;
+ f->blue_provider = gtk_css_provider_new ();
+ f->red_provider = gtk_css_provider_new ();
+ f->green_provider = gtk_css_provider_new ();
+ f->context = gtk_style_context_new ();
+ GtkWidgetPath *path = gtk_widget_path_new ();
+
+ gtk_css_provider_load_from_data (f->blue_provider, "* { color: blue; }", -1, &error);
+ g_assert_no_error (error);
+ gtk_css_provider_load_from_data (f->red_provider, "* { color: red; }", -1, &error);
+ g_assert_no_error (error);
+ gtk_css_provider_load_from_data (f->green_provider, "* { color: green; }", -1, &error);
+ g_assert_no_error (error);
+
+ gtk_widget_path_append_type (path, GTK_TYPE_WINDOW);
+ gtk_style_context_set_path (f->context, path);
+
+ gtk_widget_path_free (path);
+}
+
+static void
+test_style_priorities_teardown (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ g_object_unref (f->blue_provider);
+ g_object_unref (f->red_provider);
+ g_object_unref (f->green_provider);
+ g_object_unref (f->context);
+}
+
+static void
+test_style_priorities_equal (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ GdkRGBA color, ref_color;
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (f->blue_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+ gtk_style_context_add_provider (f->context, GTK_STYLE_PROVIDER (f->red_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+ /* When style providers are added to the screen as well as the style context
+ the one specific to the style context should take priority */
+ gdk_rgba_parse (&ref_color, "red");
+ gtk_style_context_get_color (f->context, gtk_style_context_get_state (f->context),
+ &color);
+
+ g_assert_true (gdk_rgba_equal (&ref_color, &color));
+}
+
+static void
+test_style_priorities_screen_only (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ GdkRGBA color, ref_color;
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (f->blue_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+ gdk_rgba_parse (&ref_color, "blue");
+ gtk_style_context_get_color (f->context, gtk_style_context_get_state (f->context),
+ &color);
+
+ g_assert_true (gdk_rgba_equal (&ref_color, &color));
+}
+
+static void
+test_style_priorities_context_only (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ GdkRGBA color, ref_color;
+
+ gtk_style_context_add_provider (f->context, GTK_STYLE_PROVIDER (f->red_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+ gdk_rgba_parse (&ref_color, "red");
+ gtk_style_context_get_color (f->context, gtk_style_context_get_state (f->context),
+ &color);
+
+ g_assert_true (gdk_rgba_equal (&ref_color, &color));
+}
+
+static void
+test_style_priorities_screen_higher (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ GdkRGBA color, ref_color;
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (f->blue_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER + 1);
+ gtk_style_context_add_provider (f->context, GTK_STYLE_PROVIDER (f->red_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+ gdk_rgba_parse (&ref_color, "blue");
+ gtk_style_context_get_color (f->context, gtk_style_context_get_state (f->context),
+ &color);
+
+ g_assert_true (gdk_rgba_equal (&ref_color, &color));
+}
+
+static void
+test_style_priorities_context_higher (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ GdkRGBA color, ref_color;
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (f->blue_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+ gtk_style_context_add_provider (f->context, GTK_STYLE_PROVIDER (f->red_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER + 1);
+
+ gdk_rgba_parse (&ref_color, "red");
+ gtk_style_context_get_color (f->context, gtk_style_context_get_state (f->context),
+ &color);
+
+ g_assert_true (gdk_rgba_equal (&ref_color, &color));
+}
+
+static void
+test_style_priorities_two_screen (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ GdkRGBA color, ref_color;
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (f->blue_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (f->red_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER + 1);
+
+ gdk_rgba_parse (&ref_color, "red");
+ gtk_style_context_get_color (f->context, gtk_style_context_get_state (f->context),
+ &color);
+
+ g_assert_true (gdk_rgba_equal (&ref_color, &color));
+}
+
+static void
+test_style_priorities_two_context (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ GdkRGBA color, ref_color;
+
+ gtk_style_context_add_provider (f->context, GTK_STYLE_PROVIDER (f->blue_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+ gtk_style_context_add_provider (f->context, GTK_STYLE_PROVIDER (f->red_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER + 1);
+
+ gdk_rgba_parse (&ref_color, "red");
+ gtk_style_context_get_color (f->context, gtk_style_context_get_state (f->context),
+ &color);
+
+ g_assert_true (gdk_rgba_equal (&ref_color, &color));
+}
+
+static void
+test_style_priorities_three_screen_higher (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ GdkRGBA color, ref_color;
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (f->blue_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (f->green_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER + 1);
+ gtk_style_context_add_provider (f->context, GTK_STYLE_PROVIDER (f->red_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+ gdk_rgba_parse (&ref_color, "green");
+ gtk_style_context_get_color (f->context, gtk_style_context_get_state (f->context),
+ &color);
+
+ g_assert_true (gdk_rgba_equal (&ref_color, &color));
+}
+
+static void
+test_style_priorities_three_context_higher (PrioritiesFixture *f,
+ gconstpointer unused)
+{
+ GdkRGBA color, ref_color;
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (f->blue_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+ gtk_style_context_add_provider (f->context, GTK_STYLE_PROVIDER (f->red_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+ gtk_style_context_add_provider (f->context, GTK_STYLE_PROVIDER (f->green_provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER + 1);
+
+ gdk_rgba_parse (&ref_color, "green");
+ gtk_style_context_get_color (f->context, gtk_style_context_get_state (f->context),
+ &color);
+
+ g_assert_true (gdk_rgba_equal (&ref_color, &color));
+}
+
int
main (int argc, char *argv[])
{
@@ -376,5 +590,21 @@ main (int argc, char *argv[])
g_test_add_func ("/style/widget-path-parent", test_widget_path_parent);
g_test_add_func ("/style/classes", test_style_classes);
+#define ADD_PRIORITIES_TEST(path, func) \
+ g_test_add ("/style/priorities/" path, PrioritiesFixture, NULL, test_style_priorities_setup, \
+ (func), test_style_priorities_teardown)
+
+ ADD_PRIORITIES_TEST ("equal", test_style_priorities_equal);
+ ADD_PRIORITIES_TEST ("screen-only", test_style_priorities_screen_only);
+ ADD_PRIORITIES_TEST ("context-only", test_style_priorities_context_only);
+ ADD_PRIORITIES_TEST ("screen-higher", test_style_priorities_screen_higher);
+ ADD_PRIORITIES_TEST ("context-higher", test_style_priorities_context_higher);
+ ADD_PRIORITIES_TEST ("two-screen", test_style_priorities_two_screen);
+ ADD_PRIORITIES_TEST ("two-context", test_style_priorities_two_context);
+ ADD_PRIORITIES_TEST ("three-screen-higher", test_style_priorities_three_screen_higher);
+ ADD_PRIORITIES_TEST ("three-context-higher", test_style_priorities_three_context_higher);
+
+#undef ADD_PRIORITIES_TEST
+
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]