[gtk+] style: Add support for shorthand properties



commit 42a4bd1c5b8e1721ac25d3ed08481113a4a26f71
Author: Benjamin Otte <otte redhat com>
Date:   Sat May 21 23:47:19 2011 +0200

    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 4f09c5e..6f8cbe4 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 (&parameters[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 1c5f0d9..a2cb8e5 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,
+                                             &parameters[i].value);
+          g_value_unset (&parameters[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 022e577..2d6bda6 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 57dd0d9..38850a1 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,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]