forked from AuroraMiddleware/gtk
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
This commit is contained in:
parent
1c6b878e09
commit
76bacfde6e
@ -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)
|
||||
GtkStyleCascade *cas;
|
||||
int ix, highest_priority_index = 0;
|
||||
GtkStyleProviderData *highest_priority_data = NULL;
|
||||
|
||||
for (cas = cascade, ix = 0; ix < iter->n_cascades; cas = cas->parent, ix++)
|
||||
{
|
||||
if (iter->index > 0)
|
||||
{
|
||||
GtkStyleProviderData *data, *parent_data;
|
||||
if (iter->cascade_index[ix] <= 0)
|
||||
continue;
|
||||
|
||||
data = &g_array_index (cascade->providers, GtkStyleProviderData, iter->index - 1);
|
||||
parent_data = &g_array_index (cascade->parent->providers, GtkStyleProviderData, iter->parent_index - 1);
|
||||
|
||||
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;
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user