diff --git a/gtk/Makefile.am b/gtk/Makefile.am index e8852d16a3..c976a61ca9 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -411,6 +411,7 @@ gtk_private_h_sources = \ gtkbuttonprivate.h \ gtkcellareaboxcontextprivate.h \ gtkcontainerprivate.h \ + gtkcsslookupprivate.h \ gtkcssparserprivate.h \ gtkcssproviderprivate.h \ gtkcsssectionprivate.h \ @@ -468,6 +469,7 @@ gtk_private_h_sources = \ gtkstylecontextprivate.h \ gtkstylepropertiesprivate.h \ gtkstylepropertyprivate.h \ + gtkstyleproviderprivate.h \ gtksymboliccolorprivate.h \ gtktextbtree.h \ gtktextbufferserialize.h \ @@ -582,6 +584,7 @@ gtk_base_c_sources = \ gtkcombobox.c \ gtkcomboboxtext.c \ gtkcontainer.c \ + gtkcsslookup.c \ gtkcssparser.c \ gtkcssprovider.c \ gtkcsssection.c \ @@ -708,6 +711,7 @@ gtk_base_c_sources = \ gtkstyleproperties.c \ gtkstyleproperty.c \ gtkstyleprovider.c \ + gtkstyleproviderprivate.c \ gtkswitch.c \ gtksymboliccolor.c \ gtktestutils.c \ diff --git a/gtk/gtkcsslookup.c b/gtk/gtkcsslookup.c new file mode 100644 index 0000000000..a1e4247283 --- /dev/null +++ b/gtk/gtkcsslookup.c @@ -0,0 +1,107 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2011 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gtkcsslookupprivate.h" + +#include "gtkstylepropertyprivate.h" +#include "gtkstylepropertiesprivate.h" + +struct _GtkCssLookup { + GtkBitmask *missing; + const GValue *values[1]; +}; + +GtkCssLookup * +_gtk_css_lookup_new (void) +{ + GtkCssLookup *lookup; + guint n = _gtk_style_property_get_count (); + + lookup = g_malloc0 (sizeof (GtkCssLookup) + sizeof (const GValue *) * n); + lookup->missing = _gtk_bitmask_new (); + _gtk_bitmask_invert_range (lookup->missing, 0, n); + + return lookup; +} + +void +_gtk_css_lookup_free (GtkCssLookup *lookup) +{ + g_return_if_fail (lookup != NULL); + + _gtk_bitmask_free (lookup->missing); + g_free (lookup); +} + +const GtkBitmask * +_gtk_css_lookup_get_missing (const GtkCssLookup *lookup) +{ + g_return_val_if_fail (lookup != NULL, NULL); + + return lookup->missing; +} + +gboolean +_gtk_css_lookup_is_missing (const GtkCssLookup *lookup, + guint id) +{ + g_return_val_if_fail (lookup != NULL, FALSE); + + return lookup->values[id] == NULL; +} + +void +_gtk_css_lookup_set (GtkCssLookup *lookup, + guint id, + const GValue *value) +{ + g_return_if_fail (lookup != NULL); + g_return_if_fail (_gtk_bitmask_get (lookup->missing, id)); + g_return_if_fail (value != NULL); + + _gtk_bitmask_set (lookup->missing, id, FALSE); + lookup->values[id] = value; +} + +GtkStyleProperties * +_gtk_css_lookup_resolve (GtkCssLookup *lookup) +{ + GtkStyleProperties *props; + guint i, n; + + g_return_val_if_fail (lookup != NULL, NULL); + + n = _gtk_style_property_get_count (); + props = gtk_style_properties_new (); + + for (i = 0; i < n; i++) + { + if (lookup->values[i] == NULL) + continue; + + _gtk_style_properties_set_property_by_property (props, + _gtk_style_property_get (i), + 0, + lookup->values[i]); + } + + return props; +} diff --git a/gtk/gtkcsslookupprivate.h b/gtk/gtkcsslookupprivate.h new file mode 100644 index 0000000000..b1d6d5e482 --- /dev/null +++ b/gtk/gtkcsslookupprivate.h @@ -0,0 +1,46 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2011 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GTK_CSS_LOOKUP_PRIVATE_H__ +#define __GTK_CSS_LOOKUP_PRIVATE_H__ + +#include +#include "gtk/gtkbitmaskprivate.h" +#include "gtk/gtkstyleproperties.h" + + +G_BEGIN_DECLS + +typedef struct _GtkCssLookup GtkCssLookup; + +GtkCssLookup * _gtk_css_lookup_new (void); +void _gtk_css_lookup_free (GtkCssLookup *lookup); + +const GtkBitmask * _gtk_css_lookup_get_missing (const GtkCssLookup *lookup); +gboolean _gtk_css_lookup_is_missing (const GtkCssLookup *lookup, + guint id); +void _gtk_css_lookup_set (GtkCssLookup *lookup, + guint id, + const GValue *value); +GtkStyleProperties * _gtk_css_lookup_resolve (GtkCssLookup *lookup); + + +G_END_DECLS + +#endif /* __GTK_CSS_LOOKUP_PRIVATE_H__ */ diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c index 8c5794f96d..84c5a24755 100644 --- a/gtk/gtkcssprovider.c +++ b/gtk/gtkcssprovider.c @@ -36,6 +36,7 @@ #include "gtkstylecontextprivate.h" #include "gtkstylepropertiesprivate.h" #include "gtkstylepropertyprivate.h" +#include "gtkstyleproviderprivate.h" #include "gtkbindings.h" #include "gtkmarshalers.h" #include "gtkprivate.h" @@ -995,6 +996,7 @@ static guint css_provider_signals[LAST_SIGNAL] = { 0 }; static void gtk_css_provider_finalize (GObject *object); static void gtk_css_style_provider_iface_init (GtkStyleProviderIface *iface); +static void gtk_css_style_provider_private_iface_init (GtkStyleProviderPrivateInterface *iface); static gboolean gtk_css_provider_load_internal (GtkCssProvider *css_provider, @@ -1011,7 +1013,9 @@ gtk_css_provider_error_quark (void) G_DEFINE_TYPE_EXTENDED (GtkCssProvider, gtk_css_provider, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER, - gtk_css_style_provider_iface_init)); + gtk_css_style_provider_iface_init) + G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE, + gtk_css_style_provider_private_iface_init)); static void gtk_css_provider_parsing_error (GtkCssProvider *provider, @@ -1515,6 +1519,80 @@ gtk_css_style_provider_iface_init (GtkStyleProviderIface *iface) iface->get_style_property = gtk_css_provider_get_style_property; } +static GtkSymbolicColor * +gtk_css_style_provider_get_color (GtkStyleProviderPrivate *provider, + const char *name) +{ + GtkCssProvider *css_provider = GTK_CSS_PROVIDER (provider); + + return g_hash_table_lookup (css_provider->priv->symbolic_colors, name); +} + +static void +gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider, + GtkWidgetPath *path, + GtkStateFlags state, + GtkCssLookup *lookup) +{ + GtkCssProvider *css_provider; + GtkCssProviderPrivate *priv; + guint l, length; + int i; + + css_provider = GTK_CSS_PROVIDER (provider); + priv = css_provider->priv; + length = gtk_widget_path_length (path); + + for (l = length; l > 0; l--) + { + for (i = priv->rulesets->len - 1; i >= 0; i--) + { + GtkCssRuleset *ruleset; + GHashTableIter iter; + gpointer key, val; + GtkStateFlags selector_state; + + ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i); + + if (ruleset->style == NULL) + continue; + + selector_state = _gtk_css_selector_get_state_flags (ruleset->selector); + if (l < length && (!ruleset->has_inherit || selector_state)) + continue; + + if ((selector_state & state) != selector_state) + continue; + + if (!gtk_css_ruleset_matches (ruleset, path, l)) + continue; + + g_hash_table_iter_init (&iter, ruleset->style); + + while (g_hash_table_iter_next (&iter, &key, &val)) + { + GtkStyleProperty *prop = key; + PropertyValue *value = val; + + if (l != length && !_gtk_style_property_is_inherit (prop)) + continue; + + if (!_gtk_css_lookup_is_missing (lookup, _gtk_style_property_get_id (prop))) + continue; + + _gtk_css_lookup_set (lookup, _gtk_style_property_get_id (prop), &value->value); + } + } + } +} + +static void +gtk_css_style_provider_private_iface_init (GtkStyleProviderPrivateInterface *iface) +{ + iface->get_color = gtk_css_style_provider_get_color; + iface->lookup = gtk_css_style_provider_lookup; +} + static void gtk_css_provider_finalize (GObject *object) { diff --git a/gtk/gtkmodifierstyle.c b/gtk/gtkmodifierstyle.c index d81b9bcb06..efb1008111 100644 --- a/gtk/gtkmodifierstyle.c +++ b/gtk/gtkmodifierstyle.c @@ -19,6 +19,7 @@ #include "config.h" #include "gtkmodifierstyle.h" +#include "gtkstyleproviderprivate.h" #include "gtkintl.h" typedef struct StylePropertyValue StylePropertyValue; @@ -36,12 +37,15 @@ enum { static guint signals [LAST_SIGNAL] = { 0 }; -static void gtk_modifier_style_provider_init (GtkStyleProviderIface *iface); -static void gtk_modifier_style_finalize (GObject *object); +static void gtk_modifier_style_provider_init (GtkStyleProviderIface *iface); +static void gtk_modifier_style_provider_private_init (GtkStyleProviderPrivateInterface *iface); +static void gtk_modifier_style_finalize (GObject *object); G_DEFINE_TYPE_EXTENDED (GtkModifierStyle, _gtk_modifier_style, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER, - gtk_modifier_style_provider_init)); + gtk_modifier_style_provider_init) + G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE, + gtk_modifier_style_provider_private_init)); static void _gtk_modifier_style_class_init (GtkModifierStyleClass *klass) @@ -131,6 +135,36 @@ gtk_modifier_style_provider_init (GtkStyleProviderIface *iface) iface->get_style_property = gtk_modifier_style_get_style_property; } +static GtkSymbolicColor * +gtk_modifier_style_provider_get_color (GtkStyleProviderPrivate *provider, + const char *name) +{ + GtkModifierStyle *style = GTK_MODIFIER_STYLE (provider); + + return _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (style->priv->style), name); +} + +static void +gtk_modifier_style_provider_lookup (GtkStyleProviderPrivate *provider, + GtkWidgetPath *path, + GtkStateFlags state, + GtkCssLookup *lookup) +{ + GtkModifierStyle *style = GTK_MODIFIER_STYLE (provider); + + _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (style->priv->style), + path, + state, + lookup); +} + +static void +gtk_modifier_style_provider_private_init (GtkStyleProviderPrivateInterface *iface) +{ + iface->get_color = gtk_modifier_style_provider_get_color; + iface->lookup = gtk_modifier_style_provider_lookup; +} + static void gtk_modifier_style_finalize (GObject *object) { diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index 508b4db234..ac90cdd602 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -32,6 +32,7 @@ #include "gtkwidget.h" #include "gtkprivate.h" #include "gtkcssproviderprivate.h" +#include "gtkstyleproviderprivate.h" #include "gtksymboliccolor.h" #include "gtktypebuiltins.h" #include "gtkversion.h" @@ -211,6 +212,7 @@ enum { /* --- prototypes --- */ static void gtk_settings_provider_iface_init (GtkStyleProviderIface *iface); +static void gtk_settings_provider_private_init (GtkStyleProviderPrivateInterface *iface); static void gtk_settings_finalize (GObject *object); static void gtk_settings_get_property (GObject *object, @@ -259,7 +261,9 @@ static guint class_n_properties = 0; G_DEFINE_TYPE_EXTENDED (GtkSettings, gtk_settings, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER, - gtk_settings_provider_iface_init)); + gtk_settings_provider_iface_init) + G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE, + gtk_settings_provider_private_init)); /* --- functions --- */ static void @@ -1450,6 +1454,40 @@ gtk_settings_provider_iface_init (GtkStyleProviderIface *iface) iface->get_style = gtk_settings_get_style; } +static GtkSymbolicColor * +gtk_settings_style_provider_get_color (GtkStyleProviderPrivate *provider, + const char *name) +{ + GtkSettings *settings = GTK_SETTINGS (provider); + + settings_ensure_style (settings); + + return _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (settings->priv->style), name); +} + +static void +gtk_settings_style_provider_lookup (GtkStyleProviderPrivate *provider, + GtkWidgetPath *path, + GtkStateFlags state, + GtkCssLookup *lookup) +{ + GtkSettings *settings = GTK_SETTINGS (provider); + + settings_ensure_style (settings); + + _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (settings->priv->style), + path, + state, + lookup); +} + +static void +gtk_settings_provider_private_init (GtkStyleProviderPrivateInterface *iface) +{ + iface->get_color = gtk_settings_style_provider_get_color; + iface->lookup = gtk_settings_style_provider_lookup; +} + static void gtk_settings_finalize (GObject *object) { diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c index d4f909a818..f4bd0d00f7 100644 --- a/gtk/gtkstylecontext.c +++ b/gtk/gtkstylecontext.c @@ -32,11 +32,12 @@ #include "gtkwidget.h" #include "gtkwindow.h" #include "gtkprivate.h" -#include "gtksymboliccolor.h" +#include "gtksymboliccolorprivate.h" #include "gtkanimationdescription.h" #include "gtktimeline.h" #include "gtkiconfactory.h" #include "gtkwidgetprivate.h" +#include "gtkstyleproviderprivate.h" /** * SECTION:gtkstylecontext @@ -371,6 +372,7 @@ struct _GtkStyleContextPrivate GHashTable *style_data; GSList *info_stack; StyleData *current_data; + GtkStateFlags current_state; GSList *animation_regions; GSList *animations; @@ -408,6 +410,9 @@ static void gtk_style_context_impl_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static GtkSymbolicColor * + gtk_style_context_color_lookup_func (gpointer contextp, + const char *name); G_DEFINE_TYPE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT) @@ -556,7 +561,6 @@ style_data_new (void) StyleData *data; data = g_slice_new0 (StyleData); - data->store = gtk_style_properties_new (); return data; } @@ -905,18 +909,25 @@ find_next_candidate (GList *local, static void build_properties (GtkStyleContext *context, StyleData *style_data, - GtkWidgetPath *path) + GtkWidgetPath *path, + GtkStateFlags state) { GtkStyleContextPrivate *priv; GList *elem, *list, *global_list = NULL; + GtkCssLookup *lookup; priv = context->priv; - list = priv->providers; + list = priv->providers_last; if (priv->screen) - global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark); + { + global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark); + global_list = g_list_last (global_list); + } - while ((elem = find_next_candidate (list, global_list, TRUE)) != NULL) + lookup = _gtk_css_lookup_new (); + + while ((elem = find_next_candidate (list, global_list, FALSE)) != NULL) { GtkStyleProviderData *data; GtkStyleProperties *provider_style; @@ -924,18 +935,37 @@ build_properties (GtkStyleContext *context, data = elem->data; if (elem == list) - list = list->next; + list = list->prev; else - global_list = global_list->next; + global_list = global_list->prev; - provider_style = gtk_style_provider_get_style (data->provider, path); - - if (provider_style) + if (GTK_IS_STYLE_PROVIDER_PRIVATE (data->provider)) { - gtk_style_properties_merge (style_data->store, provider_style, TRUE); - g_object_unref (provider_style); + _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (data->provider), + path, + state, + lookup); + } + else + { + provider_style = gtk_style_provider_get_style (data->provider, path); + + if (provider_style) + { + _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (provider_style), + path, + state, + lookup); + g_object_unref (provider_style); + } } } + + style_data->store = _gtk_css_lookup_resolve (lookup); + _gtk_style_properties_set_color_lookup_func (style_data->store, + gtk_style_context_color_lookup_func, + context); + _gtk_css_lookup_free (lookup); } static void @@ -1024,7 +1054,7 @@ style_data_lookup (GtkStyleContext *context, state_mismatch = ((GtkStyleInfo *) priv->info_stack->data)->state_flags != state; /* Current data in use is cached, just return it */ - if (priv->current_data && !state_mismatch) + if (priv->current_data && priv->current_state == state) return priv->current_data; g_assert (priv->widget_path != NULL); @@ -1044,7 +1074,7 @@ style_data_lookup (GtkStyleContext *context, data = style_data_new (); path = create_query_path (context); - build_properties (context, data, path); + build_properties (context, data, path, state); build_icon_factories (context, data, path); g_hash_table_insert (priv->style_data, @@ -1057,12 +1087,9 @@ style_data_lookup (GtkStyleContext *context, if (G_UNLIKELY (state_mismatch)) { gtk_style_context_restore (context); - priv->current_data = NULL; } else { - priv->current_data = data; - if (priv->theming_engine) g_object_unref (priv->theming_engine); @@ -1074,6 +1101,9 @@ style_data_lookup (GtkStyleContext *context, priv->theming_engine = g_object_ref (gtk_theming_engine_load (NULL)); } + priv->current_data = data; + priv->current_state = state; + return data; } @@ -1381,7 +1411,7 @@ gtk_style_context_get_property (GtkStyleContext *context, g_return_if_fail (priv->widget_path != NULL); data = style_data_lookup (context, state); - gtk_style_properties_get_property (data->store, property, state, value); + gtk_style_properties_get_property (data->store, property, 0, value); } void @@ -1399,7 +1429,7 @@ _gtk_style_context_get_valist (GtkStyleContext *context, g_return_if_fail (priv->widget_path != NULL); data = style_data_lookup (context, state); - _gtk_style_properties_get_valist (data->store, state, property_context, args); + _gtk_style_properties_get_valist (data->store, 0, property_context, args); } /** @@ -1426,7 +1456,7 @@ gtk_style_context_get_valist (GtkStyleContext *context, g_return_if_fail (priv->widget_path != NULL); data = style_data_lookup (context, state); - gtk_style_properties_get_valist (data->store, state, args); + gtk_style_properties_get_valist (data->store, 0, args); } /** @@ -1457,7 +1487,7 @@ gtk_style_context_get (GtkStyleContext *context, data = style_data_lookup (context, state); va_start (args, state); - gtk_style_properties_get_valist (data->store, state, args); + gtk_style_properties_get_valist (data->store, 0, args); va_end (args); } @@ -2688,6 +2718,51 @@ gtk_style_context_get_junction_sides (GtkStyleContext *context) return info->junction_sides; } +static GtkSymbolicColor * +gtk_style_context_color_lookup_func (gpointer contextp, + const char *name) +{ + GtkSymbolicColor *sym_color; + GtkStyleContext *context = contextp; + GtkStyleContextPrivate *priv = context->priv; + GList *elem, *list, *global_list = NULL; + + list = priv->providers_last; + if (priv->screen) + { + global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark); + global_list = g_list_last (global_list); + } + + sym_color = NULL; + + while (sym_color == NULL && + (elem = find_next_candidate (list, global_list, FALSE)) != NULL) + { + GtkStyleProviderData *data; + + data = elem->data; + + if (elem == list) + list = list->prev; + else + global_list = global_list->prev; + + if (GTK_IS_STYLE_PROVIDER_PRIVATE (data->provider)) + { + sym_color = _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (data->provider), + name); + } + else + { + /* If somebody hits this code path, shout at them */ + sym_color = NULL; + } + } + + return sym_color; +} + /** * gtk_style_context_lookup_color: * @context: a #GtkStyleContext @@ -2703,24 +2778,20 @@ gtk_style_context_lookup_color (GtkStyleContext *context, const gchar *color_name, GdkRGBA *color) { - GtkStyleContextPrivate *priv; GtkSymbolicColor *sym_color; - StyleData *data; g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE); g_return_val_if_fail (color_name != NULL, FALSE); g_return_val_if_fail (color != NULL, FALSE); - priv = context->priv; - g_return_val_if_fail (priv->widget_path != NULL, FALSE); - - data = style_data_lookup (context, 0); - sym_color = gtk_style_properties_lookup_color (data->store, color_name); - - if (!sym_color) + sym_color = gtk_style_context_color_lookup_func (context, color_name); + if (sym_color == NULL) return FALSE; - return gtk_symbolic_color_resolve (sym_color, data->store, color); + return _gtk_symbolic_color_resolve_full (sym_color, + gtk_style_context_color_lookup_func, + context, + color); } /** @@ -2827,8 +2898,8 @@ gtk_style_context_notify_state_change (GtkStyleContext *context, /* Find out if there is any animation description for the given * state, it will fallback to the normal state as well if necessary. */ - data = style_data_lookup (context, state); - gtk_style_properties_get (data->store, flags, + data = style_data_lookup (context, flags); + gtk_style_properties_get (data->store, 0, "transition", &desc, NULL); @@ -3374,7 +3445,7 @@ gtk_style_context_get_border (GtkStyleContext *context, data = style_data_lookup (context, state); gtk_style_properties_get (data->store, - state, + 0, "border-style", &border_style, "border-top-width", &top, "border-top-width", &top, @@ -3426,7 +3497,7 @@ gtk_style_context_get_padding (GtkStyleContext *context, data = style_data_lookup (context, state); gtk_style_properties_get (data->store, - state, + 0, "padding-top", &top, "padding-left", &left, "padding-bottom", &bottom, @@ -3467,7 +3538,7 @@ gtk_style_context_get_margin (GtkStyleContext *context, data = style_data_lookup (context, state); gtk_style_properties_get (data->store, - state, + 0, "margin-top", &top, "margin-left", &left, "margin-bottom", &bottom, @@ -3530,7 +3601,7 @@ gtk_style_context_get_font (GtkStyleContext *context, if (description == NULL) { - gtk_style_properties_get (data->store, state, "font", &description, NULL); + gtk_style_properties_get (data->store, 0, "font", &description, NULL); g_hash_table_insert (font_cache, GUINT_TO_POINTER (state), description); } diff --git a/gtk/gtkstyleproperties.c b/gtk/gtkstyleproperties.c index 5470bf5829..f2b6b7d23c 100644 --- a/gtk/gtkstyleproperties.c +++ b/gtk/gtkstyleproperties.c @@ -35,6 +35,7 @@ #include "gtkborderimageprivate.h" #include "gtkstylepropertyprivate.h" +#include "gtkstyleproviderprivate.h" #include "gtkintl.h" #include "gtkwin32themeprivate.h" @@ -76,15 +77,20 @@ struct _GtkStylePropertiesPrivate { GHashTable *color_map; GHashTable *properties; + GtkSymbolicColorLookupFunc color_lookup_func; + gpointer color_lookup_data; }; -static void gtk_style_properties_provider_init (GtkStyleProviderIface *iface); -static void gtk_style_properties_finalize (GObject *object); +static void gtk_style_properties_provider_init (GtkStyleProviderIface *iface); +static void gtk_style_properties_provider_private_init (GtkStyleProviderPrivateInterface *iface); +static void gtk_style_properties_finalize (GObject *object); G_DEFINE_TYPE_EXTENDED (GtkStyleProperties, gtk_style_properties, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER, - gtk_style_properties_provider_init)); + gtk_style_properties_provider_init) + G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE, + gtk_style_properties_provider_private_init)); static void gtk_style_properties_class_init (GtkStylePropertiesClass *klass) @@ -293,6 +299,57 @@ gtk_style_properties_provider_init (GtkStyleProviderIface *iface) iface->get_style = gtk_style_properties_get_style; } +static GtkSymbolicColor * +gtk_style_properties_provider_get_color (GtkStyleProviderPrivate *provider, + const char *name) +{ + return gtk_style_properties_lookup_color (GTK_STYLE_PROPERTIES (provider), name); +} + +static void +gtk_style_properties_provider_lookup (GtkStyleProviderPrivate *provider, + GtkWidgetPath *path, + GtkStateFlags state, + GtkCssLookup *lookup) +{ + GtkStyleProperties *props; + GtkStylePropertiesPrivate *priv; + GHashTableIter iter; + gpointer key, value; + + props = GTK_STYLE_PROPERTIES (provider); + priv = props->priv; + + /* Merge symbolic style properties */ + g_hash_table_iter_init (&iter, priv->properties); + + while (g_hash_table_iter_next (&iter, &key, &value)) + { + GtkStyleProperty *prop = key; + PropertyData *data = value; + const GValue *value; + guint id; + + id = _gtk_style_property_get_id (prop); + + if (!_gtk_css_lookup_is_missing (lookup, id)) + continue; + + value = property_data_match_state (data, state); + if (value == NULL) + continue; + + _gtk_css_lookup_set (lookup, id, value); + } +} + +static void +gtk_style_properties_provider_private_init (GtkStyleProviderPrivateInterface *iface) +{ + iface->get_color = gtk_style_properties_provider_get_color; + iface->lookup = gtk_style_properties_provider_lookup; +} + /* Property registration functions */ /** diff --git a/gtk/gtkstylepropertiesprivate.h b/gtk/gtkstylepropertiesprivate.h index 3465270e4f..5da461717f 100644 --- a/gtk/gtkstylepropertiesprivate.h +++ b/gtk/gtkstylepropertiesprivate.h @@ -23,6 +23,7 @@ #include "gtkstyleproperties.h" #include "gtkstylepropertyprivate.h" #include "gtkstylecontextprivate.h" +#include "gtksymboliccolorprivate.h" G_BEGIN_DECLS diff --git a/gtk/gtkstyleproperty.c b/gtk/gtkstyleproperty.c index 681acf6de7..fee3bba0e4 100644 --- a/gtk/gtkstyleproperty.c +++ b/gtk/gtkstyleproperty.c @@ -52,7 +52,7 @@ static GHashTable *parse_funcs = NULL; static GHashTable *print_funcs = NULL; static GHashTable *properties = NULL; -static guint __n_style_properties = 0; +static GPtrArray *__style_property_array = NULL; static void register_conversion_function (GType type, @@ -2244,7 +2244,25 @@ border_color_default_value (GtkStyleProperties *props, guint _gtk_style_property_get_count (void) { - return __n_style_properties; + return __style_property_array ? __style_property_array->len : 0; +} + +const GtkStyleProperty * +_gtk_style_property_get (guint id) +{ + g_assert (__style_property_array); + + return g_ptr_array_index (__style_property_array, id); +} + +static void +_gtk_style_property_generate_id (GtkStyleProperty *node) +{ + if (__style_property_array == NULL) + __style_property_array = g_ptr_array_new (); + + node->id = __style_property_array->len; + g_ptr_array_add (__style_property_array, node); } static void @@ -3145,7 +3163,6 @@ _gtk_style_property_register (GParamSpec *pspec, node = g_slice_new0 (GtkStyleProperty); node->flags = flags; - node->id = __n_style_properties++; node->pspec = pspec; node->property_parse_func = property_parse_func; node->pack_func = pack_func; @@ -3155,6 +3172,9 @@ _gtk_style_property_register (GParamSpec *pspec, node->default_value_func = default_value_func; node->unset_func = unset_func; + if (!_gtk_style_property_is_shorthand (node)) + _gtk_style_property_generate_id (node); + /* pspec owns name */ g_hash_table_insert (properties, (gchar *)pspec->name, node); } diff --git a/gtk/gtkstylepropertyprivate.h b/gtk/gtkstylepropertyprivate.h index fc52ae51cb..6cabf25d4b 100644 --- a/gtk/gtkstylepropertyprivate.h +++ b/gtk/gtkstylepropertyprivate.h @@ -64,6 +64,7 @@ struct _GtkStyleProperty }; guint _gtk_style_property_get_count (void); +const GtkStyleProperty * _gtk_style_property_get (guint id); const GtkStyleProperty * _gtk_style_property_lookup (const char *name); diff --git a/gtk/gtkstyleproviderprivate.c b/gtk/gtkstyleproviderprivate.c new file mode 100644 index 0000000000..a7b0a6fcb7 --- /dev/null +++ b/gtk/gtkstyleproviderprivate.c @@ -0,0 +1,66 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2011 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "gtkstyleproviderprivate.h" +#include "gtkstyleprovider.h" + +G_DEFINE_INTERFACE (GtkStyleProviderPrivate, _gtk_style_provider_private, GTK_TYPE_STYLE_PROVIDER) + +static void +_gtk_style_provider_private_default_init (GtkStyleProviderPrivateInterface *iface) +{ +} + +GtkSymbolicColor * +_gtk_style_provider_private_get_color (GtkStyleProviderPrivate *provider, + const char *name) +{ + GtkStyleProviderPrivateInterface *iface; + + g_return_val_if_fail (GTK_IS_STYLE_PROVIDER_PRIVATE (provider), NULL); + + iface = GTK_STYLE_PROVIDER_PRIVATE_GET_INTERFACE (provider); + + if (!iface->get_color) + return NULL; + + return iface->get_color (provider, name); +} + +void +_gtk_style_provider_private_lookup (GtkStyleProviderPrivate *provider, + GtkWidgetPath *path, + GtkStateFlags state, + GtkCssLookup *lookup) +{ + GtkStyleProviderPrivateInterface *iface; + + g_return_if_fail (GTK_IS_STYLE_PROVIDER_PRIVATE (provider)); + g_return_if_fail (path != NULL); + g_return_if_fail (lookup != NULL); + + iface = GTK_STYLE_PROVIDER_PRIVATE_GET_INTERFACE (provider); + + if (!iface->lookup) + return; + + iface->lookup (provider, path, state, lookup); +} diff --git a/gtk/gtkstyleproviderprivate.h b/gtk/gtkstyleproviderprivate.h new file mode 100644 index 0000000000..c2d5421dd1 --- /dev/null +++ b/gtk/gtkstyleproviderprivate.h @@ -0,0 +1,62 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2011 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GTK_STYLE_PROVIDER_PRIVATE_H__ +#define __GTK_STYLE_PROVIDER_PRIVATE_H__ + +#include +#include "gtk/gtkcsslookupprivate.h" +#include +#include +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_STYLE_PROVIDER_PRIVATE (_gtk_style_provider_private_get_type ()) +#define GTK_STYLE_PROVIDER_PRIVATE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_STYLE_PROVIDER_PRIVATE, GtkStyleProviderPrivate)) +#define GTK_IS_STYLE_PROVIDER_PRIVATE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_STYLE_PROVIDER_PRIVATE)) +#define GTK_STYLE_PROVIDER_PRIVATE_GET_INTERFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), GTK_TYPE_STYLE_PROVIDER_PRIVATE, GtkStyleProviderPrivateInterface)) + +typedef struct _GtkStyleProviderPrivateInterface GtkStyleProviderPrivateInterface; +typedef struct _GtkStyleProviderPrivate GtkStyleProviderPrivate; /* dummy typedef */ + +struct _GtkStyleProviderPrivateInterface +{ + GTypeInterface g_iface; + + GtkSymbolicColor * (* get_color) (GtkStyleProviderPrivate *provider, + const char *name); + void (* lookup) (GtkStyleProviderPrivate *provider, + GtkWidgetPath *path, + GtkStateFlags state, + GtkCssLookup *lookup); +}; + +GType _gtk_style_provider_private_get_type (void) G_GNUC_CONST; + +GtkSymbolicColor * _gtk_style_provider_private_get_color (GtkStyleProviderPrivate *provider, + const char *name); +void _gtk_style_provider_private_lookup (GtkStyleProviderPrivate *provider, + GtkWidgetPath *path, + GtkStateFlags state, + GtkCssLookup *lookup); + +G_END_DECLS + +#endif /* __GTK_STYLE_PROVIDER_PRIVATE_H__ */