[gtk+/treeview-refactor] Implemented "cell properties" on the GtkCellArea
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/treeview-refactor] Implemented "cell properties" on the GtkCellArea
- Date: Sun, 31 Oct 2010 08:09:45 +0000 (UTC)
commit d781c226dae1b370220e41d6f457fa91c6678109
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Sun Oct 31 17:13:15 2010 +0900
Implemented "cell properties" on the GtkCellArea
Added cell "packing" properties for generic configuration
of child cells inside an area.
gtk/gtkcellarea.c | 369 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
gtk/gtkcellarea.h | 51 +++++++-
2 files changed, 417 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c
index c8cbabf..dfee8cc 100644
--- a/gtk/gtkcellarea.c
+++ b/gtk/gtkcellarea.c
@@ -21,10 +21,19 @@
* Boston, MA 02111-1307, USA.
*/
+#include "config.h"
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
#include "gtkcelllayout.h"
#include "gtkcellarea.h"
#include "gtkcellareaiter.h"
+#include <gobject/gvaluecollector.h>
+
+
/* GObjectClass */
static void gtk_cell_area_dispose (GObject *object);
static void gtk_cell_area_finalize (GObject *object);
@@ -104,6 +113,14 @@ struct _GtkCellAreaPrivate
GHashTable *cell_info;
};
+/* Keep the paramspec pool internal, no need to deliver notifications
+ * on cells. at least no percieved need for now */
+static GParamSpecPool *cell_property_pool = NULL;
+
+#define PARAM_SPEC_PARAM_ID(pspec) ((pspec)->param_id)
+#define PARAM_SPEC_SET_PARAM_ID(pspec, id) ((pspec)->param_id = (id))
+
+
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkCellArea, gtk_cell_area, G_TYPE_INITIALLY_UNOWNED,
G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
gtk_cell_area_cell_layout_init));
@@ -148,6 +165,10 @@ gtk_cell_area_class_init (GtkCellAreaClass *class)
class->get_preferred_height_for_width = gtk_cell_area_real_get_preferred_height_for_width;
class->get_preferred_width_for_height = gtk_cell_area_real_get_preferred_width_for_height;
+ /* Cell properties */
+ if (!cell_property_pool)
+ cell_property_pool = g_param_spec_pool_new (FALSE);
+
g_type_class_add_private (object_class, sizeof (GtkCellAreaPrivate));
}
@@ -419,7 +440,6 @@ gtk_cell_area_get_cells (GtkCellLayout *cell_layout)
/*************************************************************
* API *
*************************************************************/
-
void
gtk_cell_area_add (GtkCellArea *area,
GtkCellRenderer *renderer)
@@ -644,6 +664,7 @@ gtk_cell_area_get_preferred_width_for_height (GtkCellArea *area,
class->get_preferred_width_for_height (area, iter, widget, height, minimum_width, natural_width);
}
+/* Attributes */
void
gtk_cell_area_attribute_connect (GtkCellArea *area,
GtkCellRenderer *renderer,
@@ -776,3 +797,349 @@ gtk_cell_area_apply_attributes (GtkCellArea *area,
* apply the data from the treemodel */
g_hash_table_foreach (priv->cell_info, (GHFunc)apply_cell_attributes, &data);
}
+
+/* Cell Properties */
+void
+gtk_cell_area_class_install_cell_property (GtkCellAreaClass *aclass,
+ guint property_id,
+ GParamSpec *pspec)
+{
+ g_return_if_fail (GTK_IS_CELL_AREA_CLASS (aclass));
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ if (pspec->flags & G_PARAM_WRITABLE)
+ g_return_if_fail (aclass->set_cell_property != NULL);
+ if (pspec->flags & G_PARAM_READABLE)
+ g_return_if_fail (aclass->get_cell_property != NULL);
+ g_return_if_fail (property_id > 0);
+ g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
+ g_return_if_fail ((pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) == 0);
+
+ if (g_param_spec_pool_lookup (cell_property_pool, pspec->name, G_OBJECT_CLASS_TYPE (aclass), TRUE))
+ {
+ g_warning (G_STRLOC ": class `%s' already contains a cell property named `%s'",
+ G_OBJECT_CLASS_NAME (aclass), pspec->name);
+ return;
+ }
+ g_param_spec_ref (pspec);
+ g_param_spec_sink (pspec);
+ PARAM_SPEC_SET_PARAM_ID (pspec, property_id);
+ g_param_spec_pool_insert (cell_property_pool, pspec, G_OBJECT_CLASS_TYPE (aclass));
+}
+
+GParamSpec*
+gtk_cell_area_class_find_cell_property (GtkCellAreaClass *aclass,
+ const gchar *property_name)
+{
+ g_return_val_if_fail (GTK_IS_CELL_AREA_CLASS (aclass), NULL);
+ g_return_val_if_fail (property_name != NULL, NULL);
+
+ return g_param_spec_pool_lookup (cell_property_pool,
+ property_name,
+ G_OBJECT_CLASS_TYPE (aclass),
+ TRUE);
+}
+
+GParamSpec**
+gtk_cell_area_class_list_cell_properties (GtkCellAreaClass *aclass,
+ guint *n_properties)
+{
+ GParamSpec **pspecs;
+ guint n;
+
+ g_return_val_if_fail (GTK_IS_CELL_AREA_CLASS (aclass), NULL);
+
+ pspecs = g_param_spec_pool_list (cell_property_pool,
+ G_OBJECT_CLASS_TYPE (aclass),
+ &n);
+ if (n_properties)
+ *n_properties = n;
+
+ return pspecs;
+}
+
+void
+gtk_cell_area_add_with_properties (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *first_prop_name,
+ ...)
+{
+ GtkCellAreaClass *class;
+
+ g_return_if_fail (GTK_IS_CELL_AREA (area));
+ g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+
+ class = GTK_CELL_AREA_GET_CLASS (area);
+
+ if (class->add)
+ {
+ va_list var_args;
+
+ class->add (area, renderer);
+
+ va_start (var_args, first_prop_name);
+ gtk_cell_area_cell_set_valist (area, renderer, first_prop_name, var_args);
+ va_end (var_args);
+ }
+ else
+ g_warning ("GtkCellAreaClass::add not implemented for `%s'",
+ g_type_name (G_TYPE_FROM_INSTANCE (area)));
+}
+
+void
+gtk_cell_area_cell_set (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *first_prop_name,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (GTK_IS_CELL_AREA (area));
+ g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+
+ va_start (var_args, first_prop_name);
+ gtk_cell_area_cell_set_valist (area, renderer, first_prop_name, var_args);
+ va_end (var_args);
+}
+
+void
+gtk_cell_area_cell_get (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *first_prop_name,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (GTK_IS_CELL_AREA (area));
+ g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+
+ va_start (var_args, first_prop_name);
+ gtk_cell_area_cell_get_valist (area, renderer, first_prop_name, var_args);
+ va_end (var_args);
+}
+
+static inline void
+area_get_cell_property (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ GParamSpec *pspec,
+ GValue *value)
+{
+ GtkCellAreaClass *class = g_type_class_peek (pspec->owner_type);
+
+ class->get_cell_property (area, renderer, PARAM_SPEC_PARAM_ID (pspec), value, pspec);
+}
+
+static inline void
+area_set_cell_property (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ GParamSpec *pspec,
+ const GValue *value)
+{
+ GValue tmp_value = { 0, };
+ GtkCellAreaClass *class = g_type_class_peek (pspec->owner_type);
+
+ /* provide a copy to work from, convert (if necessary) and validate */
+ g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ if (!g_value_transform (value, &tmp_value))
+ g_warning ("unable to set cell property `%s' of type `%s' from value of type `%s'",
+ pspec->name,
+ g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
+ G_VALUE_TYPE_NAME (value));
+ else if (g_param_value_validate (pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION))
+ {
+ gchar *contents = g_strdup_value_contents (value);
+
+ g_warning ("value \"%s\" of type `%s' is invalid for property `%s' of type `%s'",
+ contents,
+ G_VALUE_TYPE_NAME (value),
+ pspec->name,
+ g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
+ g_free (contents);
+ }
+ else
+ {
+ class->set_cell_property (area, renderer, PARAM_SPEC_PARAM_ID (pspec), &tmp_value, pspec);
+ }
+ g_value_unset (&tmp_value);
+}
+
+void
+gtk_cell_area_cell_set_valist (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *first_property_name,
+ va_list var_args)
+{
+ const gchar *name;
+
+ g_return_if_fail (GTK_IS_CELL_AREA (area));
+ g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+
+ name = first_property_name;
+ while (name)
+ {
+ GValue value = { 0, };
+ gchar *error = NULL;
+ GParamSpec *pspec =
+ g_param_spec_pool_lookup (cell_property_pool, name,
+ G_OBJECT_TYPE (area), TRUE);
+ if (!pspec)
+ {
+ g_warning ("%s: cell area class `%s' has no cell property named `%s'",
+ G_STRLOC, G_OBJECT_TYPE_NAME (area), name);
+ break;
+ }
+ if (!(pspec->flags & G_PARAM_WRITABLE))
+ {
+ g_warning ("%s: cell property `%s' of cell area class `%s' is not writable",
+ G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (area));
+ break;
+ }
+
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ G_VALUE_COLLECT (&value, var_args, 0, &error);
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+
+ /* we purposely leak the value here, it might not be
+ * in a sane state if an error condition occoured
+ */
+ break;
+ }
+ area_set_cell_property (area, renderer, pspec, &value);
+ g_value_unset (&value);
+ name = va_arg (var_args, gchar*);
+ }
+}
+
+void
+gtk_cell_area_cell_get_valist (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *first_property_name,
+ va_list var_args)
+{
+ const gchar *name;
+
+ g_return_if_fail (GTK_IS_CELL_AREA (area));
+ g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+
+ name = first_property_name;
+ while (name)
+ {
+ GValue value = { 0, };
+ GParamSpec *pspec;
+ gchar *error;
+
+ pspec = g_param_spec_pool_lookup (cell_property_pool, name,
+ G_OBJECT_TYPE (area), TRUE);
+ if (!pspec)
+ {
+ g_warning ("%s: cell area class `%s' has no cell property named `%s'",
+ G_STRLOC, G_OBJECT_TYPE_NAME (area), name);
+ break;
+ }
+ if (!(pspec->flags & G_PARAM_READABLE))
+ {
+ g_warning ("%s: cell property `%s' of cell area class `%s' is not readable",
+ G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (area));
+ break;
+ }
+
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ area_get_cell_property (area, renderer, pspec, &value);
+ G_VALUE_LCOPY (&value, var_args, 0, &error);
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+ g_value_unset (&value);
+ break;
+ }
+ g_value_unset (&value);
+ name = va_arg (var_args, gchar*);
+ }
+}
+
+void
+gtk_cell_area_cell_set_property (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *property_name,
+ const GValue *value)
+{
+ GParamSpec *pspec;
+
+ g_return_if_fail (GTK_IS_CELL_AREA (area));
+ g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+ g_return_if_fail (property_name != NULL);
+ g_return_if_fail (G_IS_VALUE (value));
+
+ pspec = g_param_spec_pool_lookup (cell_property_pool, property_name,
+ G_OBJECT_TYPE (area), TRUE);
+ if (!pspec)
+ g_warning ("%s: cell area class `%s' has no cell property named `%s'",
+ G_STRLOC, G_OBJECT_TYPE_NAME (area), property_name);
+ else if (!(pspec->flags & G_PARAM_WRITABLE))
+ g_warning ("%s: cell property `%s' of cell area class `%s' is not writable",
+ G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (area));
+ else
+ {
+ area_set_cell_property (area, renderer, pspec, value);
+ }
+}
+
+void
+gtk_cell_area_cell_get_property (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *property_name,
+ GValue *value)
+{
+ GParamSpec *pspec;
+
+ g_return_if_fail (GTK_IS_CELL_AREA (area));
+ g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+ g_return_if_fail (property_name != NULL);
+ g_return_if_fail (G_IS_VALUE (value));
+
+ pspec = g_param_spec_pool_lookup (cell_property_pool, property_name,
+ G_OBJECT_TYPE (area), TRUE);
+ if (!pspec)
+ g_warning ("%s: cell area class `%s' has no cell property named `%s'",
+ G_STRLOC, G_OBJECT_TYPE_NAME (area), property_name);
+ else if (!(pspec->flags & G_PARAM_READABLE))
+ g_warning ("%s: cell property `%s' of cell area class `%s' is not readable",
+ G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (area));
+ else
+ {
+ GValue *prop_value, tmp_value = { 0, };
+
+ /* auto-conversion of the callers value type
+ */
+ if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
+ {
+ g_value_reset (value);
+ prop_value = value;
+ }
+ else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
+ {
+ g_warning ("can't retrieve cell property `%s' of type `%s' as value of type `%s'",
+ pspec->name,
+ g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
+ G_VALUE_TYPE_NAME (value));
+ return;
+ }
+ else
+ {
+ g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ prop_value = &tmp_value;
+ }
+
+ area_get_cell_property (area, renderer, pspec, prop_value);
+
+ if (prop_value != value)
+ {
+ g_value_transform (prop_value, value);
+ g_value_unset (&tmp_value);
+ }
+ }
+}
+
diff --git a/gtk/gtkcellarea.h b/gtk/gtkcellarea.h
index 3c2c750..e599220 100644
--- a/gtk/gtkcellarea.h
+++ b/gtk/gtkcellarea.h
@@ -116,6 +116,17 @@ struct _GtkCellAreaClass
gint *minimum_width,
gint *natural_width);
+ /* Cell Properties */
+ void (* set_cell_property) (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+ void (* get_cell_property) (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
@@ -175,8 +186,7 @@ void gtk_cell_area_get_preferred_width_for_height (GtkCellArea
gint *minimum_width,
gint *natural_width);
-
-/* Following apis are not class virtual methods */
+/* Attributes */
void gtk_cell_area_apply_attributes (GtkCellArea *area,
GtkTreeModel *tree_model,
GtkTreeIter *iter);
@@ -188,6 +198,43 @@ void gtk_cell_area_attribute_disconnect (GtkCellArea
GtkCellRenderer *renderer,
const gchar *attribute);
+/* Cell Properties */
+void gtk_cell_area_class_install_cell_property (GtkCellAreaClass *aclass,
+ guint property_id,
+ GParamSpec *pspec);
+GParamSpec* gtk_cell_area_class_find_cell_property (GtkCellAreaClass *aclass,
+ const gchar *property_name);
+GParamSpec** gtk_cell_area_class_list_cell_properties (GtkCellAreaClass *aclass,
+ guint *n_properties);
+void gtk_cell_area_add_with_properties (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *first_prop_name,
+ ...) G_GNUC_NULL_TERMINATED;
+void gtk_cell_area_cell_set (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *first_prop_name,
+ ...) G_GNUC_NULL_TERMINATED;
+void gtk_cell_area_cell_get (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *first_prop_name,
+ ...) G_GNUC_NULL_TERMINATED;
+void gtk_cell_area_cell_set_valist (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *first_property_name,
+ va_list var_args);
+void gtk_cell_area_cell_get_valist (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *first_property_name,
+ va_list var_args);
+void gtk_cell_area_cell_set_property (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *property_name,
+ const GValue *value);
+void gtk_cell_area_cell_get_property (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ const gchar *property_name,
+ GValue *value);
+
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]