#include "clutter-interval.h"
#include "clutter-units.h"
+typedef struct
+{
+ GType value_type;
+ ClutterProgressFunc func;
+} ProgressData;
+
+static GHashTable *progress_funcs = NULL;
+
enum
{
PROP_0,
value_type = clutter_interval_get_value_type (interval);
+ if (G_UNLIKELY (progress_funcs != NULL))
+ {
+ ProgressData *p_data;
+
+ p_data =
+ g_hash_table_lookup (progress_funcs, GUINT_TO_POINTER (value_type));
+
+ /* if we have a progress function, and that function was
+ * successful in computing the progress, then we bail out
+ * as fast as we can
+ */
+ if (p_data != NULL)
+ {
+ retval = p_data->func (initial, final, factor, value);
+ if (retval)
+ return retval;
+ }
+ }
+
switch (G_TYPE_FUNDAMENTAL (value_type))
{
case G_TYPE_INT:
factor,
value);
}
+
+/**
+ * clutter_interval_register_progress_func:
+ * @value_type: a #GType
+ * @func: a #ClutterProgressFunc, or %NULL to unset a previously
+ * set progress function
+ *
+ * Sets the progress function for a given @value_type, like:
+ *
+ * |[
+ * clutter_interval_register_progress_func (MY_TYPE_FOO,
+ * my_foo_progress);
+ * ]|
+ *
+ * Whenever a #ClutterInterval instance using the default
+ * #ClutterInterval::compute_value implementation is set as an
+ * interval between two #GValue of type @value_type, it will call
+ * @func to establish the value depending on the given progress,
+ * for instance:
+ *
+ * |[
+ * static gboolean
+ * my_int_progress (const GValue *a,
+ * const GValue *b,
+ * gdouble progress,
+ * GValue *retval)
+ * {
+ * gint ia = g_value_get_int (a);
+ * gint ib = g_value_get_int (b);
+ * gint res = factor * (ib - ia) + ia;
+ *
+ * g_value_set_int (retval, res);
+ *
+ * return TRUE;
+ * }
+ *
+ * clutter_interval_register_progress_func (G_TYPE_INT, my_int_progress);
+ * ]|
+ *
+ * To unset a previously set progress function of a #GType, pass %NULL
+ * for @func.
+ *
+ * Since: 1.0
+ */
+void
+clutter_interval_register_progress_func (GType value_type,
+ ClutterProgressFunc func)
+{
+ ProgressData *progress_func;
+
+ g_return_if_fail (value_type != G_TYPE_INVALID);
+
+ if (G_UNLIKELY (progress_funcs == NULL))
+ progress_funcs = g_hash_table_new (NULL, NULL);
+
+ progress_func =
+ g_hash_table_lookup (progress_funcs, GUINT_TO_POINTER (value_type));
+ if (G_UNLIKELY (progress_func))
+ {
+ if (func == NULL)
+ {
+ g_hash_table_remove (progress_funcs, GUINT_TO_POINTER (value_type));
+ g_slice_free (ProgressData, progress_func);
+ }
+ else
+ progress_func->func = func;
+ }
+ else
+ {
+ progress_func = g_slice_new (ProgressData);
+ progress_func->value_type = value_type;
+ progress_func->func = func;
+
+ g_hash_table_replace (progress_funcs,
+ GUINT_TO_POINTER (value_type),
+ progress_func);
+ }
+}
typedef struct _ClutterIntervalClass ClutterIntervalClass;
/**
+ * ClutterProgressFunc:
+ * @a: the initial value of an interval
+ * @b: the final value of an interval
+ * @progress: the progress factor, between 0 and 1
+ * @retval: the value used to store the progress
+ *
+ * Prototype of the progress function used to compute the value
+ * between the two ends @a and @b of an interval depending on
+ * the value of @progress.
+ *
+ * The #GValue in @retval is already initialized with the same
+ * type as @a and @b.
+ *
+ * This function will be called by #ClutterInterval if the
+ * type of the values of the interval was registered using
+ * clutter_interval_register_progress_func().
+ *
+ * Return value: %TRUE if the function successfully computed
+ * the value and stored it inside @retval
+ *
+ * Since: 1.0
+ */
+typedef gboolean (* ClutterProgressFunc) (const GValue *a,
+ const GValue *b,
+ gdouble progress,
+ GValue *retval);
+
+/**
* ClutterInterval:
*
* The #ClutterInterval structure contains only private data and should
gdouble factor,
GValue *value);
+void clutter_interval_register_progress_func (GType value_type,
+ ClutterProgressFunc func);
+
G_END_DECLS
#endif /* __CLUTTER_INTERVAL_H__ */