diff options
Diffstat (limited to 'src/animation/gtd-animation-utils.c')
| -rw-r--r-- | src/animation/gtd-animation-utils.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src/animation/gtd-animation-utils.c b/src/animation/gtd-animation-utils.c new file mode 100644 index 0000000..7ab2198 --- /dev/null +++ b/src/animation/gtd-animation-utils.c @@ -0,0 +1,168 @@ +/* gtd-animation-utils.c + * + * Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "gtd-animation-utils.h" + + +typedef struct +{ + GType value_type; + GtdProgressFunc func; +} ProgressData; + +G_LOCK_DEFINE_STATIC (progress_funcs); +static GHashTable *progress_funcs = NULL; + +gboolean +gtd_has_progress_function (GType gtype) +{ + const char *type_name = g_type_name (gtype); + + if (progress_funcs == NULL) + return FALSE; + + return g_hash_table_lookup (progress_funcs, type_name) != NULL; +} + +gboolean +gtd_run_progress_function (GType gtype, + const GValue *initial, + const GValue *final, + gdouble progress, + GValue *retval) +{ + ProgressData *pdata; + gboolean res; + + G_LOCK (progress_funcs); + + if (G_UNLIKELY (!progress_funcs)) + { + res = FALSE; + goto out; + } + + pdata = g_hash_table_lookup (progress_funcs, g_type_name (gtype)); + if (G_UNLIKELY (!pdata)) + { + res = FALSE; + goto out; + } + + res = pdata->func (initial, final, progress, retval); + +out: + G_UNLOCK (progress_funcs); + + return res; +} + +static void +progress_data_destroy (gpointer data) +{ + g_free (data); +} + +/** + * gtd_interval_register_progress_func: (skip) + * @value_type: a #GType + * @func: a #GtdProgressFunc, or %NULL to unset a previously + * set progress function + * + * Sets the progress function for a given @value_type, like: + * + * |[ + * gtd_interval_register_progress_func (MY_TYPE_FOO, + * my_foo_progress); + * ]| + * + * Whenever a #GtdInterval instance using the default + * #GtdInterval::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; + * } + * + * gtd_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 +gtd_interval_register_progress_func (GType value_type, + GtdProgressFunc func) +{ + ProgressData *progress_func; + const char *type_name; + + g_return_if_fail (value_type != G_TYPE_INVALID); + + type_name = g_type_name (value_type); + + G_LOCK (progress_funcs); + + if (G_UNLIKELY (!progress_funcs)) + progress_funcs = g_hash_table_new_full (NULL, NULL, NULL, progress_data_destroy); + + progress_func = g_hash_table_lookup (progress_funcs, type_name); + + if (G_UNLIKELY (progress_func)) + { + if (func == NULL) + { + g_hash_table_remove (progress_funcs, type_name); + g_free (progress_func); + } + else + { + progress_func->func = func; + } + } + else + { + progress_func = g_new0 (ProgressData, 1); + progress_func->value_type = value_type; + progress_func->func = func; + + g_hash_table_replace (progress_funcs, + (gpointer) type_name, + progress_func); + } + + G_UNLOCK (progress_funcs); +} |
