From 42a4bd1c5b8e1721ac25d3ed08481113a4a26f71 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 21 May 2011 23:47:19 +0200 Subject: [PATCH] style: Add support for shorthand properties Shorthand properties are basically the same a in CSS. For storage in style properties or the CSS provider, they are unpacked into the real values, so it is possible to partially override them. No properties are yet converted to the new world yet, this is just the code for supporting them. --- gtk/gtkcssprovider.c | 20 ++++++++++++++++ gtk/gtkstyleproperties.c | 35 +++++++++++++++++++++++++++- gtk/gtkstyleproperty.c | 43 ++++++++++++++++++++++++++++++++++- gtk/gtkstylepropertyprivate.h | 23 +++++++++++++++++-- 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c index 4f09c5e939..6f8cbe4710 100644 --- a/gtk/gtkcssprovider.c +++ b/gtk/gtkcssprovider.c @@ -1000,6 +1000,26 @@ gtk_css_ruleset_add (GtkCssRuleset *ruleset, NULL, (GDestroyNotify) property_value_free); + if (_gtk_style_property_is_shorthand (prop)) + { + GParameter *parameters; + guint i, n_parameters; + + parameters = _gtk_style_property_unpack (prop, value, &n_parameters); + + for (i = 0; i < n_parameters; i++) + { + const GtkStyleProperty *child; + GValue *value; + + child = _gtk_style_property_lookup (parameters[i].name); + value = g_memdup (¶meters[i].value, sizeof (GValue)); + gtk_css_ruleset_add (ruleset, child, value); + } + g_free (parameters); + return; + } + ruleset->has_inherit |= gtk_style_param_get_inherit (prop->pspec); g_hash_table_insert (ruleset->style, (gpointer) prop, value); } diff --git a/gtk/gtkstyleproperties.c b/gtk/gtkstyleproperties.c index 1c5f0d9565..a2cb8e53e6 100644 --- a/gtk/gtkstyleproperties.c +++ b/gtk/gtkstyleproperties.c @@ -311,7 +311,9 @@ gtk_style_properties_register_property (GtkStylePropertyParser parse_func, g_return_if_fail (G_IS_PARAM_SPEC (pspec)); _gtk_style_property_register (pspec, - parse_func); + parse_func, + NULL, + NULL); } /** @@ -511,6 +513,25 @@ _gtk_style_properties_set_property_by_property (GtkStyleProperties *props, else g_return_if_fail (style_prop->pspec->value_type == value_type); + if (_gtk_style_property_is_shorthand (style_prop)) + { + GParameter *parameters; + guint i, n_parameters; + + parameters = _gtk_style_property_unpack (style_prop, value, &n_parameters); + + for (i = 0; i < n_parameters; i++) + { + gtk_style_properties_set_property (props, + parameters[i].name, + state, + ¶meters[i].value); + g_value_unset (¶meters[i].value); + } + g_free (parameters); + return; + } + priv = props->priv; prop = g_hash_table_lookup (priv->properties, style_prop->pspec); @@ -789,6 +810,7 @@ lookup_default_value (const GtkStyleProperty *node, g_param_value_set_default (node->pspec, value); } +/* NB: Will return NULL for shorthands */ const GValue * _gtk_style_properties_peek_property (GtkStyleProperties *props, const gchar *prop_name, @@ -864,6 +886,8 @@ gtk_style_properties_get_property (GtkStyleProperties *props, if (val) g_value_copy (val, value); + else if (_gtk_style_property_is_shorthand (node)) + _gtk_style_property_pack (node, props, state, value); else lookup_default_value (node, value); @@ -907,6 +931,15 @@ gtk_style_properties_get_valist (GtkStyleProperties *props, { G_VALUE_LCOPY (val, args, 0, &error); } + else if (_gtk_style_property_is_shorthand (node)) + { + GValue packed = { 0 }; + + g_value_init (&packed, node->pspec->value_type); + _gtk_style_property_pack (node, props, state, &packed); + G_VALUE_LCOPY (&packed, args, 0, &error); + g_value_unset (&packed); + } else { GValue default_value = { 0 }; diff --git a/gtk/gtkstyleproperty.c b/gtk/gtkstyleproperty.c index 022e57741a..2d6bda681a 100644 --- a/gtk/gtkstyleproperty.c +++ b/gtk/gtkstyleproperty.c @@ -1281,6 +1281,41 @@ _gtk_css_value_to_string (const GValue *value) return g_strdup_value_contents (value); } +gboolean +_gtk_style_property_is_shorthand (const GtkStyleProperty *property) +{ + g_return_val_if_fail (property != NULL, FALSE); + + return property->pack_func != NULL; +} + +GParameter * +_gtk_style_property_unpack (const GtkStyleProperty *property, + const GValue *value, + guint *n_params) +{ + g_return_val_if_fail (property != NULL, NULL); + g_return_val_if_fail (property->unpack_func != NULL, NULL); + g_return_val_if_fail (value != NULL, NULL); + g_return_val_if_fail (n_params != NULL, NULL); + + return property->unpack_func (value, n_params); +} + +void +_gtk_style_property_pack (const GtkStyleProperty *property, + GtkStyleProperties *props, + GtkStateFlags state, + GValue *value) +{ + g_return_if_fail (property != NULL); + g_return_if_fail (property->pack_func != NULL); + g_return_if_fail (GTK_IS_STYLE_PROPERTIES (props)); + g_return_if_fail (G_IS_VALUE (value)); + + property->pack_func (value, props, state); +} + static void gtk_style_property_init (void) { @@ -1392,11 +1427,15 @@ _gtk_style_property_lookup (const char *name) void _gtk_style_property_register (GParamSpec *pspec, - GtkStylePropertyParser parse_func) + GtkStylePropertyParser parse_func, + GtkStyleUnpackFunc unpack_func, + GtkStylePackFunc pack_func) { const GtkStyleProperty *existing; GtkStyleProperty *node; + g_return_if_fail ((pack_func == NULL) == (unpack_func == NULL)); + gtk_style_property_init (); existing = _gtk_style_property_lookup (pspec->name); @@ -1410,6 +1449,8 @@ _gtk_style_property_register (GParamSpec *pspec, node = g_slice_new0 (GtkStyleProperty); node->pspec = pspec; node->parse_func = parse_func; + node->pack_func = pack_func; + node->unpack_func = unpack_func; g_hash_table_insert (properties, pspec->name, node); } diff --git a/gtk/gtkstylepropertyprivate.h b/gtk/gtkstylepropertyprivate.h index 57dd0d98df..38850a19e7 100644 --- a/gtk/gtkstylepropertyprivate.h +++ b/gtk/gtkstylepropertyprivate.h @@ -26,16 +26,35 @@ G_BEGIN_DECLS typedef struct _GtkStyleProperty GtkStyleProperty; +typedef GParameter * (* GtkStyleUnpackFunc) (const GValue *value, + guint *n_params); +typedef void (* GtkStylePackFunc) (GValue *value, + GtkStyleProperties *props, + GtkStateFlags flags); + struct _GtkStyleProperty { GParamSpec *pspec; GtkStylePropertyParser parse_func; + GtkStyleUnpackFunc unpack_func; + GtkStylePackFunc pack_func; }; -const GtkStyleProperty * _gtk_style_property_lookup (const char *name); +const GtkStyleProperty * _gtk_style_property_lookup (const char *name); void _gtk_style_property_register (GParamSpec *pspec, - GtkStylePropertyParser parse_func); + GtkStylePropertyParser parse_func, + GtkStyleUnpackFunc unpack_func, + GtkStylePackFunc pack_func); + +gboolean _gtk_style_property_is_shorthand (const GtkStyleProperty *property); +GParameter * _gtk_style_property_unpack (const GtkStyleProperty *property, + const GValue *value, + guint *n_params); +void _gtk_style_property_pack (const GtkStyleProperty *property, + GtkStyleProperties *props, + GtkStateFlags state, + GValue *value); gboolean _gtk_css_value_parse (GValue *value, GtkCssParser *parser,