[gtk+] GtkStyleProperties: Use GParamSpec for properties registration.



commit 62ee0956e310a482d53e40258f021a5f9b4a1cec
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sat Nov 13 19:53:36 2010 +0100

    GtkStyleProperties: Use GParamSpec for properties registration.

 gtk/gtkcssprovider.c     |    8 +-
 gtk/gtkstyleproperties.c |  226 +++++++++++++++++++++++++++++-----------------
 gtk/gtkstyleproperties.h |   12 +--
 gtk/gtkthemingengine.c   |   55 +++++-------
 gtk/gtkthemingengine.h   |   10 +--
 5 files changed, 178 insertions(+), 133 deletions(-)
---
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index 0f220e3..1b856c3 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -2758,7 +2758,7 @@ parse_rule (GtkCssProvider *css_provider,
     {
       const gchar *value_str = NULL;
       GtkStylePropertyParser parse_func = NULL;
-      GType prop_type;
+      GParamSpec *pspec;
       GError *error = NULL;
       gchar *prop;
 
@@ -2782,19 +2782,19 @@ parse_rule (GtkCssProvider *css_provider,
 
       value_str = g_strstrip (scanner->value.v_identifier);
 
-      if (gtk_style_properties_lookup_property (prop, &prop_type, &parse_func))
+      if (gtk_style_properties_lookup_property (prop, &parse_func, &pspec))
         {
           GValue *val;
 
           val = g_slice_new0 (GValue);
-          g_value_init (val, prop_type);
+          g_value_init (val, pspec->value_type);
 
           if (strcmp (value_str, "none") == 0)
             {
               /* Remove/unset the current value */
               g_hash_table_remove (priv->cur_properties, prop);
             }
-          else if (prop_type == G_TYPE_STRING)
+          else if (pspec->value_type == G_TYPE_STRING)
             {
               g_value_set_string (val, value_str);
               g_hash_table_insert (priv->cur_properties, prop, val);
diff --git a/gtk/gtkstyleproperties.c b/gtk/gtkstyleproperties.c
index d5cc2b7..3adad1f 100644
--- a/gtk/gtkstyleproperties.c
+++ b/gtk/gtkstyleproperties.c
@@ -40,8 +40,7 @@ typedef struct ValueData ValueData;
 struct PropertyNode
 {
   GQuark property_quark;
-  GType property_type;
-  GValue default_value;
+  GParamSpec *pspec;
   GtkStylePropertyParser parse_func;
 };
 
@@ -76,33 +75,78 @@ static void
 gtk_style_properties_class_init (GtkStylePropertiesClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GValue val = { 0 };
 
   object_class->finalize = gtk_style_properties_finalize;
 
   /* Initialize default property set */
-  gtk_style_properties_register_property ("color", GDK_TYPE_RGBA, NULL, NULL);
-  gtk_style_properties_register_property ("background-color", GDK_TYPE_RGBA, NULL, NULL);
-
-  gtk_style_properties_register_property ("font", PANGO_TYPE_FONT_DESCRIPTION, NULL, NULL);
-
-  gtk_style_properties_register_property ("margin", GTK_TYPE_BORDER, NULL, NULL);
-  gtk_style_properties_register_property ("padding", GTK_TYPE_BORDER, NULL, NULL);
-
-  gtk_style_properties_register_property ("border-width", G_TYPE_INT, NULL, NULL);
-  gtk_style_properties_register_property ("border-radius", G_TYPE_INT, NULL, NULL);
-  gtk_style_properties_register_property ("border-style", GTK_TYPE_BORDER_STYLE, NULL, NULL);
-  gtk_style_properties_register_property ("border-color", GDK_TYPE_RGBA, NULL, NULL);
-
-  gtk_style_properties_register_property ("background-image", CAIRO_GOBJECT_TYPE_PATTERN, NULL, NULL);
-  gtk_style_properties_register_property ("border-image", GTK_TYPE_9SLICE, NULL, NULL);
-
-  g_value_init (&val, GTK_TYPE_THEMING_ENGINE);
-  g_value_set_object (&val, (GObject *) gtk_theming_engine_load (NULL));
-  gtk_style_properties_register_property ("engine", GTK_TYPE_THEMING_ENGINE, &val, NULL);
-  g_value_unset (&val);
-
-  gtk_style_properties_register_property ("transition", GTK_TYPE_ANIMATION_DESCRIPTION, NULL, NULL);
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("color",
+                                                              "Foreground color",
+                                                              "Foreground color",
+                                                              GDK_TYPE_RGBA, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("background-color",
+                                                              "Background color",
+                                                              "Background color",
+                                                              GDK_TYPE_RGBA, 0));
+
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("font",
+                                                              "Font Description",
+                                                              "Font Description",
+                                                              PANGO_TYPE_FONT_DESCRIPTION, 0));
+
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("margin",
+                                                              "Margin",
+                                                              "Margin",
+                                                              GTK_TYPE_BORDER, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("padding",
+                                                              "Padding",
+                                                              "Padding",
+                                                              GTK_TYPE_BORDER, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_int ("border-width",
+                                                            "Border width",
+                                                            "Border width, in pixels",
+                                                            0, G_MAXINT, 0, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_int ("border-radius",
+                                                            "Border radius",
+                                                            "Border radius, in pixels",
+                                                            0, G_MAXINT, 0, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_enum ("border-style",
+                                                             "Border style",
+                                                             "Border style",
+                                                             GTK_TYPE_BORDER_STYLE,
+                                                             GTK_BORDER_STYLE_NONE, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("border-color",
+                                                              "Border color",
+                                                              "Border color",
+                                                              GDK_TYPE_RGBA, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("background-image",
+                                                              "Background Image",
+                                                              "Background Image",
+                                                              CAIRO_GOBJECT_TYPE_PATTERN, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("border-image",
+                                                              "Border Image",
+                                                              "Border Image",
+                                                              GTK_TYPE_9SLICE, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_object ("engine",
+                                                               "Theming Engine",
+                                                               "Theming Engine",
+                                                               GTK_TYPE_THEMING_ENGINE, 0));
+  gtk_style_properties_register_property (NULL,
+                                          g_param_spec_boxed ("transition",
+                                                              "Transition animation description",
+                                                              "Transition animation description",
+                                                              GTK_TYPE_ANIMATION_DESCRIPTION, 0));
 
   g_type_class_add_private (object_class, sizeof (GtkStylePropertiesPrivate));
 }
@@ -198,7 +242,6 @@ property_data_get_value (PropertyData  *data,
     {
       ValueData new = { 0 };
 
-      //val_data = &g_array_index (data->values, ValueData, pos);
       new.state = state;
       g_array_insert_val (data->values, pos, new);
     }
@@ -333,10 +376,8 @@ property_node_lookup (GQuark quark)
 
 /**
  * gtk_style_properties_register_property:
- * @property_name: property name to register
- * @type: #GType the property will hold
- * @default_value: default value for this property
  * @parse_func: parsing function to use, or %NULL
+ * @pspec: the #GParamSpec for the new property
  *
  * Registers a property so it can be used in the CSS file format.
  * This function is the low-level equivalent of
@@ -346,42 +387,29 @@ property_node_lookup (GQuark quark)
  * Since: 3.0
  **/
 void
-gtk_style_properties_register_property (const gchar            *property_name,
-                                        GType                   type,
-                                        const GValue           *default_value,
-                                        GtkStylePropertyParser  parse_func)
+gtk_style_properties_register_property (GtkStylePropertyParser  parse_func,
+                                        GParamSpec             *pspec)
 {
   PropertyNode *node, new = { 0 };
   GQuark quark;
   gint i;
 
-  g_return_if_fail (property_name != NULL);
-  g_return_if_fail (type != 0);
+  g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
   if (G_UNLIKELY (!properties))
     properties = g_array_new (FALSE, TRUE, sizeof (PropertyNode));
 
-  quark = g_quark_try_string (property_name);
+  quark = g_quark_from_string (pspec->name);
 
   if ((node = property_node_lookup (quark)) != NULL)
     {
       g_warning ("Property \"%s\" was already registered with type %s",
-                 property_name, g_type_name (node->property_type));
+                 pspec->name, g_type_name (node->pspec->value_type));
       return;
     }
 
-  quark = g_quark_from_string (property_name);
-
   new.property_quark = quark;
-  new.property_type = type;
-
-  if (default_value)
-    {
-      g_value_init (&new.default_value, G_VALUE_TYPE (default_value));
-      g_value_copy (default_value, &new.default_value);
-    }
-  else
-    g_value_init (&new.default_value, type);
+  new.pspec = pspec;
 
   if (parse_func)
     new.parse_func = parse_func;
@@ -400,11 +428,11 @@ gtk_style_properties_register_property (const gchar            *property_name,
 /**
  * gtk_style_properties_lookup_property:
  * @property_name: property name to look up
- * @type: (out): return location for the looked up property type
- * @parse_func: (out): return value for the parse function
+ * @parse_func: (out): return location for the parse function
+ * @pspec: (out): return location for the #GParamSpec
  *
- * Returns %TRUE if a property has been registered, if @type or
- * @parse_func are not %NULL, the property #GType and parsing function
+ * Returns %TRUE if a property has been registered, if @pspec or
+ * @parse_func are not %NULL, the #GParamSpec and parsing function
  * will be respectively returned.
  *
  * Returns: %TRUE if the property is registered, %FALSE otherwise
@@ -412,9 +440,9 @@ gtk_style_properties_register_property (const gchar            *property_name,
  * Since: 3.0
  **/
 gboolean
-gtk_style_properties_lookup_property (const gchar            *property_name,
-                                      GType                  *type,
-                                      GtkStylePropertyParser *parse_func)
+gtk_style_properties_lookup_property (const gchar             *property_name,
+                                      GtkStylePropertyParser  *parse_func,
+                                      GParamSpec             **pspec)
 {
   PropertyNode *node;
   GtkStylePropertiesClass *klass;
@@ -439,8 +467,8 @@ gtk_style_properties_lookup_property (const gchar            *property_name,
 
       if (node->property_quark == quark)
         {
-          if (type)
-            *type = node->property_type;
+          if (pspec)
+            *pspec = node->pspec;
 
           if (parse_func)
             *parse_func = node->parse_func;
@@ -572,22 +600,22 @@ gtk_style_properties_set_property (GtkStyleProperties *props,
       return;
     }
 
-  if (node->property_type == GDK_TYPE_RGBA ||
-      node->property_type == GDK_TYPE_COLOR)
+  if (node->pspec->value_type == GDK_TYPE_RGBA ||
+      node->pspec->value_type == GDK_TYPE_COLOR)
     {
       /* Allow GtkSymbolicColor as well */
       g_return_if_fail (value_type == GDK_TYPE_RGBA ||
                         value_type == GDK_TYPE_COLOR ||
                         value_type == GTK_TYPE_SYMBOLIC_COLOR);
     }
-  else if (node->property_type == CAIRO_GOBJECT_TYPE_PATTERN)
+  else if (node->pspec->value_type == CAIRO_GOBJECT_TYPE_PATTERN)
     {
       /* Allow GtkGradient as a substitute */
       g_return_if_fail (value_type == CAIRO_GOBJECT_TYPE_PATTERN ||
                         value_type == GTK_TYPE_GRADIENT);
     }
   else
-    g_return_if_fail (node->property_type == value_type);
+    g_return_if_fail (node->pspec->value_type == value_type);
 
   priv = props->priv;
   prop = g_hash_table_lookup (priv->properties,
@@ -670,7 +698,7 @@ gtk_style_properties_set_valist (GtkStyleProperties *props,
       if (G_IS_VALUE (val))
         g_value_unset (val);
 
-      g_value_init (val, node->property_type);
+      g_value_init (val, node->pspec->value_type);
       G_VALUE_COLLECT (val, args, 0, &error);
 
       if (error)
@@ -765,6 +793,18 @@ resolve_gradient (GtkStyleProperties *props,
   return TRUE;
 }
 
+static void
+lookup_default_value (PropertyNode *node,
+                      GValue       *value)
+{
+  g_value_init (value, node->pspec->value_type);
+
+  if (node->pspec->value_type == GTK_TYPE_THEMING_ENGINE)
+    g_value_set_object (value, gtk_theming_engine_load (NULL));
+  else
+    g_param_value_set_default (node->pspec, value);
+}
+
 /**
  * gtk_style_properties_get_property:
  * @props: a #GtkStyleProperties
@@ -809,23 +849,18 @@ gtk_style_properties_get_property (GtkStyleProperties *props,
   if (!prop)
     return FALSE;
 
-  g_value_init (value, node->property_type);
+  g_value_init (value, node->pspec->value_type);
 
   val = property_data_match_state (prop, state);
 
-  if (!val)
-    val = &node->default_value;
-
-  g_return_val_if_fail (G_IS_VALUE (val), FALSE);
-
-  if (G_VALUE_TYPE (val) == GTK_TYPE_SYMBOLIC_COLOR)
+  if (val && G_VALUE_TYPE (val) == GTK_TYPE_SYMBOLIC_COLOR)
     {
-      if (node->property_type == GDK_TYPE_RGBA)
+      if (node->pspec->value_type == GDK_TYPE_RGBA)
         {
           if (!resolve_color (props, val))
             return FALSE;
         }
-      else if (node->property_type == GDK_TYPE_COLOR)
+      else if (node->pspec->value_type == GDK_TYPE_COLOR)
         {
           if (!resolve_color_rgb (props, val))
             return FALSE;
@@ -833,15 +868,27 @@ gtk_style_properties_get_property (GtkStyleProperties *props,
       else
         return FALSE;
     }
-  else if (G_VALUE_TYPE (val) == GTK_TYPE_GRADIENT)
+  else if (val && G_VALUE_TYPE (val) == GTK_TYPE_GRADIENT)
     {
-      g_return_val_if_fail (node->property_type == CAIRO_GOBJECT_TYPE_PATTERN, FALSE);
+      g_return_val_if_fail (node->pspec->value_type == CAIRO_GOBJECT_TYPE_PATTERN, FALSE);
 
       if (!resolve_gradient (props, val))
         return FALSE;
     }
 
-  g_value_copy (val, value);
+  if (val)
+    {
+      g_param_value_validate (node->pspec, val);
+      g_value_copy (val, value);
+    }
+  else
+    {
+      GValue default_value = { 0 };
+
+      lookup_default_value (node, &default_value);
+      g_value_copy (&default_value, value);
+      g_value_unset (&default_value);
+    }
 
   return TRUE;
 }
@@ -890,32 +937,41 @@ gtk_style_properties_get_valist (GtkStyleProperties *props,
       if (prop)
         val = property_data_match_state (prop, state);
 
-      if (!val)
-        val = &node->default_value;
-
-      if (G_VALUE_TYPE (val) == GTK_TYPE_SYMBOLIC_COLOR)
+      if (val && G_VALUE_TYPE (val) == GTK_TYPE_SYMBOLIC_COLOR)
         {
           gboolean resolved;
 
-          if (node->property_type == GDK_TYPE_RGBA)
+          if (node->pspec->value_type == GDK_TYPE_RGBA)
             resolved = resolve_color (props, val);
-          else if (node->property_type == GDK_TYPE_COLOR)
+          else if (node->pspec->value_type == GDK_TYPE_COLOR)
             resolved = resolve_color_rgb (props, val);
           else
             resolved = FALSE;
 
           if (!resolved)
-            val = &node->default_value;
+            val = NULL;
         }
-      else if (G_VALUE_TYPE (val) == GTK_TYPE_GRADIENT)
+      else if (val && G_VALUE_TYPE (val) == GTK_TYPE_GRADIENT)
         {
-          g_return_if_fail (node->property_type == CAIRO_GOBJECT_TYPE_PATTERN);
+          g_return_if_fail (node->pspec->value_type == CAIRO_GOBJECT_TYPE_PATTERN);
 
           if (!resolve_gradient (props, val))
-            val = &node->default_value;
+            val = NULL;
+        }
+
+      if (val)
+        {
+          g_param_value_validate (node->pspec, val);
+          G_VALUE_LCOPY (val, args, 0, &error);
         }
+      else
+        {
+          GValue default_value = { 0 };
 
-      G_VALUE_LCOPY (val, args, 0, &error);
+          lookup_default_value (node, &default_value);
+          G_VALUE_LCOPY (&default_value, args, 0, &error);
+          g_value_unset (&default_value);
+        }
 
       if (error)
         {
diff --git a/gtk/gtkstyleproperties.h b/gtk/gtkstyleproperties.h
index b12c223..ec77233 100644
--- a/gtk/gtkstyleproperties.h
+++ b/gtk/gtkstyleproperties.h
@@ -55,13 +55,11 @@ typedef gboolean (* GtkStylePropertyParser) (const gchar  *string,
 GType gtk_style_properties_get_type (void) G_GNUC_CONST;
 
 /* Functions to register style properties */
-void     gtk_style_properties_register_property (const gchar            *property_name,
-                                                 GType                   type,
-                                                 const GValue           *default_value,
-                                                 GtkStylePropertyParser  parse_func);
-gboolean gtk_style_properties_lookup_property   (const gchar            *property_name,
-                                                 GType                  *type,
-                                                 GtkStylePropertyParser *parse_func);
+void     gtk_style_properties_register_property (GtkStylePropertyParser  parse_func,
+                                                 GParamSpec             *pspec);
+gboolean gtk_style_properties_lookup_property   (const gchar             *property_name,
+                                                 GtkStylePropertyParser  *parse_func,
+                                                 GParamSpec             **pspec);
 
 GtkStyleProperties * gtk_style_properties_new (void);
 
diff --git a/gtk/gtkthemingengine.c b/gtk/gtkthemingengine.c
index c007274..8a29167 100644
--- a/gtk/gtkthemingengine.c
+++ b/gtk/gtkthemingengine.c
@@ -327,16 +327,15 @@ _gtk_theming_engine_set_context (GtkThemingEngine *engine,
 /**
  * gtk_theming_engine_register_property:
  * @engine: a #GtkThemingEngine
- * @property_name: property name to register
- * @type: #GType the property will hold
- * @default_value: default value for this property
+ * @namespace: namespace for the property name
  * @parse_func: parsing function to use, or %NULL
+ * @pspec: the #GParamSpec for the new property
  *
  * Registers a property so it can be used in the CSS file format,
  * on the CSS file the property will look like
- * "-${engine-object-name}-${ property_name}". being
- * ${engine-object-name} either the GtkThemingEngine:name property
- * or G_OBJECT_TYPE_NAME(engine) if the property is unset.
+ * "-${ namespace}-${property_name}". being
+ * ${property_name} the given to @pspec. @namespace will usually
+ * be the theme engine name.
  *
  * For any type a @parse_func may be provided, being this function
  * used for turning any property value (between ':' and ';') in
@@ -345,18 +344,21 @@ _gtk_theming_engine_set_context (GtkThemingEngine *engine,
  * cases.
  *
  * <note>
- * This function needs to be called only once during theming
- * engine object initialization.
+ * Engines must ensure property registration happens exactly once,
+ * usually GTK+ deals with theming engines as singletons, so this
+ * should be guaranteed to happen once, but bear this in mind
+ * when creating #GtkThemeEngine<!-- -->s yourself.
  * </note>
  *
  * <note>
  * In order to make use of the custom registered properties in
- * the CSS file, make sure the engine is loaded first either in
- * a previous rule or within the same one.
+ * the CSS file, make sure the engine is loaded first by specifying
+ * the engine property, either in a previous rule or within the same
+ * one.
  * <programlisting>
  * &ast; {
  *     engine: someengine;
- *     SomeEngine-custom-property: 2;
+ *     -SomeEngine-custom-property: 2;
  * }
  * </programlisting>
  * </note>
@@ -364,31 +366,22 @@ _gtk_theming_engine_set_context (GtkThemingEngine *engine,
  * Since: 3.0
  **/
 void
-gtk_theming_engine_register_property (GtkThemingEngine       *engine,
-                                      const gchar            *property_name,
-                                      GType                   type,
-                                      const GValue           *default_value,
-                                      GtkStylePropertyParser  parse_func)
+gtk_theming_engine_register_property (const gchar            *namespace,
+                                      GtkStylePropertyParser  parse_func,
+                                      GParamSpec             *pspec)
 {
-  GtkThemingEnginePrivate *priv;
-  const gchar *engine_name;
   gchar *name;
 
-  g_return_if_fail (GTK_IS_THEMING_ENGINE (engine));
-  g_return_if_fail (property_name != NULL);
-  g_return_if_fail (type != G_TYPE_INVALID);
-  g_return_if_fail (default_value == NULL || G_IS_VALUE (default_value));
-
-  priv = engine->priv;
+  g_return_if_fail (namespace != NULL);
+  g_return_if_fail (strchr (namespace, ' ') == NULL);
+  g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
-  if (priv->name)
-    engine_name = priv->name;
-  else
-    engine_name = G_OBJECT_TYPE_NAME (engine);
+  /* FIXME: hack hack hack, replacing pspec->name to include namespace */
+  name = g_strdup_printf ("-%s-%s", namespace, pspec->name);
+  g_free (pspec->name);
+  pspec->name = name;
 
-  name = g_strdup_printf ("-%s-%s", engine_name, property_name);
-  gtk_style_properties_register_property (name, type, default_value, parse_func);
-  g_free (name);
+  gtk_style_properties_register_property (parse_func, pspec);
 }
 
 /**
diff --git a/gtk/gtkthemingengine.h b/gtk/gtkthemingengine.h
index 3b45fb0..784737f 100644
--- a/gtk/gtkthemingengine.h
+++ b/gtk/gtkthemingengine.h
@@ -171,11 +171,9 @@ GType gtk_theming_engine_get_type (void) G_GNUC_CONST;
 void _gtk_theming_engine_set_context (GtkThemingEngine *engine,
                                       GtkStyleContext  *context);
 
-void gtk_theming_engine_register_property (GtkThemingEngine       *engine,
-                                           const gchar            *property_name,
-                                           GType                   type,
-                                           const GValue           *default_value,
-                                           GtkStylePropertyParser  parse_func);
+void gtk_theming_engine_register_property (const gchar            *namespace,
+                                           GtkStylePropertyParser  parse_func,
+                                           GParamSpec             *pspec);
 
 void gtk_theming_engine_get_property (GtkThemingEngine *engine,
                                       const gchar      *property,
@@ -202,7 +200,7 @@ G_CONST_RETURN GtkWidgetPath * gtk_theming_engine_get_path (GtkThemingEngine *en
 gboolean gtk_theming_engine_has_class  (GtkThemingEngine *engine,
                                         const gchar      *style_class);
 gboolean gtk_theming_engine_has_region (GtkThemingEngine *engine,
-                                        const gchar      *style_class,
+                                        const gchar      *style_region,
                                         GtkRegionFlags   *flags);
 
 GtkStateFlags gtk_theming_engine_get_state        (GtkThemingEngine *engine);



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