[gimp] libgimpbase: add GimpParamSpecValueArray for the same reason
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] libgimpbase: add GimpParamSpecValueArray for the same reason
- Date: Thu, 3 May 2012 22:52:50 +0000 (UTC)
commit ffe74bbb028c1a68b4975f3b315c57b809fef0b4
Author: Michael Natterer <mitch gimp org>
Date: Fri May 4 00:26:26 2012 +0200
libgimpbase: add GimpParamSpecValueArray for the same reason
libgimpbase/gimpbase.def | 2 +
libgimpbase/gimpvaluearray.c | 249 ++++++++++++++++++++++++++++++++++++++++++
libgimpbase/gimpvaluearray.h | 26 +++++
3 files changed, 277 insertions(+), 0 deletions(-)
---
diff --git a/libgimpbase/gimpbase.def b/libgimpbase/gimpbase.def
index 1a8b26a..fcaa2dd 100644
--- a/libgimpbase/gimpbase.def
+++ b/libgimpbase/gimpbase.def
@@ -57,7 +57,9 @@ EXPORTS
gimp_param_spec_memsize
gimp_param_spec_parasite
gimp_param_spec_unit
+ gimp_param_spec_value_array
gimp_param_unit_get_type
+ gimp_param_value_array_get_type
gimp_parasite_compare
gimp_parasite_copy
gimp_parasite_data
diff --git a/libgimpbase/gimpvaluearray.c b/libgimpbase/gimpvaluearray.c
index 8d49b63..fe48dc0 100644
--- a/libgimpbase/gimpvaluearray.c
+++ b/libgimpbase/gimpvaluearray.c
@@ -340,3 +340,252 @@ gimp_value_array_truncate (GimpValueArray *value_array,
for (i = value_array->n_values; i > n_values; i--)
gimp_value_array_remove (value_array, i - 1);
}
+
+
+/*
+ * GIMP_TYPE_PARAM_VALUE_ARRAY
+ */
+
+static void gimp_param_value_array_class_init (GParamSpecClass *klass);
+static void gimp_param_value_array_init (GParamSpec *pspec);
+static void gimp_param_value_array_finalize (GParamSpec *pspec);
+static void gimp_param_value_array_set_default (GParamSpec *pspec,
+ GValue *value);
+static gboolean gimp_param_value_array_validate (GParamSpec *pspec,
+ GValue *value);
+static gint gimp_param_value_array_values_cmp (GParamSpec *pspec,
+ const GValue *value1,
+ const GValue *value2);
+
+GType
+gimp_param_value_array_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type)
+ {
+ const GTypeInfo info =
+ {
+ sizeof (GParamSpecClass),
+ NULL, NULL,
+ (GClassInitFunc) gimp_param_value_array_class_init,
+ NULL, NULL,
+ sizeof (GimpParamSpecValueArray),
+ 0,
+ (GInstanceInitFunc) gimp_param_value_array_init
+ };
+
+ type = g_type_register_static (G_TYPE_PARAM_BOXED,
+ "GimpParamValueArray", &info, 0);
+ }
+
+ return type;
+}
+
+
+static void
+gimp_param_value_array_class_init (GParamSpecClass *klass)
+{
+ klass->value_type = GIMP_TYPE_VALUE_ARRAY;
+ klass->finalize = gimp_param_value_array_finalize;
+ klass->value_set_default = gimp_param_value_array_set_default;
+ klass->value_validate = gimp_param_value_array_validate;
+ klass->values_cmp = gimp_param_value_array_values_cmp;
+}
+
+static void
+gimp_param_value_array_init (GParamSpec *pspec)
+{
+ GimpParamSpecValueArray *aspec = GIMP_PARAM_SPEC_VALUE_ARRAY (pspec);
+
+ aspec->element_spec = NULL;
+ aspec->fixed_n_elements = 0; /* disable */
+}
+
+static inline guint
+gimp_value_array_ensure_size (GimpValueArray *value_array,
+ guint fixed_n_elements)
+{
+ guint changed = 0;
+
+ if (fixed_n_elements)
+ {
+ while (gimp_value_array_length (value_array) < fixed_n_elements)
+ {
+ gimp_value_array_append (value_array, NULL);
+ changed++;
+ }
+
+ while (gimp_value_array_length (value_array) > fixed_n_elements)
+ {
+ gimp_value_array_remove (value_array,
+ gimp_value_array_length (value_array) - 1);
+ changed++;
+ }
+ }
+
+ return changed;
+}
+
+static void
+gimp_param_value_array_finalize (GParamSpec *pspec)
+{
+ GimpParamSpecValueArray *aspec = GIMP_PARAM_SPEC_VALUE_ARRAY (pspec);
+ GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (GIMP_TYPE_PARAM_VALUE_ARRAY));
+
+ if (aspec->element_spec)
+ {
+ g_param_spec_unref (aspec->element_spec);
+ aspec->element_spec = NULL;
+ }
+
+ parent_class->finalize (pspec);
+}
+
+static void
+gimp_param_value_array_set_default (GParamSpec *pspec,
+ GValue *value)
+{
+ GimpParamSpecValueArray *aspec = GIMP_PARAM_SPEC_VALUE_ARRAY (pspec);
+
+ if (!value->data[0].v_pointer && aspec->fixed_n_elements)
+ value->data[0].v_pointer = gimp_value_array_new (aspec->fixed_n_elements);
+
+ if (value->data[0].v_pointer)
+ {
+ /* g_value_reset (value); already done */
+ gimp_value_array_ensure_size (value->data[0].v_pointer,
+ aspec->fixed_n_elements);
+ }
+}
+
+static gboolean
+gimp_param_value_array_validate (GParamSpec *pspec,
+ GValue *value)
+{
+ GimpParamSpecValueArray *aspec = GIMP_PARAM_SPEC_VALUE_ARRAY (pspec);
+ GimpValueArray *value_array = value->data[0].v_pointer;
+ guint changed = 0;
+
+ if (!value->data[0].v_pointer && aspec->fixed_n_elements)
+ value->data[0].v_pointer = gimp_value_array_new (aspec->fixed_n_elements);
+
+ if (value->data[0].v_pointer)
+ {
+ /* ensure array size validity */
+ changed += gimp_value_array_ensure_size (value_array,
+ aspec->fixed_n_elements);
+
+ /* ensure array values validity against a present element spec */
+ if (aspec->element_spec)
+ {
+ GParamSpec *element_spec = aspec->element_spec;
+ gint length = gimp_value_array_length (value_array);
+ gint i;
+
+ for (i = 0; i < length; i++)
+ {
+ GValue *element = gimp_value_array_index (value_array, i);
+
+ /* need to fixup value type, or ensure that the array
+ * value is initialized at all
+ */
+ if (! g_value_type_compatible (G_VALUE_TYPE (element),
+ G_PARAM_SPEC_VALUE_TYPE (element_spec)))
+ {
+ if (G_VALUE_TYPE (element) != 0)
+ g_value_unset (element);
+
+ g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec));
+ g_param_value_set_default (element_spec, element);
+ changed++;
+ }
+
+ /* validate array value against element_spec */
+ changed += g_param_value_validate (element_spec, element);
+ }
+ }
+ }
+
+ return changed;
+}
+
+static gint
+gimp_param_value_array_values_cmp (GParamSpec *pspec,
+ const GValue *value1,
+ const GValue *value2)
+{
+ GimpParamSpecValueArray *aspec = GIMP_PARAM_SPEC_VALUE_ARRAY (pspec);
+ GimpValueArray *value_array1 = value1->data[0].v_pointer;
+ GimpValueArray *value_array2 = value2->data[0].v_pointer;
+ gint length1;
+ gint length2;
+
+ if (!value_array1 || !value_array2)
+ return value_array2 ? -1 : value_array1 != value_array2;
+
+ length1 = gimp_value_array_length (value_array1);
+ length2 = gimp_value_array_length (value_array2);
+
+ if (length1 != length2)
+ {
+ return length1 < length2 ? -1 : 1;
+ }
+ else if (! aspec->element_spec)
+ {
+ /* we need an element specification for comparisons, so there's
+ * not much to compare here, try to at least provide stable
+ * lesser/greater result
+ */
+ return length1 < length2 ? -1 : length1 > length2;
+ }
+ else /* length1 == length2 */
+ {
+ guint i;
+
+ for (i = 0; i < length1; i++)
+ {
+ GValue *element1 = gimp_value_array_index (value_array1, i);
+ GValue *element2 = gimp_value_array_index (value_array2, i);
+ gint cmp;
+
+ /* need corresponding element types, provide stable result
+ * otherwise
+ */
+ if (G_VALUE_TYPE (element1) != G_VALUE_TYPE (element2))
+ return G_VALUE_TYPE (element1) < G_VALUE_TYPE (element2) ? -1 : 1;
+
+ cmp = g_param_values_cmp (aspec->element_spec, element1, element2);
+ if (cmp)
+ return cmp;
+ }
+
+ return 0;
+ }
+}
+
+GParamSpec *
+gimp_param_spec_value_array (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GParamSpec *element_spec,
+ GParamFlags flags)
+{
+ GimpParamSpecValueArray *aspec;
+
+ if (element_spec)
+ g_return_val_if_fail (G_IS_PARAM_SPEC (element_spec), NULL);
+
+ aspec = g_param_spec_internal (GIMP_TYPE_PARAM_VALUE_ARRAY,
+ name,
+ nick,
+ blurb,
+ flags);
+ if (element_spec)
+ {
+ aspec->element_spec = g_param_spec_ref (element_spec);
+ g_param_spec_sink (element_spec);
+ }
+
+ return G_PARAM_SPEC (aspec);
+}
diff --git a/libgimpbase/gimpvaluearray.h b/libgimpbase/gimpvaluearray.h
index 58a14ca..ca968b3 100644
--- a/libgimpbase/gimpvaluearray.h
+++ b/libgimpbase/gimpvaluearray.h
@@ -64,6 +64,32 @@ void gimp_value_array_truncate (GimpValueArray *value_array,
gint n_values);
+/*
+ * GIMP_TYPE_PARAM_VALUE_ARRAY
+ */
+
+#define GIMP_TYPE_PARAM_VALUE_ARRAY (gimp_param_value_array_get_type ())
+#define GIMP_IS_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_VALUE_ARRAY))
+#define GIMP_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_VALUE_ARRAY, GimpParamSpecValueArray))
+
+typedef struct _GimpParamSpecValueArray GimpParamSpecValueArray;
+
+struct _GimpParamSpecValueArray
+{
+ GParamSpec parent_instance;
+ GParamSpec *element_spec;
+ gint fixed_n_elements;
+};
+
+GType gimp_param_value_array_get_type (void) G_GNUC_CONST;
+
+GParamSpec * gimp_param_spec_value_array (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GParamSpec *element_spec,
+ GParamFlags flags);
+
+
G_END_DECLS
#endif /* __GIMP_VALUE_ARRAY_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]