diff --git a/clutter/clutter-interval.c b/clutter/clutter-interval.c index 0b74e3d96..efdf58dff 100644 --- a/clutter/clutter-interval.c +++ b/clutter/clutter-interval.c @@ -62,6 +62,14 @@ #include "clutter-interval.h" #include "clutter-units.h" +typedef struct +{ + GType value_type; + ClutterProgressFunc func; +} ProgressData; + +static GHashTable *progress_funcs = NULL; + enum { PROP_0, @@ -186,6 +194,25 @@ clutter_interval_real_compute_value (ClutterInterval *interval, 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: @@ -870,3 +897,81 @@ clutter_interval_compute_value (ClutterInterval *interval, 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); + } +} diff --git a/clutter/clutter-interval.h b/clutter/clutter-interval.h index 919369bb8..72ae5304c 100644 --- a/clutter/clutter-interval.h +++ b/clutter/clutter-interval.h @@ -44,6 +44,34 @@ typedef struct _ClutterInterval ClutterInterval; typedef struct _ClutterIntervalPrivate ClutterIntervalPrivate; 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: * @@ -126,6 +154,9 @@ gboolean clutter_interval_compute_value (ClutterInterval *interval, gdouble factor, GValue *value); +void clutter_interval_register_progress_func (GType value_type, + ClutterProgressFunc func); + G_END_DECLS #endif /* __CLUTTER_INTERVAL_H__ */