diff options
author | Jamie Murphy <hello@itsjamie.dev> | 2023-01-12 15:28:03 -0800 |
---|---|---|
committer | Jamie Murphy <hello@itsjamie.dev> | 2023-02-12 07:14:41 +0000 |
commit | 39d63bf2fd9a9f752e4136aa3574265a8953a971 (patch) | |
tree | 960e0bdf30788e4b35bff6c35897e184006531f3 | |
parent | d68a45d81772e63a91396eaa41d03d27dcae492a (diff) | |
download | gnome-todo-39d63bf2fd9a9f752e4136aa3574265a8953a971.tar.gz |
project: Remove GtdAnimation
The custom animation code was never really touched in-tree, and AdwAnimation exists for any future animation work
35 files changed, 47 insertions, 8239 deletions
diff --git a/src/animation/gtd-animatable.c b/src/animation/gtd-animatable.c deleted file mode 100644 index b068b316..00000000 --- a/src/animation/gtd-animatable.c +++ /dev/null @@ -1,204 +0,0 @@ -/* gtd-animatable.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 - */ - - -/** - * SECTION:gtd-animatable - * @short_description: Interface for animatable classes - * - * #GtdAnimatable is an interface that allows a #GObject class - * to control how an widget will animate a property. - * - * Each #GtdAnimatable should implement the - * #GtdAnimatableInterface.interpolate_property() virtual function of the - * interface to compute the animation state between two values of an interval - * depending on a progress fwidget, expressed as a floating point value. - */ - -#include "gtd-animatable.h" - -#include "gtd-debug.h" -#include "gtd-interval.h" - -G_DEFINE_INTERFACE (GtdAnimatable, gtd_animatable, G_TYPE_OBJECT); - -static void -gtd_animatable_default_init (GtdAnimatableInterface *iface) -{ -} - -/** - * gtd_animatable_find_property: - * @animatable: a #GtdAnimatable - * @property_name: the name of the animatable property to find - * - * Finds the #GParamSpec for @property_name - * - * Return value: (transfer none) (nullable): The #GParamSpec for the given property - */ -GParamSpec * -gtd_animatable_find_property (GtdAnimatable *animatable, - const gchar *property_name) -{ - GtdAnimatableInterface *iface; - - g_return_val_if_fail (GTD_IS_ANIMATABLE (animatable), NULL); - g_return_val_if_fail (property_name != NULL, NULL); - - GTD_TRACE_MSG ("[animation] Looking for property '%s'", property_name); - - iface = GTD_ANIMATABLE_GET_IFACE (animatable); - if (iface->find_property != NULL) - return iface->find_property (animatable, property_name); - - return g_object_class_find_property (G_OBJECT_GET_CLASS (animatable), - property_name); -} - -/** - * gtd_animatable_get_initial_state: - * @animatable: a #GtdAnimatable - * @property_name: the name of the animatable property to retrieve - * @value: a #GValue initialized to the type of the property to retrieve - * - * Retrieves the current state of @property_name and sets @value with it - */ -void -gtd_animatable_get_initial_state (GtdAnimatable *animatable, - const gchar *property_name, - GValue *value) -{ - GtdAnimatableInterface *iface; - - g_return_if_fail (GTD_IS_ANIMATABLE (animatable)); - g_return_if_fail (property_name != NULL); - - GTD_TRACE_MSG ("[animation] Getting initial state of '%s'", property_name); - - iface = GTD_ANIMATABLE_GET_IFACE (animatable); - if (iface->get_initial_state != NULL) - iface->get_initial_state (animatable, property_name, value); - else - g_object_get_property (G_OBJECT (animatable), property_name, value); -} - -/** - * gtd_animatable_set_final_state: - * @animatable: a #GtdAnimatable - * @property_name: the name of the animatable property to set - * @value: the value of the animatable property to set - * - * Sets the current state of @property_name to @value - */ -void -gtd_animatable_set_final_state (GtdAnimatable *animatable, - const gchar *property_name, - const GValue *value) -{ - GtdAnimatableInterface *iface; - - g_return_if_fail (GTD_IS_ANIMATABLE (animatable)); - g_return_if_fail (property_name != NULL); - - GTD_TRACE_MSG ("[animation] Setting state of property '%s'", property_name); - - iface = GTD_ANIMATABLE_GET_IFACE (animatable); - if (iface->set_final_state != NULL) - iface->set_final_state (animatable, property_name, value); - else - g_object_set_property (G_OBJECT (animatable), property_name, value); -} - -/** - * gtd_animatable_interpolate_value: - * @animatable: a #GtdAnimatable - * @property_name: the name of the property to interpolate - * @interval: a #GtdInterval with the animation range - * @progress: the progress to use to interpolate between the - * initial and final values of the @interval - * @value: (out): return location for an initialized #GValue - * using the same type of the @interval - * - * Asks a #GtdAnimatable implementation to interpolate a - * a named property between the initial and final values of - * a #GtdInterval, using @progress as the interpolation - * value, and store the result inside @value. - * - * This function should be used for every property animation - * involving #GtdAnimatable<!-- -->s. - * - * This function replaces gtd_animatable_animate_property(). - * - * Return value: %TRUE if the interpolation was successful, - * and %FALSE otherwise - */ -gboolean -gtd_animatable_interpolate_value (GtdAnimatable *animatable, - const gchar *property_name, - GtdInterval *interval, - gdouble progress, - GValue *value) -{ - GtdAnimatableInterface *iface; - - g_return_val_if_fail (GTD_IS_ANIMATABLE (animatable), FALSE); - g_return_val_if_fail (property_name != NULL, FALSE); - g_return_val_if_fail (GTD_IS_INTERVAL (interval), FALSE); - g_return_val_if_fail (value != NULL, FALSE); - - GTD_TRACE_MSG ("[animation] Interpolating '%s' (progress: %.3f)", - property_name, - progress); - - iface = GTD_ANIMATABLE_GET_IFACE (animatable); - if (iface->interpolate_value != NULL) - { - return iface->interpolate_value (animatable, property_name, - interval, - progress, - value); - } - else - { - return gtd_interval_compute_value (interval, progress, value); - } -} - -/** - * gtd_animatable_get_widget: - * @animatable: a #GtdAnimatable - * - * Get animated widget. - * - * Return value: (transfer none): a #GtdWidget - */ -GtdWidget * -gtd_animatable_get_widget (GtdAnimatable *animatable) -{ - GtdAnimatableInterface *iface; - - g_return_val_if_fail (GTD_IS_ANIMATABLE (animatable), NULL); - - iface = GTD_ANIMATABLE_GET_IFACE (animatable); - - g_return_val_if_fail (iface->get_widget, NULL); - - return iface->get_widget (animatable); -} diff --git a/src/animation/gtd-animatable.h b/src/animation/gtd-animatable.h deleted file mode 100644 index 3edb07db..00000000 --- a/src/animation/gtd-animatable.h +++ /dev/null @@ -1,85 +0,0 @@ -/* gtd-animatable.h - * - * 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 - */ - -#pragma once - -#include "gtd-types.h" - -G_BEGIN_DECLS - -#define GTD_TYPE_ANIMATABLE (gtd_animatable_get_type ()) -G_DECLARE_INTERFACE (GtdAnimatable, gtd_animatable, GTD, ANIMATABLE, GObject) - -/** - * GtdAnimatableInterface: - * @find_property: virtual function for retrieving the #GParamSpec of - * an animatable property - * @get_initial_state: virtual function for retrieving the initial - * state of an animatable property - * @set_final_state: virtual function for setting the state of an - * animatable property - * @interpolate_value: virtual function for interpolating the progress - * of a property - * @get_widget: virtual function for getting associated #GtdWidget - * - * Since: 1.0 - */ -struct _GtdAnimatableInterface -{ - /*< private >*/ - GTypeInterface parent_iface; - - /*< public >*/ - GParamSpec *(* find_property) (GtdAnimatable *animatable, - const gchar *property_name); - void (* get_initial_state) (GtdAnimatable *animatable, - const gchar *property_name, - GValue *value); - void (* set_final_state) (GtdAnimatable *animatable, - const gchar *property_name, - const GValue *value); - gboolean (* interpolate_value) (GtdAnimatable *animatable, - const gchar *property_name, - GtdInterval *interval, - gdouble progress, - GValue *value); - GtdWidget * (* get_widget) (GtdAnimatable *animatable); -}; - -GParamSpec *gtd_animatable_find_property (GtdAnimatable *animatable, - const gchar *property_name); - -void gtd_animatable_get_initial_state (GtdAnimatable *animatable, - const gchar *property_name, - GValue *value); - -void gtd_animatable_set_final_state (GtdAnimatable *animatable, - const gchar *property_name, - const GValue *value); - -gboolean gtd_animatable_interpolate_value (GtdAnimatable *animatable, - const gchar *property_name, - GtdInterval *interval, - gdouble progress, - GValue *value); - -GtdWidget * gtd_animatable_get_widget (GtdAnimatable *animatable); - -G_END_DECLS diff --git a/src/animation/gtd-animation-enums.h b/src/animation/gtd-animation-enums.h deleted file mode 100644 index ed26f8ea..00000000 --- a/src/animation/gtd-animation-enums.h +++ /dev/null @@ -1,173 +0,0 @@ -/* gtd-animation-enums.h - * - * 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 - */ - -#pragma once - -#include <glib.h> - -G_BEGIN_DECLS - - -/** - * GtdEaseMode: - * @GTD_CUSTOM_MODE: custom progress function - * @GTD_EASE_LINEAR: linear tweening - * @GTD_EASE_IN_QUAD: quadratic tweening - * @GTD_EASE_OUT_QUAD: quadratic tweening, inverse of - * %GTD_EASE_IN_QUAD - * @GTD_EASE_IN_OUT_QUAD: quadratic tweening, combininig - * %GTD_EASE_IN_QUAD and %GTD_EASE_OUT_QUAD - * @GTD_EASE_IN_CUBIC: cubic tweening - * @GTD_EASE_OUT_CUBIC: cubic tweening, invers of - * %GTD_EASE_IN_CUBIC - * @GTD_EASE_IN_OUT_CUBIC: cubic tweening, combining - * %GTD_EASE_IN_CUBIC and %GTD_EASE_OUT_CUBIC - * @GTD_EASE_IN_QUART: quartic tweening - * @GTD_EASE_OUT_QUART: quartic tweening, inverse of - * %GTD_EASE_IN_QUART - * @GTD_EASE_IN_OUT_QUART: quartic tweening, combining - * %GTD_EASE_IN_QUART and %GTD_EASE_OUT_QUART - * @GTD_EASE_IN_QUINT: quintic tweening - * @GTD_EASE_OUT_QUINT: quintic tweening, inverse of - * %GTD_EASE_IN_QUINT - * @GTD_EASE_IN_OUT_QUINT: fifth power tweening, combining - * %GTD_EASE_IN_QUINT and %GTD_EASE_OUT_QUINT - * @GTD_EASE_IN_SINE: sinusoidal tweening - * @GTD_EASE_OUT_SINE: sinusoidal tweening, inverse of - * %GTD_EASE_IN_SINE - * @GTD_EASE_IN_OUT_SINE: sine wave tweening, combining - * %GTD_EASE_IN_SINE and %GTD_EASE_OUT_SINE - * @GTD_EASE_IN_EXPO: exponential tweening - * @GTD_EASE_OUT_EXPO: exponential tweening, inverse of - * %GTD_EASE_IN_EXPO - * @GTD_EASE_IN_OUT_EXPO: exponential tweening, combining - * %GTD_EASE_IN_EXPO and %GTD_EASE_OUT_EXPO - * @GTD_EASE_IN_CIRC: circular tweening - * @GTD_EASE_OUT_CIRC: circular tweening, inverse of - * %GTD_EASE_IN_CIRC - * @GTD_EASE_IN_OUT_CIRC: circular tweening, combining - * %GTD_EASE_IN_CIRC and %GTD_EASE_OUT_CIRC - * @GTD_EASE_IN_ELASTIC: elastic tweening, with offshoot on start - * @GTD_EASE_OUT_ELASTIC: elastic tweening, with offshoot on end - * @GTD_EASE_IN_OUT_ELASTIC: elastic tweening with offshoot on both ends - * @GTD_EASE_IN_BACK: overshooting cubic tweening, with - * backtracking on start - * @GTD_EASE_OUT_BACK: overshooting cubic tweening, with - * backtracking on end - * @GTD_EASE_IN_OUT_BACK: overshooting cubic tweening, with - * backtracking on both ends - * @GTD_EASE_IN_BOUNCE: exponentially decaying parabolic (bounce) - * tweening, with bounce on start - * @GTD_EASE_OUT_BOUNCE: exponentially decaying parabolic (bounce) - * tweening, with bounce on end - * @GTD_EASE_IN_OUT_BOUNCE: exponentially decaying parabolic (bounce) - * tweening, with bounce on both ends - * @GTD_ANIMATION_LAST: last animation mode, used as a guard for - * registered global alpha functions - * - * The animation modes used by #ClutterAnimatable. This - * enumeration can be expanded in later versions of Clutter. - * - * <figure id="easing-modes"> - * <title>Easing modes provided by Clutter</title> - * <graphic fileref="easing-modes.png" format="PNG"/> - * </figure> - * - * Every global alpha function registered using clutter_alpha_register_func() - * or clutter_alpha_register_closure() will have a logical id greater than - * %GTD_ANIMATION_LAST. - * - * Since: 1.0 - */ -typedef enum -{ - GTD_CUSTOM_MODE = 0, - - /* linear */ - GTD_EASE_LINEAR, - - /* quadratic */ - GTD_EASE_IN_QUAD, - GTD_EASE_OUT_QUAD, - GTD_EASE_IN_OUT_QUAD, - - /* cubic */ - GTD_EASE_IN_CUBIC, - GTD_EASE_OUT_CUBIC, - GTD_EASE_IN_OUT_CUBIC, - - /* quartic */ - GTD_EASE_IN_QUART, - GTD_EASE_OUT_QUART, - GTD_EASE_IN_OUT_QUART, - - /* quintic */ - GTD_EASE_IN_QUINT, - GTD_EASE_OUT_QUINT, - GTD_EASE_IN_OUT_QUINT, - - /* sinusoidal */ - GTD_EASE_IN_SINE, - GTD_EASE_OUT_SINE, - GTD_EASE_IN_OUT_SINE, - - /* exponential */ - GTD_EASE_IN_EXPO, - GTD_EASE_OUT_EXPO, - GTD_EASE_IN_OUT_EXPO, - - /* circular */ - GTD_EASE_IN_CIRC, - GTD_EASE_OUT_CIRC, - GTD_EASE_IN_OUT_CIRC, - - /* elastic */ - GTD_EASE_IN_ELASTIC, - GTD_EASE_OUT_ELASTIC, - GTD_EASE_IN_OUT_ELASTIC, - - /* overshooting cubic */ - GTD_EASE_IN_BACK, - GTD_EASE_OUT_BACK, - GTD_EASE_IN_OUT_BACK, - - /* exponentially decaying parabolic */ - GTD_EASE_IN_BOUNCE, - GTD_EASE_OUT_BOUNCE, - GTD_EASE_IN_OUT_BOUNCE, - - /* guard, before registered alpha functions */ - GTD_EASE_LAST -} GtdEaseMode; - -/** - * GtdTimelineDirection: - * @GTD_TIMELINE_FORWARD: forward direction for a timeline - * @GTD_TIMELINE_BACKWARD: backward direction for a timeline - * - * The direction of a #GtdTimeline - */ -typedef enum -{ - GTD_TIMELINE_FORWARD, - GTD_TIMELINE_BACKWARD -} GtdTimelineDirection; - -G_END_DECLS diff --git a/src/animation/gtd-animation-utils.c b/src/animation/gtd-animation-utils.c deleted file mode 100644 index 7ab2198b..00000000 --- a/src/animation/gtd-animation-utils.c +++ /dev/null @@ -1,168 +0,0 @@ -/* 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); -} diff --git a/src/animation/gtd-animation-utils.h b/src/animation/gtd-animation-utils.h deleted file mode 100644 index b41bc121..00000000 --- a/src/animation/gtd-animation-utils.h +++ /dev/null @@ -1,65 +0,0 @@ -/* gtd-animation-utils.h - * - * 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 - */ - -#pragma once - -#include <glib-object.h> - -G_BEGIN_DECLS - - -/** - * GtdProgressFunc: - * @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 #GtdInterval if the - * type of the values of the interval was registered using - * gtd_interval_register_progress_func(). - * - * Return value: %TRUE if the function successfully computed - * the value and stored it inside @retval - */ -typedef gboolean (* GtdProgressFunc) (const GValue *a, - const GValue *b, - gdouble progress, - GValue *retval); - -void gtd_interval_register_progress_func (GType value_type, - GtdProgressFunc func); - - -gboolean gtd_has_progress_function (GType gtype); -gboolean gtd_run_progress_function (GType gtype, - const GValue *initial, - const GValue *final, - gdouble progress, - GValue *retval); - -G_END_DECLS diff --git a/src/animation/gtd-easing.c b/src/animation/gtd-easing.c deleted file mode 100644 index c674f91d..00000000 --- a/src/animation/gtd-easing.c +++ /dev/null @@ -1,474 +0,0 @@ -/* gtd-easing.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-easing.h" - -#include <math.h> - -gdouble -gtd_linear (gdouble t, - gdouble d) -{ - return t / d; -} - -gdouble -gtd_ease_in_quad (gdouble t, - gdouble d) -{ - gdouble p = t / d; - - return p * p; -} - -gdouble -gtd_ease_out_quad (gdouble t, - gdouble d) -{ - gdouble p = t / d; - - return -1.0 * p * (p - 2); -} - -gdouble -gtd_ease_in_out_quad (gdouble t, - gdouble d) -{ - gdouble p = t / (d / 2); - - if (p < 1) - return 0.5 * p * p; - - p -= 1; - - return -0.5 * (p * (p - 2) - 1); -} - -gdouble -gtd_ease_in_cubic (gdouble t, - gdouble d) -{ - gdouble p = t / d; - - return p * p * p; -} - -gdouble -gtd_ease_out_cubic (gdouble t, - gdouble d) -{ - gdouble p = t / d - 1; - - return p * p * p + 1; -} - -gdouble -gtd_ease_in_out_cubic (gdouble t, - gdouble d) -{ - gdouble p = t / (d / 2); - - if (p < 1) - return 0.5 * p * p * p; - - p -= 2; - - return 0.5 * (p * p * p + 2); -} - -gdouble -gtd_ease_in_quart (gdouble t, - gdouble d) -{ - gdouble p = t / d; - - return p * p * p * p; -} - -gdouble -gtd_ease_out_quart (gdouble t, - gdouble d) -{ - gdouble p = t / d - 1; - - return -1.0 * (p * p * p * p - 1); -} - -gdouble -gtd_ease_in_out_quart (gdouble t, - gdouble d) -{ - gdouble p = t / (d / 2); - - if (p < 1) - return 0.5 * p * p * p * p; - - p -= 2; - - return -0.5 * (p * p * p * p - 2); -} - -gdouble -gtd_ease_in_quint (gdouble t, - gdouble d) - { - gdouble p = t / d; - - return p * p * p * p * p; -} - -gdouble -gtd_ease_out_quint (gdouble t, - gdouble d) -{ - gdouble p = t / d - 1; - - return p * p * p * p * p + 1; -} - -gdouble -gtd_ease_in_out_quint (gdouble t, - gdouble d) -{ - gdouble p = t / (d / 2); - - if (p < 1) - return 0.5 * p * p * p * p * p; - - p -= 2; - - return 0.5 * (p * p * p * p * p + 2); -} - -gdouble -gtd_ease_in_sine (gdouble t, - gdouble d) -{ - return -1.0 * cos (t / d * G_PI_2) + 1.0; -} - -gdouble -gtd_ease_out_sine (gdouble t, - gdouble d) -{ - return sin (t / d * G_PI_2); -} - -gdouble -gtd_ease_in_out_sine (gdouble t, - gdouble d) -{ - return -0.5 * (cos (G_PI * t / d) - 1); -} - -gdouble -gtd_ease_in_expo (gdouble t, - gdouble d) -{ - return (t == 0) ? 0.0 : pow (2, 10 * (t / d - 1)); -} - -gdouble -gtd_ease_out_expo (gdouble t, - gdouble d) -{ - return (t == d) ? 1.0 : -pow (2, -10 * t / d) + 1; -} - -gdouble -gtd_ease_in_out_expo (gdouble t, - gdouble d) -{ - gdouble p; - - if (t == 0) - return 0.0; - - if (t == d) - return 1.0; - - p = t / (d / 2); - - if (p < 1) - return 0.5 * pow (2, 10 * (p - 1)); - - p -= 1; - - return 0.5 * (-pow (2, -10 * p) + 2); -} - -gdouble -gtd_ease_in_circ (gdouble t, - gdouble d) -{ - gdouble p = t / d; - - return -1.0 * (sqrt (1 - p * p) - 1); -} - -gdouble -gtd_ease_out_circ (gdouble t, - gdouble d) -{ - gdouble p = t / d - 1; - - return sqrt (1 - p * p); -} - -gdouble -gtd_ease_in_out_circ (gdouble t, - gdouble d) -{ - gdouble p = t / (d / 2); - - if (p < 1) - return -0.5 * (sqrt (1 - p * p) - 1); - - p -= 2; - - return 0.5 * (sqrt (1 - p * p) + 1); -} - -gdouble -gtd_ease_in_elastic (gdouble t, - gdouble d) -{ - gdouble p = d * .3; - gdouble s = p / 4; - gdouble q = t / d; - - if (q == 1) - return 1.0; - - q -= 1; - - return -(pow (2, 10 * q) * sin ((q * d - s) * (2 * G_PI) / p)); -} - -gdouble -gtd_ease_out_elastic (gdouble t, - gdouble d) -{ - gdouble p = d * .3; - gdouble s = p / 4; - gdouble q = t / d; - - if (q == 1) - return 1.0; - - return pow (2, -10 * q) * sin ((q * d - s) * (2 * G_PI) / p) + 1.0; -} - -gdouble -gtd_ease_in_out_elastic (gdouble t, - gdouble d) -{ - gdouble p = d * (.3 * 1.5); - gdouble s = p / 4; - gdouble q = t / (d / 2); - - if (q == 2) - return 1.0; - - if (q < 1) - { - q -= 1; - - return -.5 * (pow (2, 10 * q) * sin ((q * d - s) * (2 * G_PI) / p)); - } - else - { - q -= 1; - - return pow (2, -10 * q) - * sin ((q * d - s) * (2 * G_PI) / p) - * .5 + 1.0; - } -} - -gdouble -gtd_ease_in_back (gdouble t, - gdouble d) -{ - gdouble p = t / d; - - return p * p * ((1.70158 + 1) * p - 1.70158); -} - -gdouble -gtd_ease_out_back (gdouble t, - gdouble d) -{ - gdouble p = t / d - 1; - - return p * p * ((1.70158 + 1) * p + 1.70158) + 1; -} - -gdouble -gtd_ease_in_out_back (gdouble t, - gdouble d) -{ - gdouble p = t / (d / 2); - gdouble s = 1.70158 * 1.525; - - if (p < 1) - return 0.5 * (p * p * ((s + 1) * p - s)); - - p -= 2; - - return 0.5 * (p * p * ((s + 1) * p + s) + 2); -} - -static inline gdouble -ease_out_bounce_internal (gdouble t, - gdouble d) -{ - gdouble p = t / d; - - if (p < (1 / 2.75)) - { - return 7.5625 * p * p; - } - else if (p < (2 / 2.75)) - { - p -= (1.5 / 2.75); - - return 7.5625 * p * p + .75; - } - else if (p < (2.5 / 2.75)) - { - p -= (2.25 / 2.75); - - return 7.5625 * p * p + .9375; - } - else - { - p -= (2.625 / 2.75); - - return 7.5625 * p * p + .984375; - } -} - -static inline gdouble -ease_in_bounce_internal (gdouble t, - gdouble d) -{ - return 1.0 - ease_out_bounce_internal (d - t, d); -} - -gdouble -gtd_ease_in_bounce (gdouble t, - gdouble d) -{ - return ease_in_bounce_internal (t, d); -} - -gdouble -gtd_ease_out_bounce (gdouble t, - gdouble d) -{ - return ease_out_bounce_internal (t, d); -} - -gdouble -gtd_ease_in_out_bounce (gdouble t, - gdouble d) -{ - if (t < d / 2) - return ease_in_bounce_internal (t * 2, d) * 0.5; - else - return ease_out_bounce_internal (t * 2 - d, d) * 0.5 + 1.0 * 0.5; -} - -/*< private > - * _gtd_animation_modes: - * - * A mapping of animation modes and easing functions. - */ -static const struct { - GtdEaseMode mode; - GtdEaseFunc func; - const char *name; -} _gtd_animation_modes[] = { - { GTD_CUSTOM_MODE, NULL, "custom" }, - - { GTD_EASE_LINEAR, gtd_linear, "linear" }, - { GTD_EASE_IN_QUAD, gtd_ease_in_quad, "easeInQuad" }, - { GTD_EASE_OUT_QUAD, gtd_ease_out_quad, "easeOutQuad" }, - { GTD_EASE_IN_OUT_QUAD, gtd_ease_in_out_quad, "easeInOutQuad" }, - { GTD_EASE_IN_CUBIC, gtd_ease_in_cubic, "easeInCubic" }, - { GTD_EASE_OUT_CUBIC, gtd_ease_out_cubic, "easeOutCubic" }, - { GTD_EASE_IN_OUT_CUBIC, gtd_ease_in_out_cubic, "easeInOutCubic" }, - { GTD_EASE_IN_QUART, gtd_ease_in_quart, "easeInQuart" }, - { GTD_EASE_OUT_QUART, gtd_ease_out_quart, "easeOutQuart" }, - { GTD_EASE_IN_OUT_QUART, gtd_ease_in_out_quart, "easeInOutQuart" }, - { GTD_EASE_IN_QUINT, gtd_ease_in_quint, "easeInQuint" }, - { GTD_EASE_OUT_QUINT, gtd_ease_out_quint, "easeOutQuint" }, - { GTD_EASE_IN_OUT_QUINT, gtd_ease_in_out_quint, "easeInOutQuint" }, - { GTD_EASE_IN_SINE, gtd_ease_in_sine, "easeInSine" }, - { GTD_EASE_OUT_SINE, gtd_ease_out_sine, "easeOutSine" }, - { GTD_EASE_IN_OUT_SINE, gtd_ease_in_out_sine, "easeInOutSine" }, - { GTD_EASE_IN_EXPO, gtd_ease_in_expo, "easeInExpo" }, - { GTD_EASE_OUT_EXPO, gtd_ease_out_expo, "easeOutExpo" }, - { GTD_EASE_IN_OUT_EXPO, gtd_ease_in_out_expo, "easeInOutExpo" }, - { GTD_EASE_IN_CIRC, gtd_ease_in_circ, "easeInCirc" }, - { GTD_EASE_OUT_CIRC, gtd_ease_out_circ, "easeOutCirc" }, - { GTD_EASE_IN_OUT_CIRC, gtd_ease_in_out_circ, "easeInOutCirc" }, - { GTD_EASE_IN_ELASTIC, gtd_ease_in_elastic, "easeInElastic" }, - { GTD_EASE_OUT_ELASTIC, gtd_ease_out_elastic, "easeOutElastic" }, - { GTD_EASE_IN_OUT_ELASTIC, gtd_ease_in_out_elastic, "easeInOutElastic" }, - { GTD_EASE_IN_BACK, gtd_ease_in_back, "easeInBack" }, - { GTD_EASE_OUT_BACK, gtd_ease_out_back, "easeOutBack" }, - { GTD_EASE_IN_OUT_BACK, gtd_ease_in_out_back, "easeInOutBack" }, - { GTD_EASE_IN_BOUNCE, gtd_ease_in_bounce, "easeInBounce" }, - { GTD_EASE_OUT_BOUNCE, gtd_ease_out_bounce, "easeOutBounce" }, - { GTD_EASE_IN_OUT_BOUNCE, gtd_ease_in_out_bounce, "easeInOutBounce" }, - - { GTD_EASE_LAST, NULL, "sentinel" }, -}; - -GtdEaseFunc -gtd_get_easing_func_for_mode (GtdEaseMode mode) -{ - g_assert (_gtd_animation_modes[mode].mode == mode); - g_assert (_gtd_animation_modes[mode].func != NULL); - - return _gtd_animation_modes[mode].func; -} - -const char * -gtd_get_easing_name_for_mode (GtdEaseMode mode) -{ - g_assert (_gtd_animation_modes[mode].mode == mode); - g_assert (_gtd_animation_modes[mode].func != NULL); - - return _gtd_animation_modes[mode].name; -} - -gdouble -gtd_easing_for_mode (GtdEaseMode mode, - gdouble t, - gdouble d) -{ - g_assert (_gtd_animation_modes[mode].mode == mode); - g_assert (_gtd_animation_modes[mode].func != NULL); - - return _gtd_animation_modes[mode].func (t, d); -} diff --git a/src/animation/gtd-easing.h b/src/animation/gtd-easing.h deleted file mode 100644 index b83bb7f8..00000000 --- a/src/animation/gtd-easing.h +++ /dev/null @@ -1,141 +0,0 @@ -/* gtd-easing.h - * - * 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 - */ - -#pragma once - -#include <glib.h> - -#include "gtd-animation-enums.h" - -G_BEGIN_DECLS - -/** - * GtdEaseFunc: - * @t: elapsed time - * @d: total duration - * - * Internal type for the easing functions used by Gtd. - * - * Return value: the interpolated value, between -1.0 and 2.0 - */ -typedef gdouble (* GtdEaseFunc) (gdouble t, gdouble d); - -GtdEaseFunc gtd_get_easing_func_for_mode (GtdEaseMode mode); - -const gchar* gtd_get_easing_name_for_mode (GtdEaseMode mode); - -gdouble gtd_easing_for_mode (GtdEaseMode mode, - gdouble t, - gdouble d); - -gdouble gtd_ease_linear (gdouble t, - gdouble d); - -gdouble gtd_ease_in_quad (gdouble t, - gdouble d); - -gdouble gtd_ease_out_quad (gdouble t, - gdouble d); - -gdouble gtd_ease_in_out_quad (gdouble t, - gdouble d); - -gdouble gtd_ease_in_cubic (gdouble t, - gdouble d); - -gdouble gtd_ease_out_cubic (gdouble t, - gdouble d); - -gdouble gtd_ease_in_out_cubic (gdouble t, - gdouble d); - -gdouble gtd_ease_in_quart (gdouble t, - gdouble d); - -gdouble gtd_ease_out_quart (gdouble t, - gdouble d); - -gdouble gtd_ease_in_out_quart (gdouble t, - gdouble d); - -gdouble gtd_ease_in_quint (gdouble t, - gdouble d); - -gdouble gtd_ease_out_quint (gdouble t, - gdouble d); - -gdouble gtd_ease_in_out_quint (gdouble t, - gdouble d); - -gdouble gtd_ease_in_sine (gdouble t, - gdouble d); - -gdouble gtd_ease_out_sine (gdouble t, - gdouble d); - -gdouble gtd_ease_in_out_sine (gdouble t, - gdouble d); - -gdouble gtd_ease_in_expo (gdouble t, - gdouble d); - -gdouble gtd_ease_out_expo (gdouble t, - gdouble d); - -gdouble gtd_ease_in_out_expo (gdouble t, - gdouble d); - -gdouble gtd_ease_in_circ (gdouble t, - gdouble d); - -gdouble gtd_ease_out_circ (gdouble t, - gdouble d); - -gdouble gtd_ease_in_out_circ (gdouble t, - gdouble d); - -gdouble gtd_ease_in_elastic (gdouble t, - gdouble d); - -gdouble gtd_ease_out_elastic (gdouble t, - gdouble d); - -gdouble gtd_ease_in_out_elastic (gdouble t, - gdouble d); - -gdouble gtd_ease_in_back (gdouble t, - gdouble d); - -gdouble gtd_ease_out_back (gdouble t, - gdouble d); - -gdouble gtd_ease_in_out_back (gdouble t, - gdouble d); - -gdouble gtd_ease_in_bounce (gdouble t, - gdouble d); - -gdouble gtd_ease_out_bounce (gdouble t, - gdouble d); - -gdouble gtd_ease_in_out_bounce (gdouble t, - gdouble d); - -G_END_DECLS diff --git a/src/animation/gtd-interval.c b/src/animation/gtd-interval.c deleted file mode 100644 index 20efd826..00000000 --- a/src/animation/gtd-interval.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* gtd-interval.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 - */ - - -/** - * SECTION:clutter-interval - * @short_description: An object holding an interval of two values - * - * #GtdInterval is a simple object that can hold two values - * defining an interval. #GtdInterval can hold any value that - * can be enclosed inside a #GValue. - * - * Once a #GtdInterval for a specific #GType has been instantiated - * the #GtdInterval:value-type property cannot be changed anymore. - * - * #GtdInterval starts with a floating reference; this means that - * any object taking a reference on a #GtdInterval instance should - * also take ownership of the interval by using g_object_ref_sink(). - * - * #GtdInterval can be subclassed to override the validation - * and value computation. - * - * #GtdInterval is available since Gtd 1.0 - */ - -#include "gtd-interval.h" - -#include "gtd-animation-utils.h" -#include "gtd-easing.h" - -#include <stdlib.h> -#include <string.h> - -#include <glib.h> -#include <glib-object.h> -#include <gobject/gvaluecollector.h> - -enum -{ - PROP_0, - PROP_VALUE_TYPE, - PROP_INITIAL, - PROP_FINAL, - PROP_LAST, -}; - -static GParamSpec *obj_props[PROP_LAST]; - -enum -{ - INITIAL, - FINAL, - RESULT, - N_VALUES, -}; - -typedef struct -{ - GType value_type; - - GValue *values; -} GtdIntervalPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (GtdInterval, gtd_interval, G_TYPE_INITIALLY_UNOWNED); - - -static gboolean -gtd_interval_real_validate (GtdInterval *self, - GParamSpec *pspec) -{ - GType pspec_gtype = G_PARAM_SPEC_VALUE_TYPE (pspec); - - /* then check the fundamental types */ - switch (G_TYPE_FUNDAMENTAL (pspec_gtype)) - { - case G_TYPE_INT: - { - GParamSpecInt *pspec_int = G_PARAM_SPEC_INT (pspec); - gint a, b; - - a = b = 0; - gtd_interval_get_interval (self, &a, &b); - if ((a >= pspec_int->minimum && a <= pspec_int->maximum) && - (b >= pspec_int->minimum && b <= pspec_int->maximum)) - return TRUE; - else - return FALSE; - } - break; - - case G_TYPE_INT64: - { - GParamSpecInt64 *pspec_int = G_PARAM_SPEC_INT64 (pspec); - gint64 a, b; - - a = b = 0; - gtd_interval_get_interval (self, &a, &b); - if ((a >= pspec_int->minimum && a <= pspec_int->maximum) && - (b >= pspec_int->minimum && b <= pspec_int->maximum)) - return TRUE; - else - return FALSE; - } - break; - - case G_TYPE_UINT: - { - GParamSpecUInt *pspec_uint = G_PARAM_SPEC_UINT (pspec); - guint a, b; - - a = b = 0; - gtd_interval_get_interval (self, &a, &b); - if ((a >= pspec_uint->minimum && a <= pspec_uint->maximum) && - (b >= pspec_uint->minimum && b <= pspec_uint->maximum)) - return TRUE; - else - return FALSE; - } - break; - - case G_TYPE_UINT64: - { - GParamSpecUInt64 *pspec_int = G_PARAM_SPEC_UINT64 (pspec); - guint64 a, b; - - a = b = 0; - gtd_interval_get_interval (self, &a, &b); - if ((a >= pspec_int->minimum && a <= pspec_int->maximum) && - (b >= pspec_int->minimum && b <= pspec_int->maximum)) - return TRUE; - else - return FALSE; - } - break; - - case G_TYPE_CHAR: - { - GParamSpecChar *pspec_char = G_PARAM_SPEC_CHAR (pspec); - guchar a, b; - - a = b = 0; - gtd_interval_get_interval (self, &a, &b); - if ((a >= pspec_char->minimum && a <= pspec_char->maximum) && - (b >= pspec_char->minimum && b <= pspec_char->maximum)) - return TRUE; - else - return FALSE; - } - break; - - case G_TYPE_UCHAR: - { - GParamSpecUChar *pspec_uchar = G_PARAM_SPEC_UCHAR (pspec); - guchar a, b; - - a = b = 0; - gtd_interval_get_interval (self, &a, &b); - if ((a >= pspec_uchar->minimum && a <= pspec_uchar->maximum) && - (b >= pspec_uchar->minimum && b <= pspec_uchar->maximum)) - return TRUE; - else - return FALSE; - } - break; - - case G_TYPE_FLOAT: - { - GParamSpecFloat *pspec_flt = G_PARAM_SPEC_FLOAT (pspec); - float a, b; - - a = b = 0.f; - gtd_interval_get_interval (self, &a, &b); - if ((a >= pspec_flt->minimum && a <= pspec_flt->maximum) && - (b >= pspec_flt->minimum && b <= pspec_flt->maximum)) - return TRUE; - else - return FALSE; - } - break; - - case G_TYPE_DOUBLE: - { - GParamSpecDouble *pspec_flt = G_PARAM_SPEC_DOUBLE (pspec); - double a, b; - - a = b = 0; - gtd_interval_get_interval (self, &a, &b); - if ((a >= pspec_flt->minimum && a <= pspec_flt->maximum) && - (b >= pspec_flt->minimum && b <= pspec_flt->maximum)) - return TRUE; - else - return FALSE; - } - break; - - case G_TYPE_BOOLEAN: - return TRUE; - - default: - break; - } - - return TRUE; -} - -static gboolean -gtd_interval_real_compute_value (GtdInterval *self, - gdouble factor, - GValue *value) -{ - GValue *initial, *final; - GType value_type; - gboolean retval = FALSE; - - initial = gtd_interval_peek_initial_value (self); - final = gtd_interval_peek_final_value (self); - - value_type = gtd_interval_get_value_type (self); - - if (gtd_has_progress_function (value_type)) - { - retval = gtd_run_progress_function (value_type, initial, final, factor, value); - if (retval) - return TRUE; - } - - switch (G_TYPE_FUNDAMENTAL (value_type)) - { - case G_TYPE_INT: - { - gint ia, ib, res; - - ia = g_value_get_int (initial); - ib = g_value_get_int (final); - - res = (factor * (ib - ia)) + ia; - - g_value_set_int (value, res); - - retval = TRUE; - } - break; - - case G_TYPE_CHAR: - { - gchar ia, ib, res; - - ia = g_value_get_schar (initial); - ib = g_value_get_schar (final); - - res = (factor * (ib - (gdouble) ia)) + ia; - - g_value_set_schar (value, res); - - retval = TRUE; - } - break; - - case G_TYPE_UINT: - { - guint ia, ib, res; - - ia = g_value_get_uint (initial); - ib = g_value_get_uint (final); - - res = (factor * (ib - (gdouble) ia)) + ia; - - g_value_set_uint (value, res); - - retval = TRUE; - } - break; - - case G_TYPE_UCHAR: - { - guchar ia, ib, res; - - ia = g_value_get_uchar (initial); - ib = g_value_get_uchar (final); - - res = (factor * (ib - (gdouble) ia)) + ia; - - g_value_set_uchar (value, res); - - retval = TRUE; - } - break; - - case G_TYPE_FLOAT: - case G_TYPE_DOUBLE: - { - gdouble ia, ib, res; - - if (value_type == G_TYPE_DOUBLE) - { - ia = g_value_get_double (initial); - ib = g_value_get_double (final); - } - else - { - ia = g_value_get_float (initial); - ib = g_value_get_float (final); - } - - res = (factor * (ib - ia)) + ia; - - if (value_type == G_TYPE_DOUBLE) - g_value_set_double (value, res); - else - g_value_set_float (value, res); - - retval = TRUE; - } - break; - - case G_TYPE_BOOLEAN: - if (factor > 0.5) - g_value_set_boolean (value, TRUE); - else - g_value_set_boolean (value, FALSE); - - retval = TRUE; - break; - - case G_TYPE_BOXED: - break; - - default: - break; - } - - /* We're trying to animate a property without knowing how to do that. Issue - * a warning with a hint to what could be done to fix that */ - if (G_UNLIKELY (retval == FALSE)) - { - g_warning ("%s: Could not compute progress between two %s. You can " - "register a progress function to instruct GtdInterval " - "how to deal with this GType", - G_STRLOC, - g_type_name (value_type)); - } - - return retval; -} - -static void -gtd_interval_finalize (GObject *object) -{ - GtdInterval *self = GTD_INTERVAL (object); - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - - if (G_IS_VALUE (&priv->values[INITIAL])) - g_value_unset (&priv->values[INITIAL]); - - if (G_IS_VALUE (&priv->values[FINAL])) - g_value_unset (&priv->values[FINAL]); - - if (G_IS_VALUE (&priv->values[RESULT])) - g_value_unset (&priv->values[RESULT]); - - g_free (priv->values); - - G_OBJECT_CLASS (gtd_interval_parent_class)->finalize (object); -} - -static void -gtd_interval_set_property (GObject *gobject, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtdInterval *self = GTD_INTERVAL (gobject); - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - - switch (prop_id) - { - case PROP_VALUE_TYPE: - priv->value_type = g_value_get_gtype (value); - break; - - case PROP_INITIAL: - if (g_value_get_boxed (value) != NULL) - gtd_interval_set_initial_value (self, g_value_get_boxed (value)); - else if (G_IS_VALUE (&priv->values[INITIAL])) - g_value_unset (&priv->values[INITIAL]); - break; - - case PROP_FINAL: - if (g_value_get_boxed (value) != NULL) - gtd_interval_set_final_value (self, g_value_get_boxed (value)); - else if (G_IS_VALUE (&priv->values[FINAL])) - g_value_unset (&priv->values[FINAL]); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - break; - } -} - -static void -gtd_interval_get_property (GObject *gobject, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtdIntervalPrivate *priv; - - priv = gtd_interval_get_instance_private (GTD_INTERVAL (gobject)); - - switch (prop_id) - { - case PROP_VALUE_TYPE: - g_value_set_gtype (value, priv->value_type); - break; - - case PROP_INITIAL: - if (G_IS_VALUE (&priv->values[INITIAL])) - g_value_set_boxed (value, &priv->values[INITIAL]); - break; - - case PROP_FINAL: - if (G_IS_VALUE (&priv->values[FINAL])) - g_value_set_boxed (value, &priv->values[FINAL]); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - break; - } -} - -static void -gtd_interval_class_init (GtdIntervalClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - klass->validate = gtd_interval_real_validate; - klass->compute_value = gtd_interval_real_compute_value; - - gobject_class->set_property = gtd_interval_set_property, - gobject_class->get_property = gtd_interval_get_property; - gobject_class->finalize = gtd_interval_finalize; - - /** - * GtdInterval:value-type: - * - * The type of the values in the interval. - */ - obj_props[PROP_VALUE_TYPE] = - g_param_spec_gtype ("value-type", - "Value Type", - "The type of the values in the interval", - G_TYPE_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - /** - * GtdInterval:initial: - * - * The initial value of the interval. - */ - obj_props[PROP_INITIAL] = - g_param_spec_boxed ("initial", - "Initial Value", - "Initial value of the interval", - G_TYPE_VALUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdInterval:final: - * - * The final value of the interval. - */ - obj_props[PROP_FINAL] = - g_param_spec_boxed ("final", - "Final Value", - "Final value of the interval", - G_TYPE_VALUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); -} - -static void -gtd_interval_init (GtdInterval *self) -{ - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - - priv->value_type = G_TYPE_INVALID; - priv->values = g_malloc0 (sizeof (GValue) * N_VALUES); -} - -static inline void -gtd_interval_set_value_internal (GtdInterval *self, - gint index_, - const GValue *value) -{ - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - GType value_type; - - g_assert (index_ >= INITIAL && index_ <= RESULT); - - if (G_IS_VALUE (&priv->values[index_])) - g_value_unset (&priv->values[index_]); - - g_value_init (&priv->values[index_], priv->value_type); - - value_type = G_VALUE_TYPE (value); - if (value_type != priv->value_type || - !g_type_is_a (value_type, priv->value_type)) - { - if (g_value_type_compatible (value_type, priv->value_type)) - { - g_value_copy (value, &priv->values[index_]); - return; - } - - if (g_value_type_transformable (value_type, priv->value_type)) - { - GValue transform = G_VALUE_INIT; - - g_value_init (&transform, priv->value_type); - - if (g_value_transform (value, &transform)) - g_value_copy (&transform, &priv->values[index_]); - else - { - g_warning ("%s: Unable to convert a value of type '%s' into " - "the value type '%s' of the interval.", - G_STRLOC, - g_type_name (value_type), - g_type_name (priv->value_type)); - } - - g_value_unset (&transform); - } - } - else - g_value_copy (value, &priv->values[index_]); -} - -static inline void -gtd_interval_get_value_internal (GtdInterval *self, - gint index_, - GValue *value) -{ - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - - g_assert (index_ >= INITIAL && index_ <= RESULT); - - g_value_copy (&priv->values[index_], value); -} - -static gboolean -gtd_interval_set_initial_internal (GtdInterval *self, - va_list *args) -{; - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - GType gtype = priv->value_type; - GValue value = G_VALUE_INIT; - gchar *error; - - /* initial value */ - G_VALUE_COLLECT_INIT (&value, gtype, *args, 0, &error); - - if (error) - { - g_warning ("%s: %s", G_STRLOC, error); - - /* we leak the value here as it might not be in a valid state - * given the error and calling g_value_unset() might lead to - * undefined behaviour - */ - g_free (error); - return FALSE; - } - - gtd_interval_set_value_internal (self, INITIAL, &value); - g_value_unset (&value); - - return TRUE; -} - -static gboolean -gtd_interval_set_final_internal (GtdInterval *self, - va_list *args) -{ - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - GType gtype = priv->value_type; - GValue value = G_VALUE_INIT; - gchar *error; - - /* initial value */ - G_VALUE_COLLECT_INIT (&value, gtype, *args, 0, &error); - - if (error) - { - g_warning ("%s: %s", G_STRLOC, error); - - /* we leak the value here as it might not be in a valid state - * given the error and calling g_value_unset() might lead to - * undefined behaviour - */ - g_free (error); - return FALSE; - } - - gtd_interval_set_value_internal (self, FINAL, &value); - g_value_unset (&value); - - return TRUE; -} - -static void -gtd_interval_get_interval_valist (GtdInterval *self, - va_list var_args) -{ - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - GType gtype = priv->value_type; - GValue value = G_VALUE_INIT; - gchar *error; - - /* initial value */ - g_value_init (&value, gtype); - gtd_interval_get_initial_value (self, &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); - return; - } - - g_value_unset (&value); - - /* final value */ - g_value_init (&value, gtype); - gtd_interval_get_final_value (self, &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); - return; - } - - g_value_unset (&value); -} - -/** - * gtd_interval_new: - * @gtype: the type of the values in the interval - * @...: the initial value and the final value of the interval - * - * Creates a new #GtdInterval holding values of type @gtype. - * - * This function avoids using a #GValue for the initial and final values - * of the interval: - * - * |[ - * interval = gtd_interval_new (G_TYPE_FLOAT, 0.0, 1.0); - * interval = gtd_interval_new (G_TYPE_BOOLEAN, FALSE, TRUE); - * interval = gtd_interval_new (G_TYPE_INT, 0, 360); - * ]| - * - * Return value: the newly created #GtdInterval - */ -GtdInterval * -gtd_interval_new (GType gtype, - ...) -{ - GtdInterval *retval; - va_list args; - - g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL); - - retval = g_object_new (GTD_TYPE_INTERVAL, "value-type", gtype, NULL); - - va_start (args, gtype); - - if (!gtd_interval_set_initial_internal (retval, &args)) - goto out; - - gtd_interval_set_final_internal (retval, &args); - -out: - va_end (args); - - return retval; -} - -/** - * gtd_interval_new_with_values: - * @gtype: the type of the values in the interval - * @initial: (allow-none): a #GValue holding the initial value of the interval - * @final: (allow-none): a #GValue holding the final value of the interval - * - * Creates a new #GtdInterval of type @gtype, between @initial - * and @final. - * - * This function is useful for language bindings. - * - * Return value: the newly created #GtdInterval - */ -GtdInterval * -gtd_interval_new_with_values (GType gtype, - const GValue *initial, - const GValue *final) -{ - g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL); - g_return_val_if_fail (initial == NULL || G_VALUE_TYPE (initial) == gtype, NULL); - g_return_val_if_fail (final == NULL || G_VALUE_TYPE (final) == gtype, NULL); - - return g_object_new (GTD_TYPE_INTERVAL, - "value-type", gtype, - "initial", initial, - "final", final, - NULL); -} - -/** - * gtd_interval_clone: - * @interval: a #GtdInterval - * - * Creates a copy of @interval. - * - * Return value: (transfer full): the newly created #GtdInterval - */ -GtdInterval * -gtd_interval_clone (GtdInterval *self) -{ - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - GtdInterval *retval; - GType gtype; - GValue *tmp; - - g_return_val_if_fail (GTD_IS_INTERVAL (self), NULL); - g_return_val_if_fail (priv->value_type != G_TYPE_INVALID, NULL); - - gtype = priv->value_type; - retval = g_object_new (GTD_TYPE_INTERVAL, "value-type", gtype, NULL); - - tmp = gtd_interval_peek_initial_value (self); - gtd_interval_set_initial_value (retval, tmp); - - tmp = gtd_interval_peek_final_value (self); - gtd_interval_set_final_value (retval, tmp); - - return retval; -} - -/** - * gtd_interval_get_value_type: - * @interval: a #GtdInterval - * - * Retrieves the #GType of the values inside @interval. - * - * Return value: the type of the value, or G_TYPE_INVALID - */ -GType -gtd_interval_get_value_type (GtdInterval *self) -{ - GtdIntervalPrivate *priv; - - g_return_val_if_fail (GTD_IS_INTERVAL (self), G_TYPE_INVALID); - - priv = gtd_interval_get_instance_private (self); - return priv->value_type; -} - -/** - * gtd_interval_set_initial_value: (rename-to gtd_interval_set_initial) - * @interval: a #GtdInterval - * @value: a #GValue - * - * Sets the initial value of @interval to @value. The value is copied - * inside the #GtdInterval. - */ -void -gtd_interval_set_initial_value (GtdInterval *self, - const GValue *value) -{ - g_return_if_fail (GTD_IS_INTERVAL (self)); - g_return_if_fail (value != NULL); - - gtd_interval_set_value_internal (self, INITIAL, value); -} - -/** - * gtd_interval_set_initial: (skip) - * @interval: a #GtdInterval - * @...: the initial value of the interval. - * - * Variadic arguments version of gtd_interval_set_initial_value(). - * - * This function is meant as a convenience for the C API. - * - * Language bindings should use gtd_interval_set_initial_value() - * instead. - */ -void -gtd_interval_set_initial (GtdInterval *self, - ...) -{ - va_list args; - - g_return_if_fail (GTD_IS_INTERVAL (self)); - - va_start (args, self); - gtd_interval_set_initial_internal (self, &args); - va_end (args); -} - -/** - * gtd_interval_get_initial_value: - * @interval: a #GtdInterval - * @value: (out caller-allocates): a #GValue - * - * Retrieves the initial value of @interval and copies - * it into @value. - * - * The passed #GValue must be initialized to the value held by - * the #GtdInterval. - */ -void -gtd_interval_get_initial_value (GtdInterval *self, - GValue *value) -{ - g_return_if_fail (GTD_IS_INTERVAL (self)); - g_return_if_fail (value != NULL); - - gtd_interval_get_value_internal (self, INITIAL, value); -} - -/** - * gtd_interval_peek_initial_value: - * @interval: a #GtdInterval - * - * Gets the pointer to the initial value of @interval - * - * Return value: (transfer none): the initial value of the interval. - * The value is owned by the #GtdInterval and it should not be - * modified or freed - */ -GValue * -gtd_interval_peek_initial_value (GtdInterval *self) -{ - GtdIntervalPrivate *priv; - - g_return_val_if_fail (GTD_IS_INTERVAL (self), NULL); - - priv = gtd_interval_get_instance_private (self); - return priv->values + INITIAL; -} - -/** - * gtd_interval_set_final_value: (rename-to gtd_interval_set_final) - * @interval: a #GtdInterval - * @value: a #GValue - * - * Sets the final value of @interval to @value. The value is - * copied inside the #GtdInterval. - */ -void -gtd_interval_set_final_value (GtdInterval *self, - const GValue *value) -{ - g_return_if_fail (GTD_IS_INTERVAL (self)); - g_return_if_fail (value != NULL); - - gtd_interval_set_value_internal (self, FINAL, value); -} - -/** - * gtd_interval_get_final_value: - * @interval: a #GtdInterval - * @value: (out caller-allocates): a #GValue - * - * Retrieves the final value of @interval and copies - * it into @value. - * - * The passed #GValue must be initialized to the value held by - * the #GtdInterval. - */ -void -gtd_interval_get_final_value (GtdInterval *self, - GValue *value) -{ - g_return_if_fail (GTD_IS_INTERVAL (self)); - g_return_if_fail (value != NULL); - - gtd_interval_get_value_internal (self, FINAL, value); -} - -/** - * gtd_interval_set_final: (skip) - * @interval: a #GtdInterval - * @...: the final value of the interval - * - * Variadic arguments version of gtd_interval_set_final_value(). - * - * This function is meant as a convenience for the C API. - * - * Language bindings should use gtd_interval_set_final_value() instead. - */ -void -gtd_interval_set_final (GtdInterval *self, - ...) -{ - va_list args; - - g_return_if_fail (GTD_IS_INTERVAL (self)); - - va_start (args, self); - gtd_interval_set_final_internal (self, &args); - va_end (args); -} - -/** - * gtd_interval_peek_final_value: - * @interval: a #GtdInterval - * - * Gets the pointer to the final value of @interval - * - * Return value: (transfer none): the final value of the interval. - * The value is owned by the #GtdInterval and it should not be - * modified or freed - */ -GValue * -gtd_interval_peek_final_value (GtdInterval *self) -{ - GtdIntervalPrivate *priv; - - g_return_val_if_fail (GTD_IS_INTERVAL (self), NULL); - - priv = gtd_interval_get_instance_private (self); - return priv->values + FINAL; -} - -/** - * gtd_interval_set_interval: - * @interval: a #GtdInterval - * @...: the initial and final values of the interval - * - * Variable arguments wrapper for gtd_interval_set_initial_value() - * and gtd_interval_set_final_value() that avoids using the - * #GValue arguments: - * - * |[ - * gtd_interval_set_interval (self, 0, 50); - * gtd_interval_set_interval (self, 1.0, 0.0); - * gtd_interval_set_interval (self, FALSE, TRUE); - * ]| - * - * This function is meant for the convenience of the C API; bindings - * should reimplement this function using the #GValue-based API. - */ -void -gtd_interval_set_interval (GtdInterval *self, - ...) -{ - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - va_list args; - - g_return_if_fail (GTD_IS_INTERVAL (self)); - g_return_if_fail (priv->value_type != G_TYPE_INVALID); - - va_start (args, self); - - if (!gtd_interval_set_initial_internal (self, &args)) - goto out; - - gtd_interval_set_final_internal (self, &args); - -out: - va_end (args); -} - -/** - * gtd_interval_get_interval: - * @interval: a #GtdInterval - * @...: return locations for the initial and final values of - * the interval - * - * Variable arguments wrapper for gtd_interval_get_initial_value() - * and gtd_interval_get_final_value() that avoids using the - * #GValue arguments: - * - * |[ - * gint a = 0, b = 0; - * gtd_interval_get_interval (self, &a, &b); - * ]| - * - * This function is meant for the convenience of the C API; bindings - * should reimplement this function using the #GValue-based API. - */ -void -gtd_interval_get_interval (GtdInterval *self, - ...) -{ - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - va_list args; - - g_return_if_fail (GTD_IS_INTERVAL (self)); - g_return_if_fail (priv->value_type != G_TYPE_INVALID); - - va_start (args, self); - gtd_interval_get_interval_valist (self, args); - va_end (args); -} - -/** - * gtd_interval_validate: - * @interval: a #GtdInterval - * @pspec: a #GParamSpec - * - * Validates the initial and final values of @interval against - * a #GParamSpec. - * - * Return value: %TRUE if the #GtdInterval is valid, %FALSE otherwise - */ -gboolean -gtd_interval_validate (GtdInterval *self, - GParamSpec *pspec) -{ - g_return_val_if_fail (GTD_IS_INTERVAL (self), FALSE); - g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE); - - return GTD_INTERVAL_GET_CLASS (self)->validate (self, pspec); -} - -/** - * gtd_interval_compute_value: - * @interval: a #GtdInterval - * @factor: the progress factor, between 0 and 1 - * @value: (out caller-allocates): return location for an initialized #GValue - * - * Computes the value between the @interval boundaries given the - * progress @factor and copies it into @value. - * - * Return value: %TRUE if the operation was successful - */ -gboolean -gtd_interval_compute_value (GtdInterval *self, - gdouble factor, - GValue *value) -{ - g_return_val_if_fail (GTD_IS_INTERVAL (self), FALSE); - g_return_val_if_fail (value != NULL, FALSE); - - return GTD_INTERVAL_GET_CLASS (self)->compute_value (self, factor, value); -} - -/** - * gtd_interval_compute: - * @interval: a #GtdInterval - * @factor: the progress factor, between 0 and 1 - * - * Computes the value between the @interval boundaries given the - * progress @factor - * - * Unlike gtd_interval_compute_value(), this function will - * return a const pointer to the computed value - * - * You should use this function if you immediately pass the computed - * value to another function that makes a copy of it, like - * g_object_set_property() - * - * Return value: (transfer none): a pointer to the computed value, - * or %NULL if the computation was not successfull - */ -const GValue * -gtd_interval_compute (GtdInterval *self, - gdouble factor) -{ - GtdIntervalPrivate *priv = gtd_interval_get_instance_private (self); - GValue *value; - gboolean res; - - g_return_val_if_fail (GTD_IS_INTERVAL (self), NULL); - - value = &(priv->values[RESULT]); - - if (G_VALUE_TYPE (value) == G_TYPE_INVALID) - g_value_init (value, priv->value_type); - - res = GTD_INTERVAL_GET_CLASS (self)->compute_value (self, factor, value); - - if (res) - return priv->values + RESULT; - - return NULL; -} - -/** - * gtd_interval_is_valid: - * @interval: a #GtdInterval - * - * Checks if the @interval has a valid initial and final values. - * - * Return value: %TRUE if the #GtdInterval has an initial and - * final values, and %FALSE otherwise - */ -gboolean -gtd_interval_is_valid (GtdInterval *self) -{ - GtdIntervalPrivate *priv; - - g_return_val_if_fail (GTD_IS_INTERVAL (self), FALSE); - - priv = gtd_interval_get_instance_private (self); - - return G_IS_VALUE (&priv->values[INITIAL]) && - G_IS_VALUE (&priv->values[FINAL]); -} diff --git a/src/animation/gtd-interval.h b/src/animation/gtd-interval.h deleted file mode 100644 index efcfb03b..00000000 --- a/src/animation/gtd-interval.h +++ /dev/null @@ -1,116 +0,0 @@ -/* gtd-interval.h - * - * 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 - */ - -#pragma once - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define GTD_TYPE_INTERVAL (gtd_interval_get_type()) -G_DECLARE_DERIVABLE_TYPE (GtdInterval, gtd_interval, GTD, INTERVAL, GInitiallyUnowned) - -/** - * GtdIntervalClass: - * @validate: virtual function for validating an interval - * using a #GParamSpec - * @compute_value: virtual function for computing the value - * inside an interval using an adimensional factor between 0 and 1 - * - * The #GtdIntervalClass contains only private data. - * - * Since: 1.0 - */ -struct _GtdIntervalClass -{ - /*< private >*/ - GInitiallyUnownedClass parent_class; - - /*< public >*/ - gboolean (* validate) (GtdInterval *self, - GParamSpec *pspec); - gboolean (* compute_value) (GtdInterval *self, - gdouble factor, - GValue *value); - - /*< private >*/ - /* padding for future expansion */ - void (*_gtd_reserved1) (void); - void (*_gtd_reserved2) (void); - void (*_gtd_reserved3) (void); - void (*_gtd_reserved4) (void); - void (*_gtd_reserved5) (void); - void (*_gtd_reserved6) (void); -}; - -GtdInterval* gtd_interval_new (GType gtype, - ...); - -GtdInterval* gtd_interval_new_with_values (GType gtype, - const GValue *initial, - const GValue *final); - - -GtdInterval* gtd_interval_clone (GtdInterval *self); - -GType gtd_interval_get_value_type (GtdInterval *self); - -void gtd_interval_set_initial (GtdInterval *self, - ...); - -void gtd_interval_set_initial_value (GtdInterval *self, - const GValue *value); - -void gtd_interval_get_initial_value (GtdInterval *self, - GValue *value); - -GValue* gtd_interval_peek_initial_value (GtdInterval *self); - -void gtd_interval_set_final (GtdInterval *self, - ...); - -void gtd_interval_set_final_value (GtdInterval *self, - const GValue *value); - -void gtd_interval_get_final_value (GtdInterval *self, - GValue *value); - -GValue* gtd_interval_peek_final_value (GtdInterval *self); - -void gtd_interval_set_interval (GtdInterval *self, - ...); - -void gtd_interval_get_interval (GtdInterval *self, - ...); - -gboolean gtd_interval_validate (GtdInterval *self, - GParamSpec *pspec); - -gboolean gtd_interval_compute_value (GtdInterval *self, - gdouble factor, - GValue *value); - -const GValue* gtd_interval_compute (GtdInterval *self, - gdouble factor); - -gboolean gtd_interval_is_valid (GtdInterval *self); - - -G_END_DECLS diff --git a/src/animation/gtd-keyframe-transition.c b/src/animation/gtd-keyframe-transition.c deleted file mode 100644 index a77fea2b..00000000 --- a/src/animation/gtd-keyframe-transition.c +++ /dev/null @@ -1,716 +0,0 @@ -/* gtd-keyframe-transition.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 - */ - -/** - * SECTION:gtd-keyframe-transition - * @Title: GtdKeyframeTransition - * @Short_Description: Keyframe property transition - * - * #GtdKeyframeTransition allows animating a property by defining - * "key frames": values at a normalized position on the transition - * duration. - * - * The #GtdKeyframeTransition interpolates the value of the property - * to which it's bound across these key values. - * - * Setting up a #GtdKeyframeTransition means providing the times, - * values, and easing modes between these key frames, for instance: - * - * |[ - * GtdTransition *keyframe; - * - * keyframe = gtd_keyframe_transition_new ("opacity"); - * gtd_transition_set_from (keyframe, G_TYPE_UINT, 255); - * gtd_transition_set_to (keyframe, G_TYPE_UINT, 0); - * gtd_keyframe_transition_set (GTD_KEYFRAME_TRANSITION (keyframe), - * G_TYPE_UINT, - * 1, /* number of key frames */ - * 0.5, 128, GTD_EASE_IN_OUT_CUBIC); - * ]| - * - * The example above sets up a keyframe transition for the #GtdActor:opacity - * property of a #GtdActor; the transition starts and sets the value of the - * property to fully transparent; between the start of the transition and its mid - * point, it will animate the property to half opacity, using an easy in/easy out - * progress. Once the transition reaches the mid point, it will linearly fade the - * actor out until it reaches the end of the transition. - * - * The #GtdKeyframeTransition will add an implicit key frame between the last - * and the 1.0 value, to interpolate to the final value of the transition's - * interval. - */ - -#include "gtd-keyframe-transition.h" - -#include "gtd-debug.h" -#include "gtd-easing.h" -#include "gtd-interval.h" -#include "gtd-timeline.h" - -#include <math.h> -#include <gobject/gvaluecollector.h> - -typedef struct _KeyFrame -{ - double key; - - double start; - double end; - - GtdEaseMode mode; - - GtdInterval *interval; -} KeyFrame; - -typedef struct -{ - GArray *frames; - - gint current_frame; -} GtdKeyframeTransitionPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (GtdKeyframeTransition, gtd_keyframe_transition, GTD_TYPE_PROPERTY_TRANSITION) - -static void -key_frame_free (gpointer data) -{ - if (data != NULL) - { - KeyFrame *key = data; - - g_object_unref (key->interval); - } -} - -static int -sort_by_key (gconstpointer a, - gconstpointer b) -{ - const KeyFrame *k_a = a; - const KeyFrame *k_b = b; - - if (fabs (k_a->key - k_b->key) < 0.0001) - return 0; - - if (k_a->key > k_b->key) - return 1; - - return -1; -} - -static inline void -gtd_keyframe_transition_sort_frames (GtdKeyframeTransition *self) -{ - GtdKeyframeTransitionPrivate *priv = gtd_keyframe_transition_get_instance_private (self); - - if (priv->frames != NULL) - g_array_sort (priv->frames, sort_by_key); -} - -static inline void -gtd_keyframe_transition_init_frames (GtdKeyframeTransition *self, - gssize n_key_frames) -{ - GtdKeyframeTransitionPrivate *priv = gtd_keyframe_transition_get_instance_private (self); - guint i; - - priv->frames = g_array_sized_new (FALSE, FALSE, - sizeof (KeyFrame), - n_key_frames); - g_array_set_clear_func (priv->frames, key_frame_free); - - /* we add an implicit key frame that goes to 1.0, so that the - * user doesn't have to do that an can simply add key frames - * in between 0.0 and 1.0 - */ - for (i = 0; i < n_key_frames + 1; i++) - { - KeyFrame frame; - - if (i == n_key_frames) - frame.key = 1.0; - else - frame.key = 0.0; - - frame.mode = GTD_EASE_LINEAR; - frame.interval = NULL; - - g_array_insert_val (priv->frames, i, frame); - } -} - -static inline void -gtd_keyframe_transition_update_frames (GtdKeyframeTransition *self) -{ - GtdKeyframeTransitionPrivate *priv = gtd_keyframe_transition_get_instance_private (self); - guint i; - - if (priv->frames == NULL) - return; - - for (i = 0; i < priv->frames->len; i++) - { - KeyFrame *cur_frame = &g_array_index (priv->frames, KeyFrame, i); - KeyFrame *prev_frame; - - if (i > 0) - prev_frame = &g_array_index (priv->frames, KeyFrame, i - 1); - else - prev_frame = NULL; - - if (prev_frame != NULL) - { - cur_frame->start = prev_frame->key; - - if (prev_frame->interval != NULL) - { - const GValue *value; - - value = gtd_interval_peek_final_value (prev_frame->interval); - - if (cur_frame->interval != NULL) - gtd_interval_set_initial_value (cur_frame->interval, value); - else - { - cur_frame->interval = - gtd_interval_new_with_values (G_VALUE_TYPE (value), value, NULL); - } - } - } - else - cur_frame->start = 0.0; - - cur_frame->end = cur_frame->key; - } -} - -static void -gtd_keyframe_transition_compute_value (GtdTransition *transition, - GtdAnimatable *animatable, - GtdInterval *interval, - gdouble progress) -{ - GtdKeyframeTransition *self = GTD_KEYFRAME_TRANSITION (transition); - GtdKeyframeTransitionPrivate *priv = gtd_keyframe_transition_get_instance_private (self); - GtdTimeline *timeline = GTD_TIMELINE (self); - GtdTransitionClass *parent_class; - GtdTimelineDirection direction; - GtdInterval *real_interval; - gdouble real_progress; - double t, d, p; - KeyFrame *cur_frame = NULL; - - real_interval = interval; - real_progress = progress; - - /* if we don't have any keyframe, we behave like our parent class */ - if (priv->frames == NULL) - goto out; - - direction = gtd_timeline_get_direction (timeline); - - /* we need a normalized linear value */ - t = gtd_timeline_get_elapsed_time (timeline); - d = gtd_timeline_get_duration (timeline); - p = t / d; - - if (priv->current_frame < 0) - { - if (direction == GTD_TIMELINE_FORWARD) - priv->current_frame = 0; - else - priv->current_frame = priv->frames->len - 1; - } - - cur_frame = &g_array_index (priv->frames, KeyFrame, priv->current_frame); - - /* skip to the next key frame, depending on the direction of the timeline */ - if (direction == GTD_TIMELINE_FORWARD) - { - if (p > cur_frame->end) - { - priv->current_frame = MIN (priv->current_frame + 1, - (gint) priv->frames->len - 1); - cur_frame = &g_array_index (priv->frames, KeyFrame, priv->current_frame); - } - } - else - { - if (p < cur_frame->start) - { - priv->current_frame = MAX (priv->current_frame - 1, 0); - - cur_frame = &g_array_index (priv->frames, KeyFrame, priv->current_frame); - } - } - - /* if we are at the boundaries of the transition, use the from and to - * value from the transition - */ - if (priv->current_frame == 0) - { - const GValue *value; - - value = gtd_interval_peek_initial_value (interval); - gtd_interval_set_initial_value (cur_frame->interval, value); - } - else if (priv->current_frame == (gint) priv->frames->len - 1) - { - const GValue *value; - - cur_frame->mode = gtd_timeline_get_progress_mode (timeline); - - value = gtd_interval_peek_final_value (interval); - gtd_interval_set_final_value (cur_frame->interval, value); - } - - /* update the interval to be used to interpolate the property */ - real_interval = cur_frame->interval; - - /* normalize the progress and apply the easing mode */ - real_progress = gtd_easing_for_mode (cur_frame->mode, - (p - cur_frame->start), - (cur_frame->end - cur_frame->start)); - -#ifdef GTD_ENABLE_DEBUG - if (GTD_HAS_DEBUG (ANIMATION)) - { - char *from, *to; - const GValue *value; - - value = gtd_interval_peek_initial_value (cur_frame->interval); - from = g_strdup_value_contents (value); - - value = gtd_interval_peek_final_value (cur_frame->interval); - to = g_strdup_value_contents (value); - - GTD_TRACE_MSG ("[animation] cur_frame [%d] => { %g, %s, %s %s %s } - " - "progress: %g, sub-progress: %g\n", - priv->current_frame, - cur_frame->key, - gtd_get_easing_name_for_mode (cur_frame->mode), - from, - direction == GTD_TIMELINE_FORWARD ? "->" : "<-", - to, - p, - real_progress); - - g_free (from); - g_free (to); - } -#endif /* GTD_ENABLE_DEBUG */ - -out: - parent_class = - GTD_TRANSITION_CLASS (gtd_keyframe_transition_parent_class); - parent_class->compute_value (transition, animatable, real_interval, real_progress); -} - -static void -gtd_keyframe_transition_started (GtdTimeline *timeline) -{ - GtdKeyframeTransition *self; - GtdKeyframeTransitionPrivate *priv; - - self = GTD_KEYFRAME_TRANSITION (timeline); - priv = gtd_keyframe_transition_get_instance_private (self); - - priv->current_frame = -1; - - gtd_keyframe_transition_sort_frames (self); - gtd_keyframe_transition_update_frames (self); -} - -static void -gtd_keyframe_transition_completed (GtdTimeline *timeline) -{ - GtdKeyframeTransition *self = GTD_KEYFRAME_TRANSITION (timeline); - GtdKeyframeTransitionPrivate *priv = gtd_keyframe_transition_get_instance_private (self); - - priv->current_frame = -1; -} - -static void -gtd_keyframe_transition_finalize (GObject *gobject) -{ - GtdKeyframeTransition *self = GTD_KEYFRAME_TRANSITION (gobject); - GtdKeyframeTransitionPrivate *priv = gtd_keyframe_transition_get_instance_private (self); - - if (priv->frames != NULL) - g_array_unref (priv->frames); - - G_OBJECT_CLASS (gtd_keyframe_transition_parent_class)->finalize (gobject); -} - -static void -gtd_keyframe_transition_class_init (GtdKeyframeTransitionClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GtdTimelineClass *timeline_class = GTD_TIMELINE_CLASS (klass); - GtdTransitionClass *transition_class = GTD_TRANSITION_CLASS (klass); - - gobject_class->finalize = gtd_keyframe_transition_finalize; - - timeline_class->started = gtd_keyframe_transition_started; - timeline_class->completed = gtd_keyframe_transition_completed; - - transition_class->compute_value = gtd_keyframe_transition_compute_value; -} - -static void -gtd_keyframe_transition_init (GtdKeyframeTransition *self) -{ -} - -/** - * gtd_keyframe_transition_new: - * @property_name: the property to animate - * - * Creates a new #GtdKeyframeTransition for @property_name. - * - * Return value: (transfer full): the newly allocated - * #GtdKeyframeTransition instance. Use g_object_unref() when - * done to free its resources. - * - * Since: 1.12 - */ -GtdTransition * -gtd_keyframe_transition_new (const gchar *property_name) -{ - return g_object_new (GTD_TYPE_KEYFRAME_TRANSITION, - "property-name", property_name, - NULL); -} - -/** - * gtd_keyframe_transition_set_key_frames: - * @transition: a #GtdKeyframeTransition - * @n_key_frames: the number of values - * @key_frames: (array length=n_key_frames): an array of keys between 0.0 - * and 1.0, one for each key frame - * - * Sets the keys for each key frame inside @transition. - * - * If @transition does not hold any key frame, @n_key_frames key frames - * will be created; if @transition already has key frames, @key_frames must - * have at least as many elements as the number of key frames. - * - * Since: 1.12 - */ -void -gtd_keyframe_transition_set_key_frames (GtdKeyframeTransition *self, - guint n_key_frames, - const gdouble *key_frames) -{ - GtdKeyframeTransitionPrivate *priv; - guint i; - - g_return_if_fail (GTD_IS_KEYFRAME_TRANSITION (self)); - g_return_if_fail (n_key_frames > 0); - g_return_if_fail (key_frames != NULL); - - priv = gtd_keyframe_transition_get_instance_private (self); - - if (priv->frames == NULL) - gtd_keyframe_transition_init_frames (self, n_key_frames); - else - g_return_if_fail (n_key_frames == priv->frames->len - 1); - - for (i = 0; i < n_key_frames; i++) - { - KeyFrame *frame = &g_array_index (priv->frames, KeyFrame, i); - - frame->key = key_frames[i]; - } -} - -/** - * gtd_keyframe_transition_set_values: - * @transition: a #GtdKeyframeTransition - * @n_values: the number of values - * @values: (array length=n_values): an array of values, one for each - * key frame - * - * Sets the values for each key frame inside @transition. - * - * If @transition does not hold any key frame, @n_values key frames will - * be created; if @transition already has key frames, @values must have - * at least as many elements as the number of key frames. - * - * Since: 1.12 - */ -void -gtd_keyframe_transition_set_values (GtdKeyframeTransition *self, - guint n_values, - const GValue *values) -{ - GtdKeyframeTransitionPrivate *priv; - guint i; - - g_return_if_fail (GTD_IS_KEYFRAME_TRANSITION (self)); - g_return_if_fail (n_values > 0); - g_return_if_fail (values != NULL); - - priv = gtd_keyframe_transition_get_instance_private (self); - - if (priv->frames == NULL) - gtd_keyframe_transition_init_frames (self, n_values); - else - g_return_if_fail (n_values == priv->frames->len - 1); - - for (i = 0; i < n_values; i++) - { - KeyFrame *frame = &g_array_index (priv->frames, KeyFrame, i); - - if (frame->interval) - gtd_interval_set_final_value (frame->interval, &values[i]); - else - frame->interval = - gtd_interval_new_with_values (G_VALUE_TYPE (&values[i]), NULL, - &values[i]); - } -} - -/** - * gtd_keyframe_transition_set_modes: - * @transition: a #GtdKeyframeTransition - * @n_modes: the number of easing modes - * @modes: (array length=n_modes): an array of easing modes, one for - * each key frame - * - * Sets the easing modes for each key frame inside @transition. - * - * If @transition does not hold any key frame, @n_modes key frames will - * be created; if @transition already has key frames, @modes must have - * at least as many elements as the number of key frames. - */ -void -gtd_keyframe_transition_set_modes (GtdKeyframeTransition *self, - guint n_modes, - const GtdEaseMode *modes) -{ - GtdKeyframeTransitionPrivate *priv; - guint i; - - g_return_if_fail (GTD_IS_KEYFRAME_TRANSITION (self)); - g_return_if_fail (n_modes > 0); - g_return_if_fail (modes != NULL); - - priv = gtd_keyframe_transition_get_instance_private (self); - - if (priv->frames == NULL) - gtd_keyframe_transition_init_frames (self, n_modes); - else - g_return_if_fail (n_modes == priv->frames->len - 1); - - for (i = 0; i < n_modes; i++) - { - KeyFrame *frame = &g_array_index (priv->frames, KeyFrame, i); - - frame->mode = modes[i]; - } -} - -/** - * gtd_keyframe_transition_set: (skip) - * @transition: a #GtdKeyframeTransition - * @gtype: the type of the values to use for the key frames - * @n_key_frames: the number of key frames between the initial - * and final values - * @...: a list of tuples, containing the key frame index, the value - * at the key frame, and the animation mode - * - * Sets the key frames of the @transition. - * - * This variadic arguments function is a convenience for C developers; - * language bindings should use gtd_keyframe_transition_set_key_frames(), - * gtd_keyframe_transition_set_modes(), and - * gtd_keyframe_transition_set_values() instead. - */ -void -gtd_keyframe_transition_set (GtdKeyframeTransition *self, - GType gtype, - guint n_key_frames, - ...) -{ - GtdKeyframeTransitionPrivate *priv; - va_list args; - guint i; - - g_return_if_fail (GTD_IS_KEYFRAME_TRANSITION (self)); - g_return_if_fail (gtype != G_TYPE_INVALID); - g_return_if_fail (n_key_frames > 0); - - priv = gtd_keyframe_transition_get_instance_private (self); - - if (priv->frames == NULL) - gtd_keyframe_transition_init_frames (self, n_key_frames); - else - g_return_if_fail (n_key_frames == priv->frames->len - 1); - - va_start (args, n_key_frames); - - for (i = 0; i < n_key_frames; i++) - { - KeyFrame *frame = &g_array_index (priv->frames, KeyFrame, i); - GValue value = G_VALUE_INIT; - char *error = NULL; - - frame->key = va_arg (args, gdouble); - - G_VALUE_COLLECT_INIT (&value, gtype, args, 0, &error); - if (error != NULL) - { - g_warning ("%s: %s", G_STRLOC, error); - g_free (error); - break; - } - - frame->mode = va_arg (args, GtdEaseMode); - - g_clear_object (&frame->interval); - frame->interval = gtd_interval_new_with_values (gtype, NULL, &value); - - g_value_unset (&value); - } - - va_end (args); -} - -/** - * gtd_keyframe_transition_clear: - * @transition: a #GtdKeyframeTransition - * - * Removes all key frames from @transition. - */ -void -gtd_keyframe_transition_clear (GtdKeyframeTransition *self) -{ - GtdKeyframeTransitionPrivate *priv; - - g_return_if_fail (GTD_IS_KEYFRAME_TRANSITION (self)); - - priv = gtd_keyframe_transition_get_instance_private (self); - if (priv->frames != NULL) - { - g_array_unref (priv->frames); - priv->frames = NULL; - } -} - -/** - * gtd_keyframe_transition_get_n_key_frames: - * @transition: a #GtdKeyframeTransition - * - * Retrieves the number of key frames inside @transition. - * - * Return value: the number of key frames - */ -guint -gtd_keyframe_transition_get_n_key_frames (GtdKeyframeTransition *self) -{ - GtdKeyframeTransitionPrivate *priv; - - g_return_val_if_fail (GTD_IS_KEYFRAME_TRANSITION (self), 0); - - priv = gtd_keyframe_transition_get_instance_private (self); - if (priv->frames == NULL) - return 0; - - return priv->frames->len - 1; -} - -/** - * gtd_keyframe_transition_set_key_frame: - * @transition: a #GtdKeyframeTransition - * @index_: the index of the key frame - * @key: the key of the key frame - * @mode: the easing mode of the key frame - * @value: a #GValue containing the value of the key frame - * - * Sets the details of the key frame at @index_ inside @transition. - * - * The @transition must already have a key frame at @index_, and @index_ - * must be smaller than the number of key frames inside @transition. - */ -void -gtd_keyframe_transition_set_key_frame (GtdKeyframeTransition *self, - guint index_, - double key, - GtdEaseMode mode, - const GValue *value) -{ - GtdKeyframeTransitionPrivate *priv; - KeyFrame *frame; - - g_return_if_fail (GTD_IS_KEYFRAME_TRANSITION (self)); - - priv = gtd_keyframe_transition_get_instance_private (self); - - g_return_if_fail (priv->frames != NULL); - g_return_if_fail (index_ < priv->frames->len - 1); - - frame = &g_array_index (priv->frames, KeyFrame, index_); - frame->key = key; - frame->mode = mode; - gtd_interval_set_final_value (frame->interval, value); -} - -/** - * gtd_keyframe_transition_get_key_frame: - * @transition: a #GtdKeyframeTransition - * @index_: the index of the key frame - * @key: (out) (allow-none): return location for the key, or %NULL - * @mode: (out) (allow-none): return location for the easing mode, or %NULL - * @value: (out caller-allocates): a #GValue initialized with the type of - * the values - * - * Retrieves the details of the key frame at @index_ inside @transition. - * - * The @transition must already have key frames set, and @index_ must be - * smaller than the number of key frames. - */ -void -gtd_keyframe_transition_get_key_frame (GtdKeyframeTransition *self, - guint index_, - double *key, - GtdEaseMode *mode, - GValue *value) -{ - GtdKeyframeTransitionPrivate *priv; - const KeyFrame *frame; - - g_return_if_fail (GTD_IS_KEYFRAME_TRANSITION (self)); - - priv = gtd_keyframe_transition_get_instance_private (self); - g_return_if_fail (priv->frames != NULL); - g_return_if_fail (index_ < priv->frames->len - 1); - - frame = &g_array_index (priv->frames, KeyFrame, index_); - - if (key != NULL) - *key = frame->key; - - if (mode != NULL) - *mode = frame->mode; - - if (value != NULL) - gtd_interval_get_final_value (frame->interval, value); -} diff --git a/src/animation/gtd-keyframe-transition.h b/src/animation/gtd-keyframe-transition.h deleted file mode 100644 index d3d50246..00000000 --- a/src/animation/gtd-keyframe-transition.h +++ /dev/null @@ -1,83 +0,0 @@ -/* gtd-keyframe-transition.h - * - * 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 - */ - -#pragma once - -#include "gtd-property-transition.h" - -G_BEGIN_DECLS - -#define GTD_TYPE_KEYFRAME_TRANSITION (gtd_keyframe_transition_get_type()) -G_DECLARE_DERIVABLE_TYPE (GtdKeyframeTransition, gtd_keyframe_transition, GTD, KEYFRAME_TRANSITION, GtdPropertyTransition) - -/** - * GtdKeyframeTransitionClass: - * - * The `GtdKeyframeTransitionClass` structure contains only - * private data. - * - * Since: 1.12 - */ -struct _GtdKeyframeTransitionClass -{ - /*< private >*/ - GtdPropertyTransitionClass parent_class; - - gpointer _padding[8]; -}; - - -GtdTransition* gtd_keyframe_transition_new (const gchar *property_name); - - -void gtd_keyframe_transition_set_key_frames (GtdKeyframeTransition *transition, - guint n_key_frames, - const gdouble *key_frames); - -void gtd_keyframe_transition_set_values (GtdKeyframeTransition *transition, - guint n_values, - const GValue *values); - -void gtd_keyframe_transition_set_modes (GtdKeyframeTransition *transition, - guint n_modes, - const GtdEaseMode *modes); - -void gtd_keyframe_transition_set (GtdKeyframeTransition *transition, - GType gtype, - guint n_key_frames, - ...); - -void gtd_keyframe_transition_set_key_frame (GtdKeyframeTransition *transition, - guint index_, - double key, - GtdEaseMode mode, - const GValue *value); - -void gtd_keyframe_transition_get_key_frame (GtdKeyframeTransition *transition, - guint index_, - double *key, - GtdEaseMode *mode, - GValue *value); - -guint gtd_keyframe_transition_get_n_key_frames (GtdKeyframeTransition *transition); - -void gtd_keyframe_transition_clear (GtdKeyframeTransition *transition); - -G_END_DECLS diff --git a/src/animation/gtd-property-transition.c b/src/animation/gtd-property-transition.c deleted file mode 100644 index f0ceb883..00000000 --- a/src/animation/gtd-property-transition.c +++ /dev/null @@ -1,359 +0,0 @@ -/* gtd-property-transition.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 - */ - - -/** - * SECTION:gtd-property-transition - * @Title: GtdPropertyTransition - * @Short_Description: Property transitions - * - * #GtdPropertyTransition is a specialized #GtdTransition that - * can be used to tween a property of a #GtdAnimatable instance. - */ - -#include "gtd-property-transition.h" - -#include "gtd-animatable.h" -#include "gtd-debug.h" -#include "gtd-interval.h" -#include "gtd-transition.h" - -typedef struct -{ - gchar *property_name; - - GParamSpec *pspec; -} GtdPropertyTransitionPrivate; - -enum -{ - PROP_0, - PROP_PROPERTY_NAME, - PROP_LAST, -}; - -static GParamSpec *obj_props[PROP_LAST] = { NULL, }; - -G_DEFINE_TYPE_WITH_PRIVATE (GtdPropertyTransition, gtd_property_transition, GTD_TYPE_TRANSITION) - -static inline void -gtd_property_transition_ensure_interval (GtdPropertyTransition *self, - GtdAnimatable *animatable, - GtdInterval *interval) -{ - GtdPropertyTransitionPrivate *priv = gtd_property_transition_get_instance_private (self); - GValue *value_p; - - if (gtd_interval_is_valid (interval)) - return; - - /* if no initial value has been set, use the current value */ - value_p = gtd_interval_peek_initial_value (interval); - if (!G_IS_VALUE (value_p)) - { - g_value_init (value_p, gtd_interval_get_value_type (interval)); - gtd_animatable_get_initial_state (animatable, - priv->property_name, - value_p); - } - - /* if no final value has been set, use the current value */ - value_p = gtd_interval_peek_final_value (interval); - if (!G_IS_VALUE (value_p)) - { - g_value_init (value_p, gtd_interval_get_value_type (interval)); - gtd_animatable_get_initial_state (animatable, - priv->property_name, - value_p); - } -} - -static void -gtd_property_transition_attached (GtdTransition *transition, - GtdAnimatable *animatable) -{ - GtdPropertyTransition *self = GTD_PROPERTY_TRANSITION (transition); - GtdPropertyTransitionPrivate *priv = gtd_property_transition_get_instance_private (self); - GtdInterval *interval; - - if (priv->property_name == NULL) - return; - - priv->pspec = - gtd_animatable_find_property (animatable, priv->property_name); - - if (priv->pspec == NULL) - return; - - interval = gtd_transition_get_interval (transition); - if (interval == NULL) - return; - - gtd_property_transition_ensure_interval (self, animatable, interval); -} - -static void -gtd_property_transition_detached (GtdTransition *transition, - GtdAnimatable *animatable) -{ - GtdPropertyTransition *self = GTD_PROPERTY_TRANSITION (transition); - GtdPropertyTransitionPrivate *priv = gtd_property_transition_get_instance_private (self); - - priv->pspec = NULL; -} - -static void -gtd_property_transition_compute_value (GtdTransition *transition, - GtdAnimatable *animatable, - GtdInterval *interval, - gdouble progress) -{ - GtdPropertyTransition *self = GTD_PROPERTY_TRANSITION (transition); - GtdPropertyTransitionPrivate *priv = gtd_property_transition_get_instance_private (self); - GValue value = G_VALUE_INIT; - GType p_type, i_type; - gboolean res; - - /* if we have a GParamSpec we also have an animatable instance */ - if (priv->pspec == NULL) - return; - - gtd_property_transition_ensure_interval (self, animatable, interval); - - p_type = G_PARAM_SPEC_VALUE_TYPE (priv->pspec); - i_type = gtd_interval_get_value_type (interval); - - g_value_init (&value, i_type); - - res = gtd_animatable_interpolate_value (animatable, - priv->property_name, - interval, - progress, - &value); - - if (res) - { - if (i_type != p_type || g_type_is_a (i_type, p_type)) - { - if (g_value_type_transformable (i_type, p_type)) - { - GValue transform = G_VALUE_INIT; - - g_value_init (&transform, p_type); - - if (g_value_transform (&value, &transform)) - { - gtd_animatable_set_final_state (animatable, - priv->property_name, - &transform); - } - else - g_warning ("%s: Unable to convert a value of type '%s' from " - "the value type '%s' of the interval.", - G_STRLOC, - g_type_name (p_type), - g_type_name (i_type)); - - g_value_unset (&transform); - } - } - else - gtd_animatable_set_final_state (animatable, - priv->property_name, - &value); - } - - g_value_unset (&value); -} - -static void -gtd_property_transition_set_property (GObject *gobject, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtdPropertyTransition *self = GTD_PROPERTY_TRANSITION (gobject); - - switch (prop_id) - { - case PROP_PROPERTY_NAME: - gtd_property_transition_set_property_name (self, g_value_get_string (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - } -} - -static void -gtd_property_transition_get_property (GObject *gobject, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtdPropertyTransition *self = GTD_PROPERTY_TRANSITION (gobject); - GtdPropertyTransitionPrivate *priv = gtd_property_transition_get_instance_private (self); - - switch (prop_id) - { - case PROP_PROPERTY_NAME: - g_value_set_string (value, priv->property_name); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - } -} - -static void -gtd_property_transition_finalize (GObject *gobject) -{ - GtdPropertyTransition *self = GTD_PROPERTY_TRANSITION (gobject); - GtdPropertyTransitionPrivate *priv = gtd_property_transition_get_instance_private (self); - - g_free (priv->property_name); - - G_OBJECT_CLASS (gtd_property_transition_parent_class)->finalize (gobject); -} - -static void -gtd_property_transition_class_init (GtdPropertyTransitionClass *klass) -{ - GtdTransitionClass *transition_class = GTD_TRANSITION_CLASS (klass); - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - transition_class->attached = gtd_property_transition_attached; - transition_class->detached = gtd_property_transition_detached; - transition_class->compute_value = gtd_property_transition_compute_value; - - gobject_class->set_property = gtd_property_transition_set_property; - gobject_class->get_property = gtd_property_transition_get_property; - gobject_class->finalize = gtd_property_transition_finalize; - - /** - * GtdPropertyTransition:property-name: - * - * The name of the property of a #GtdAnimatable to animate. - */ - obj_props[PROP_PROPERTY_NAME] = - g_param_spec_string ("property-name", - "Property Name", - "The name of the property to animate", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); -} - -static void -gtd_property_transition_init (GtdPropertyTransition *self) -{ -} - -/** - * gtd_property_transition_new_for_actor: - * @actor: a #GtdActor - * @property_name: (allow-none): a property of @animatable, or %NULL - * - * Creates a new #GtdPropertyTransition. - * - * Return value: (transfer full): the newly created #GtdPropertyTransition. - * Use g_object_unref() when done - */ -GtdTransition * -gtd_property_transition_new_for_actor (GtdWidget *widget, - const char *property_name) -{ - return g_object_new (GTD_TYPE_PROPERTY_TRANSITION, - "widget", widget, - "property-name", property_name, - NULL); -} - -/** - * gtd_property_transition_new: - * @property_name: (allow-none): a property of @animatable, or %NULL - * - * Creates a new #GtdPropertyTransition. - * - * Return value: (transfer full): the newly created #GtdPropertyTransition. - * Use g_object_unref() when done - */ -GtdTransition * -gtd_property_transition_new (const char *property_name) -{ - return g_object_new (GTD_TYPE_PROPERTY_TRANSITION, - "property-name", property_name, - NULL); -} - -/** - * gtd_property_transition_set_property_name: - * @transition: a #GtdPropertyTransition - * @property_name: (allow-none): a property name - * - * Sets the #GtdPropertyTransition:property-name property of @transition. - */ -void -gtd_property_transition_set_property_name (GtdPropertyTransition *self, - const gchar *property_name) -{ - GtdPropertyTransitionPrivate *priv; - GtdAnimatable *animatable; - - g_return_if_fail (GTD_IS_PROPERTY_TRANSITION (self)); - - priv = gtd_property_transition_get_instance_private (self); - - if (g_strcmp0 (priv->property_name, property_name) == 0) - return; - - g_free (priv->property_name); - priv->property_name = g_strdup (property_name); - priv->pspec = NULL; - - animatable = gtd_transition_get_animatable (GTD_TRANSITION (self)); - if (animatable) - priv->pspec = gtd_animatable_find_property (animatable, priv->property_name); - - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PROPERTY_NAME]); -} - -/** - * gtd_property_transition_get_property_name: - * @transition: a #GtdPropertyTransition - * - * Retrieves the value of the #GtdPropertyTransition:property-name - * property. - * - * Return value: the name of the property being animated, or %NULL if - * none is set. The returned string is owned by the @transition and - * it should not be freed. - */ -const char * -gtd_property_transition_get_property_name (GtdPropertyTransition *self) -{ - GtdPropertyTransitionPrivate *priv; - - g_return_val_if_fail (GTD_IS_PROPERTY_TRANSITION (self), NULL); - - priv = gtd_property_transition_get_instance_private (self); - return priv->property_name; -} diff --git a/src/animation/gtd-property-transition.h b/src/animation/gtd-property-transition.h deleted file mode 100644 index 3b38ddac..00000000 --- a/src/animation/gtd-property-transition.h +++ /dev/null @@ -1,55 +0,0 @@ -/* gtd-property-transition.h - * - * 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 - */ - -#pragma once - -#include "gtd-transition.h" -#include "gtd-types.h" - -G_BEGIN_DECLS - -#define GTD_TYPE_PROPERTY_TRANSITION (gtd_property_transition_get_type()) -G_DECLARE_DERIVABLE_TYPE (GtdPropertyTransition, gtd_property_transition, GTD, PROPERTY_TRANSITION, GtdTransition) - -/** - * GtdPropertyTransitionClass: - * - * The #GtdPropertyTransitionClass structure - * contains private data. - */ -struct _GtdPropertyTransitionClass -{ - /*< private >*/ - GtdTransitionClass parent_class; - - gpointer _padding[8]; -}; - -GtdTransition * gtd_property_transition_new_for_widget (GtdWidget *widget, - const char *property_name); - -GtdTransition * gtd_property_transition_new (const char *property_name); - -void gtd_property_transition_set_property_name (GtdPropertyTransition *transition, - const char *property_name); - -const char * gtd_property_transition_get_property_name (GtdPropertyTransition *transition); - -G_END_DECLS diff --git a/src/animation/gtd-timeline.c b/src/animation/gtd-timeline.c deleted file mode 100644 index 54464048..00000000 --- a/src/animation/gtd-timeline.c +++ /dev/null @@ -1,1547 +0,0 @@ -/* - * Gtd. - * - * An OpenGL based 'interactive canvas' library. - * - * Authored By Matthew Allum <mallum@openedhand.com> - * - * Copyright (C) 2006 OpenedHand - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - */ - -/** - * SECTION:gtd-timeline - * @short_description: A class for time-based events - * - * #GtdTimeline is a base class for managing time-based event that cause - * GTK to redraw, such as animations. - * - * Each #GtdTimeline instance has a duration: once a timeline has been - * started, using gtd_timeline_start(), it will emit a signal that can - * be used to update the state of the widgets. - * - * It is important to note that #GtdTimeline is not a generic API for - * calling closures after an interval; each Timeline is tied into the master - * clock used to drive the frame cycle. If you need to schedule a closure - * after an interval, see gtd_threads_add_timeout() instead. - * - * Users of #GtdTimeline should connect to the #GtdTimeline::new-frame - * signal, which is emitted each time a timeline is advanced during the maste - * clock iteration. The #GtdTimeline::new-frame signal provides the time - * elapsed since the beginning of the timeline, in milliseconds. A normalized - * progress value can be obtained by calling gtd_timeline_get_progress(). - * By using gtd_timeline_get_delta() it is possible to obtain the wallclock - * time elapsed since the last emission of the #GtdTimeline::new-frame - * signal. - * - * Initial state can be set up by using the #GtdTimeline::started signal, - * while final state can be set up by using the #GtdTimeline::stopped - * signal. The #GtdTimeline guarantees the emission of at least a single - * #GtdTimeline::new-frame signal, as well as the emission of the - * #GtdTimeline::completed signal every time the #GtdTimeline reaches - * its #GtdTimeline:duration. - * - * It is possible to connect to specific points in the timeline progress by - * adding markers using gtd_timeline_add_marker_at_time() and connecting - * to the #GtdTimeline::marker-reached signal. - * - * Timelines can be made to loop once they reach the end of their duration, by - * using gtd_timeline_set_repeat_count(); a looping timeline will still - * emit the #GtdTimeline::completed signal once it reaches the end of its - * duration at each repeat. If you want to be notified of the end of the last - * repeat, use the #GtdTimeline::stopped signal. - * - * Timelines have a #GtdTimeline:direction: the default direction is - * %GTD_TIMELINE_FORWARD, and goes from 0 to the duration; it is possible - * to change the direction to %GTD_TIMELINE_BACKWARD, and have the timeline - * go from the duration to 0. The direction can be automatically reversed - * when reaching completion by using the #GtdTimeline:auto-reverse property. - * - * Timelines are used in the Gtd animation framework by classes like - * #GtdTransition. - */ - -#define G_LOG_DOMAIN "GtdTimeline" - -#include "gtd-debug.h" -#include "gtd-enum-types.h" -#include "gtd-timeline.h" -#include "gtd-widget.h" - -typedef struct -{ - GtdTimelineDirection direction; - - GtdWidget *widget; - guint frame_tick_id; - - gint64 duration_us; - gint64 delay_us; - - /* The current amount of elapsed time */ - gint64 elapsed_time_us; - - /* The elapsed time since the last frame was fired */ - gint64 delta_us; - - /* Time we last advanced the elapsed time and showed a frame */ - gint64 last_frame_time_us; - - gint64 start_us; - - /* How many times the timeline should repeat */ - gint repeat_count; - - /* The number of times the timeline has repeated */ - gint current_repeat; - - GtdTimelineProgressFunc progress_func; - gpointer progress_data; - GDestroyNotify progress_notify; - GtdEaseMode progress_mode; - - guint is_playing : 1; - - /* If we've just started playing and haven't yet gotten - * a tick from the master clock - */ - guint auto_reverse : 1; -} GtdTimelinePrivate; - -enum -{ - PROP_0, - - PROP_AUTO_REVERSE, - PROP_DELAY, - PROP_DURATION, - PROP_DIRECTION, - PROP_REPEAT_COUNT, - PROP_PROGRESS_MODE, - PROP_WIDGET, - - PROP_LAST -}; - -static GParamSpec *obj_props[PROP_LAST] = { NULL, }; - -enum -{ - NEW_FRAME, - STARTED, - PAUSED, - COMPLETED, - STOPPED, - - LAST_SIGNAL -}; - -static guint timeline_signals[LAST_SIGNAL] = { 0, }; - -static void set_is_playing (GtdTimeline *self, - gboolean is_playing); - -G_DEFINE_TYPE_WITH_PRIVATE (GtdTimeline, gtd_timeline, G_TYPE_OBJECT) - -static inline gint64 -us_to_ms (gint64 ms) -{ - return ms / 1000; -} - -static inline gint64 -ms_to_us (gint64 us) -{ - return us * 1000; -} - -static inline gboolean -is_waiting_for_delay (GtdTimeline *self, - gint64 frame_time_us) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - return priv->start_us + priv->delay_us > frame_time_us; -} - -static void -emit_frame_signal (GtdTimeline *self) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - gint64 elapsed_time_ms = us_to_ms (priv->elapsed_time_us); - - GTD_TRACE_MSG ("Emitting ::new-frame signal on timeline[%p]", self); - - g_signal_emit (self, timeline_signals[NEW_FRAME], 0, elapsed_time_ms); -} - -static gboolean -is_complete (GtdTimeline *self) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - - return (priv->direction == GTD_TIMELINE_FORWARD - ? priv->elapsed_time_us >= priv->duration_us - : priv->elapsed_time_us <= 0); -} - -static gboolean -maybe_loop_timeline (GtdTimeline *self) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - GtdTimelineDirection saved_direction = priv->direction; - gint64 overflow_us = priv->elapsed_time_us; - gint64 end_us; - - /* Update the current elapsed time in case the signal handlers - * want to take a peek. If we clamp elapsed time, then we need - * to correpondingly reduce elapsed_time_delta to reflect the correct - * range of times */ - if (priv->direction == GTD_TIMELINE_FORWARD) - priv->elapsed_time_us = priv->duration_us; - else if (priv->direction == GTD_TIMELINE_BACKWARD) - priv->elapsed_time_us = 0; - - end_us = priv->elapsed_time_us; - - /* Emit the signal */ - emit_frame_signal (self); - - /* Did the signal handler modify the elapsed time? */ - if (priv->elapsed_time_us != end_us) - return TRUE; - - /* Note: If the new-frame signal handler paused the timeline - * on the last frame we will still go ahead and send the - * completed signal */ - GTD_TRACE_MSG ("Timeline [%p] completed (cur: %ldµs, tot: %ldµs)", - self, - priv->elapsed_time_us, - priv->delta_us); - - if (priv->is_playing && - (priv->repeat_count == 0 || - priv->repeat_count == priv->current_repeat)) - { - /* We stop the timeline now, so that the completed signal handler - * may choose to re-start the timeline - */ - set_is_playing (self, FALSE); - - g_signal_emit (self, timeline_signals[COMPLETED], 0); - g_signal_emit (self, timeline_signals[STOPPED], 0, TRUE); - } - else - { - g_signal_emit (self, timeline_signals[COMPLETED], 0); - } - - priv->current_repeat += 1; - - if (priv->auto_reverse) - { - /* :auto-reverse changes the direction of the timeline */ - if (priv->direction == GTD_TIMELINE_FORWARD) - priv->direction = GTD_TIMELINE_BACKWARD; - else - priv->direction = GTD_TIMELINE_FORWARD; - - g_object_notify_by_pspec (G_OBJECT (self), - obj_props[PROP_DIRECTION]); - } - - /* - * Again check to see if the user has manually played with - * the elapsed time, before we finally stop or loop the timeline, - * except changing time from 0 -> duration (or vice-versa) - * since these are considered equivalent - */ - if (priv->elapsed_time_us != end_us && - !((priv->elapsed_time_us == 0 && end_us == priv->duration_us) || - (priv->elapsed_time_us == priv->duration_us && end_us == 0))) - { - return TRUE; - } - - if (priv->repeat_count == 0) - { - gtd_timeline_rewind (self); - return FALSE; - } - - /* Try and interpolate smoothly around a loop */ - if (saved_direction == GTD_TIMELINE_FORWARD) - priv->elapsed_time_us = overflow_us - priv->duration_us; - else - priv->elapsed_time_us = priv->duration_us + overflow_us; - - /* Or if the direction changed, we try and bounce */ - if (priv->direction != saved_direction) - priv->elapsed_time_us = priv->duration_us - priv->elapsed_time_us; - - return TRUE; -} - -static gboolean -tick_timeline (GtdTimeline *self, - gint64 tick_time_us) -{ - GtdTimelinePrivate *priv; - gboolean should_continue; - gboolean complete; - gint64 elapsed_us; - - priv = gtd_timeline_get_instance_private (self); - - GTD_TRACE_MSG ("Timeline [%p] ticked (elapsed_time: %ldµs, delta_us: %ldµs, " - "last_frame_time: %ldµs, tick_time: %ldµs)", - self, - priv->elapsed_time_us, - priv->delta_us, - priv->last_frame_time_us, - tick_time_us); - - /* Check the is_playing variable before performing the timeline tick. - * This is necessary, as if a timeline is stopped in response to a - * frame clock generated signal of a different timeline, this code can - * still be reached. - */ - if (!priv->is_playing) - return FALSE; - - elapsed_us = tick_time_us - priv->last_frame_time_us; - priv->last_frame_time_us = tick_time_us; - - if (is_waiting_for_delay (self, tick_time_us)) - { - GTD_TRACE_MSG ("- waiting for delay"); - return G_SOURCE_CONTINUE; - } - - /* if the clock rolled back between ticks we need to - * account for it; the best course of action, since the - * clock roll back can happen by any arbitrary amount - * of milliseconds, is to drop a frame here - */ - if (elapsed_us <= 0) - return TRUE; - - priv->delta_us = elapsed_us; - - GTD_TRACE_MSG ("Timeline [%p] activated (elapsed time: %ldµs, " - "duration: %ldµs, delta_us: %ldµs)", - self, - priv->elapsed_time_us, - priv->duration_us, - priv->delta_us); - - g_object_ref (self); - - /* Advance time */ - if (priv->direction == GTD_TIMELINE_FORWARD) - priv->elapsed_time_us += priv->delta_us; - else - priv->elapsed_time_us -= priv->delta_us; - - complete = is_complete (self); - should_continue = !complete ? priv->is_playing : maybe_loop_timeline (self); - - /* If we have not reached the end of the timeline */ - if (!complete) - emit_frame_signal (self); - - g_object_unref (self); - - return should_continue; -} - -static gboolean -frame_tick_cb (GtkWidget *widget, - GdkFrameClock *frame_clock, - gpointer user_data) -{ - GtdTimeline *self = GTD_TIMELINE (user_data); - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - gint64 frame_time_us; - - frame_time_us = gdk_frame_clock_get_frame_time (frame_clock); - - if (tick_timeline (self, frame_time_us)) - return G_SOURCE_CONTINUE; - - priv->frame_tick_id = 0; - return G_SOURCE_REMOVE; -} - -static void -add_tick_callback (GtdTimeline *self) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - - g_assert (!(priv->frame_tick_id > 0 && !priv->widget)); - - if (priv->frame_tick_id == 0) - { - priv->frame_tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (priv->widget), - frame_tick_cb, - self, - NULL); - } -} - -static void -remove_tick_callback (GtdTimeline *self) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - - g_assert (!(priv->frame_tick_id > 0 && !priv->widget)); - - if (priv->frame_tick_id > 0) - { - gtk_widget_remove_tick_callback (GTK_WIDGET (priv->widget), priv->frame_tick_id); - priv->frame_tick_id = 0; - } -} - -static void -set_is_playing (GtdTimeline *self, - gboolean is_playing) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - - is_playing = !!is_playing; - - if (is_playing == priv->is_playing) - return; - - priv->is_playing = is_playing; - - if (priv->is_playing) - { - priv->start_us = g_get_monotonic_time (); - priv->last_frame_time_us = priv->start_us; - priv->current_repeat = 0; - - add_tick_callback (self); - } - else - { - remove_tick_callback (self); - } -} - -static gdouble -timeline_progress_func (GtdTimeline *self, - gdouble elapsed, - gdouble duration, - gpointer user_data) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - - return gtd_easing_for_mode (priv->progress_mode, elapsed, duration); -} - - -/* - * GObject overrides - */ - -static void -gtd_timeline_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtdTimeline *self = GTD_TIMELINE (object); - - switch (prop_id) - { - case PROP_DELAY: - gtd_timeline_set_delay (self, g_value_get_uint (value)); - break; - - case PROP_DURATION: - gtd_timeline_set_duration (self, g_value_get_uint (value)); - break; - - case PROP_DIRECTION: - gtd_timeline_set_direction (self, g_value_get_enum (value)); - break; - - case PROP_AUTO_REVERSE: - gtd_timeline_set_auto_reverse (self, g_value_get_boolean (value)); - break; - - case PROP_REPEAT_COUNT: - gtd_timeline_set_repeat_count (self, g_value_get_int (value)); - break; - - case PROP_PROGRESS_MODE: - gtd_timeline_set_progress_mode (self, g_value_get_enum (value)); - break; - - case PROP_WIDGET: - gtd_timeline_set_widget (self, g_value_get_object (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gtd_timeline_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtdTimeline *self = GTD_TIMELINE (object); - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - - switch (prop_id) - { - case PROP_DELAY: - g_value_set_uint (value, us_to_ms (priv->delay_us)); - break; - - case PROP_DURATION: - g_value_set_uint (value, gtd_timeline_get_duration (self)); - break; - - case PROP_DIRECTION: - g_value_set_enum (value, priv->direction); - break; - - case PROP_AUTO_REVERSE: - g_value_set_boolean (value, priv->auto_reverse); - break; - - case PROP_REPEAT_COUNT: - g_value_set_int (value, priv->repeat_count); - break; - - case PROP_PROGRESS_MODE: - g_value_set_enum (value, priv->progress_mode); - break; - - case PROP_WIDGET: - g_value_set_object (value, priv->widget); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gtd_timeline_dispose (GObject *object) -{ - GtdTimeline *self = GTD_TIMELINE (object); - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - - if (priv->progress_notify != NULL) - { - priv->progress_notify (priv->progress_data); - priv->progress_func = NULL; - priv->progress_data = NULL; - priv->progress_notify = NULL; - } - - G_OBJECT_CLASS (gtd_timeline_parent_class)->dispose (object); -} - -static void -gtd_timeline_class_init (GtdTimelineClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - /** - * GtdTimeline::widget: - * - * The widget the timeline is associated with. This will determine what frame - * clock will drive it. - */ - obj_props[PROP_WIDGET] = - g_param_spec_object ("widget", - "Widget", - "Associated GtdWidget", - GTD_TYPE_WIDGET, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - /** - * GtdTimeline:delay: - * - * A delay, in milliseconds, that should be observed by the - * timeline before actually starting. - */ - obj_props[PROP_DELAY] = - g_param_spec_uint ("delay", - "Delay", - "Delay before start", - 0, G_MAXUINT, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdTimeline:duration: - * - * Duration of the timeline in milliseconds. - */ - obj_props[PROP_DURATION] = - g_param_spec_uint ("duration", - "Duration", - "Duration of the timeline in milliseconds", - 0, G_MAXUINT, - 1000, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdTimeline:direction:GIT - * - * The direction of the timeline, either %GTD_TIMELINE_FORWARD or - * %GTD_TIMELINE_BACKWARD. - */ - obj_props[PROP_DIRECTION] = - g_param_spec_enum ("direction", - "Direction", - "Direction of the timeline", - GTD_TYPE_TIMELINE_DIRECTION, - GTD_TIMELINE_FORWARD, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdTimeline:auto-reverse: - * - * If the direction of the timeline should be automatically reversed - * when reaching the end. - */ - obj_props[PROP_AUTO_REVERSE] = - g_param_spec_boolean ("auto-reverse", - "Auto Reverse", - "Whether the direction should be reversed when reaching the end", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdTimeline:repeat-count: - * - * Defines how many times the timeline should repeat. - * - * If the repeat count is 0, the timeline does not repeat. - * - * If the repeat count is set to -1, the timeline will repeat until it is - * stopped. - */ - obj_props[PROP_REPEAT_COUNT] = - g_param_spec_int ("repeat-count", - "Repeat Count", - "How many times the timeline should repeat", - -1, G_MAXINT, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdTimeline:progress-mode: - * - * Controls the way a #GtdTimeline computes the normalized progress. - */ - obj_props[PROP_PROGRESS_MODE] = - g_param_spec_enum ("progress-mode", - "Progress Mode", - "How the timeline should compute the progress", - GTD_TYPE_EASE_MODE, - GTD_EASE_LINEAR, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - object_class->dispose = gtd_timeline_dispose; - object_class->set_property = gtd_timeline_set_property; - object_class->get_property = gtd_timeline_get_property; - g_object_class_install_properties (object_class, PROP_LAST, obj_props); - - /** - * GtdTimeline::new-frame: - * @timeline: the timeline which received the signal - * @msecs: the elapsed time between 0 and duration - * - * The ::new-frame signal is emitted for each timeline running - * timeline before a new frame is drawn to give animations a chance - * to update the scene. - */ - timeline_signals[NEW_FRAME] = - g_signal_new ("new-frame", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtdTimelineClass, new_frame), - NULL, NULL, NULL, - G_TYPE_NONE, - 1, G_TYPE_INT); - /** - * GtdTimeline::completed: - * @timeline: the #GtdTimeline which received the signal - * - * The #GtdTimeline::completed signal is emitted when the timeline's - * elapsed time reaches the value of the #GtdTimeline:duration - * property. - * - * This signal will be emitted even if the #GtdTimeline is set to be - * repeating. - * - * If you want to get notification on whether the #GtdTimeline has - * been stopped or has finished its run, including its eventual repeats, - * you should use the #GtdTimeline::stopped signal instead. - */ - timeline_signals[COMPLETED] = - g_signal_new ("completed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtdTimelineClass, completed), - NULL, NULL, NULL, - G_TYPE_NONE, 0); - /** - * GtdTimeline::started: - * @timeline: the #GtdTimeline which received the signal - * - * The ::started signal is emitted when the timeline starts its run. - * This might be as soon as gtd_timeline_start() is invoked or - * after the delay set in the GtdTimeline:delay property has - * expired. - */ - timeline_signals[STARTED] = - g_signal_new ("started", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtdTimelineClass, started), - NULL, NULL, NULL, - G_TYPE_NONE, 0); - /** - * GtdTimeline::paused: - * @timeline: the #GtdTimeline which received the signal - * - * The ::paused signal is emitted when gtd_timeline_pause() is invoked. - */ - timeline_signals[PAUSED] = - g_signal_new ("paused", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtdTimelineClass, paused), - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - /** - * GtdTimeline::stopped: - * @timeline: the #GtdTimeline that emitted the signal - * @is_finished: %TRUE if the signal was emitted at the end of the - * timeline. - * - * The #GtdTimeline::stopped signal is emitted when the timeline - * has been stopped, either because gtd_timeline_stop() has been - * called, or because it has been exhausted. - * - * This is different from the #GtdTimeline::completed signal, - * which gets emitted after every repeat finishes. - * - * If the #GtdTimeline has is marked as infinitely repeating, - * this signal will never be emitted. - */ - timeline_signals[STOPPED] = - g_signal_new ("stopped", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtdTimelineClass, stopped), - NULL, NULL, NULL, - G_TYPE_NONE, - 1, - G_TYPE_BOOLEAN); -} - -static void -gtd_timeline_init (GtdTimeline *self) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - - priv->progress_mode = GTD_EASE_LINEAR; - priv->progress_func = timeline_progress_func; -} - -/** - * gtd_timeline_new: - * @duration_ms: Duration of the timeline in milliseconds - * - * Creates a new #GtdTimeline with a duration of @duration_ms milli seconds. - * - * Return value: the newly created #GtdTimeline instance. Use - * g_object_unref() when done using it - */ -GtdTimeline * -gtd_timeline_new (guint duration_ms) -{ - return g_object_new (GTD_TYPE_TIMELINE, - "duration", duration_ms, - NULL); -} - -/** - * gtd_timeline_new_for_widget: - * @widget: The #GtdWidget the timeline is associated with - * @duration_ms: Duration of the timeline in milliseconds - * - * Creates a new #GtdTimeline with a duration of @duration milli seconds. - * - * Return value: the newly created #GtdTimeline instance. Use - * g_object_unref() when done using it - */ -GtdTimeline * -gtd_timeline_new_for_widget (GtdWidget *widget, - guint duration_ms) -{ - return g_object_new (GTD_TYPE_TIMELINE, - "duration", duration_ms, - "widget", widget, - NULL); -} - -/** - * gtd_timeline_set_widget: - * @timeline: a #GtdTimeline - * @widget: a #GtdWidget - * - * Set the widget the timeline is associated with. - */ -void -gtd_timeline_set_widget (GtdTimeline *self, - GtdWidget *widget) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - if (priv->widget) - { - remove_tick_callback (self); - priv->widget = NULL; - } - - priv->widget = widget; - - if (priv->is_playing) - add_tick_callback (self); -} - -/** - * gtd_timeline_start: - * @timeline: A #GtdTimeline - * - * Starts the #GtdTimeline playing. - **/ -void -gtd_timeline_start (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - priv = gtd_timeline_get_instance_private (self); - - if (priv->is_playing) - return; - - if (priv->duration_us == 0) - return; - - priv->delta_us = 0; - set_is_playing (self, TRUE); - - g_signal_emit (self, timeline_signals[STARTED], 0); -} - -/** - * gtd_timeline_pause: - * @timeline: A #GtdTimeline - * - * Pauses the #GtdTimeline on current frame - **/ -void -gtd_timeline_pause (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - priv = gtd_timeline_get_instance_private (self); - - if (!priv->is_playing) - return; - - priv->delta_us = 0; - set_is_playing (self, FALSE); - - g_signal_emit (self, timeline_signals[PAUSED], 0); -} - -/** - * gtd_timeline_stop: - * @timeline: A #GtdTimeline - * - * Stops the #GtdTimeline and moves to frame 0 - **/ -void -gtd_timeline_stop (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - gboolean was_playing; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - priv = gtd_timeline_get_instance_private (self); - - /* we check the is_playing here because pause() will return immediately - * if the timeline wasn't playing, so we don't know if it was actually - * stopped, and yet we still don't want to emit a ::stopped signal if - * the timeline was not playing in the first place. - */ - was_playing = priv->is_playing; - - gtd_timeline_pause (self); - gtd_timeline_rewind (self); - - if (was_playing) - g_signal_emit (self, timeline_signals[STOPPED], 0, FALSE); -} - -/** - * gtd_timeline_rewind: - * @timeline: A #GtdTimeline - * - * Rewinds #GtdTimeline to the first frame if its direction is - * %GTD_TIMELINE_FORWARD and the last frame if it is - * %GTD_TIMELINE_BACKWARD. - */ -void -gtd_timeline_rewind (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - priv = gtd_timeline_get_instance_private (self); - - if (priv->direction == GTD_TIMELINE_FORWARD) - gtd_timeline_advance (self, 0); - else if (priv->direction == GTD_TIMELINE_BACKWARD) - gtd_timeline_advance (self, us_to_ms (priv->duration_us)); -} - -/** - * gtd_timeline_skip: - * @timeline: A #GtdTimeline - * @msecs: Amount of time to skip - * - * Advance timeline by the requested time in milliseconds - */ -void -gtd_timeline_skip (GtdTimeline *self, - guint msecs) -{ - GtdTimelinePrivate *priv; - gint64 us; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - priv = gtd_timeline_get_instance_private (self); - us = ms_to_us (msecs); - - if (priv->direction == GTD_TIMELINE_FORWARD) - { - priv->elapsed_time_us += us; - - if (priv->elapsed_time_us > priv->duration_us) - priv->elapsed_time_us = 1; - } - else if (priv->direction == GTD_TIMELINE_BACKWARD) - { - priv->elapsed_time_us -= us; - - if (priv->elapsed_time_us < 1) - priv->elapsed_time_us = priv->duration_us - 1; - } - - priv->delta_us = 0; -} - -/** - * gtd_timeline_advance: - * @timeline: A #GtdTimeline - * @msecs: Time to advance to - * - * Advance timeline to the requested point. The point is given as a - * time in milliseconds since the timeline started. - * - * The @timeline will not emit the #GtdTimeline::new-frame - * signal for the given time. The first ::new-frame signal after the call to - * gtd_timeline_advance() will be emit the skipped markers. - */ -void -gtd_timeline_advance (GtdTimeline *self, - guint msecs) -{ - GtdTimelinePrivate *priv; - gint64 us; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - priv = gtd_timeline_get_instance_private (self); - us = ms_to_us (msecs); - - priv->elapsed_time_us = MIN (us, priv->duration_us); -} - -/** - * gtd_timeline_get_elapsed_time: - * @timeline: A #GtdTimeline - * - * Request the current time position of the timeline. - * - * Return value: current elapsed time in milliseconds. - */ -guint -gtd_timeline_get_elapsed_time (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), 0); - - priv = gtd_timeline_get_instance_private (self); - return us_to_ms (priv->elapsed_time_us); -} - -/** - * gtd_timeline_is_playing: - * @timeline: A #GtdTimeline - * - * Queries state of a #GtdTimeline. - * - * Return value: %TRUE if timeline is currently playing - */ -gboolean -gtd_timeline_is_playing (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), FALSE); - - priv = gtd_timeline_get_instance_private (self); - return priv->is_playing; -} - -/** - * gtd_timeline_get_delay: - * @timeline: a #GtdTimeline - * - * Retrieves the delay set using gtd_timeline_set_delay(). - * - * Return value: the delay in milliseconds. - */ -guint -gtd_timeline_get_delay (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), 0); - - priv = gtd_timeline_get_instance_private (self); - return us_to_ms (priv->delay_us); -} - -/** - * gtd_timeline_set_delay: - * @timeline: a #GtdTimeline - * @msecs: delay in milliseconds - * - * Sets the delay, in milliseconds, before @timeline should start. - */ -void -gtd_timeline_set_delay (GtdTimeline *self, - guint msecs) -{ - GtdTimelinePrivate *priv; - gint64 us; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - priv = gtd_timeline_get_instance_private (self); - us = ms_to_us (msecs); - - if (priv->delay_us != us) - { - priv->delay_us = us; - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DELAY]); - } -} - -/** - * gtd_timeline_get_duration: - * @timeline: a #GtdTimeline - * - * Retrieves the duration of a #GtdTimeline in milliseconds. - * See gtd_timeline_set_duration(). - * - * Return value: the duration of the timeline, in milliseconds. - */ -guint -gtd_timeline_get_duration (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), 0); - - priv = gtd_timeline_get_instance_private (self); - - return us_to_ms (priv->duration_us); -} - -/** - * gtd_timeline_set_duration: - * @timeline: a #GtdTimeline - * @msecs: duration of the timeline in milliseconds - * - * Sets the duration of the timeline, in milliseconds. The speed - * of the timeline depends on the GtdTimeline:fps setting. - */ -void -gtd_timeline_set_duration (GtdTimeline *self, - guint msecs) -{ - GtdTimelinePrivate *priv; - gint64 us; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - g_return_if_fail (msecs > 0); - - priv = gtd_timeline_get_instance_private (self); - us = ms_to_us (msecs); - - if (priv->duration_us != us) - { - priv->duration_us = us; - - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DURATION]); - } -} - -/** - * gtd_timeline_get_progress: - * @timeline: a #GtdTimeline - * - * The position of the timeline in a normalized [-1, 2] interval. - * - * The return value of this function is determined by the progress - * mode set using gtd_timeline_set_progress_mode(), or by the - * progress function set using gtd_timeline_set_progress_func(). - * - * Return value: the normalized current position in the timeline. - */ -gdouble -gtd_timeline_get_progress (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), 0.0); - - priv = gtd_timeline_get_instance_private (self); - - return priv->progress_func (self, - (gdouble) priv->elapsed_time_us, - (gdouble) priv->duration_us, - priv->progress_data); -} - -/** - * gtd_timeline_get_direction: - * @timeline: a #GtdTimeline - * - * Retrieves the direction of the timeline set with - * gtd_timeline_set_direction(). - * - * Return value: the direction of the timeline - */ -GtdTimelineDirection -gtd_timeline_get_direction (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), GTD_TIMELINE_FORWARD); - - priv = gtd_timeline_get_instance_private (self); - return priv->direction; -} - -/** - * gtd_timeline_set_direction: - * @timeline: a #GtdTimeline - * @direction: the direction of the timeline - * - * Sets the direction of @timeline, either %GTD_TIMELINE_FORWARD or - * %GTD_TIMELINE_BACKWARD. - */ -void -gtd_timeline_set_direction (GtdTimeline *self, - GtdTimelineDirection direction) -{ - GtdTimelinePrivate *priv; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - priv = gtd_timeline_get_instance_private (self); - - if (priv->direction != direction) - { - priv->direction = direction; - - if (priv->elapsed_time_us == 0) - priv->elapsed_time_us = priv->duration_us; - - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DIRECTION]); - } -} - -/** - * gtd_timeline_get_delta: - * @timeline: a #GtdTimeline - * - * Retrieves the amount of time elapsed since the last - * GtdTimeline::new-frame signal. - * - * This function is only useful inside handlers for the ::new-frame - * signal, and its behaviour is undefined if the timeline is not - * playing. - * - * Return value: the amount of time in milliseconds elapsed since the - * last frame - */ -guint -gtd_timeline_get_delta (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), 0); - - if (!gtd_timeline_is_playing (self)) - return 0; - - priv = gtd_timeline_get_instance_private (self); - return us_to_ms (priv->delta_us); -} - -/** - * gtd_timeline_set_auto_reverse: - * @timeline: a #GtdTimeline - * @reverse: %TRUE if the @timeline should reverse the direction - * - * Sets whether @timeline should reverse the direction after the - * emission of the #GtdTimeline::completed signal. - * - * Setting the #GtdTimeline:auto-reverse property to %TRUE is the - * equivalent of connecting a callback to the #GtdTimeline::completed - * signal and changing the direction of the timeline from that callback; - * for instance, this code: - * - * |[ - * static void - * reverse_timeline (GtdTimeline *self) - * { - * GtdTimelineDirection dir = gtd_timeline_get_direction (self); - * - * if (dir == GTD_TIMELINE_FORWARD) - * dir = GTD_TIMELINE_BACKWARD; - * else - * dir = GTD_TIMELINE_FORWARD; - * - * gtd_timeline_set_direction (self, dir); - * } - * ... - * timeline = gtd_timeline_new (1000); - * gtd_timeline_set_repeat_count (self, -1); - * g_signal_connect (self, "completed", - * G_CALLBACK (reverse_timeline), - * NULL); - * ]| - * - * can be effectively replaced by: - * - * |[ - * timeline = gtd_timeline_new (1000); - * gtd_timeline_set_repeat_count (self, -1); - * gtd_timeline_set_auto_reverse (self); - * ]| - */ -void -gtd_timeline_set_auto_reverse (GtdTimeline *self, - gboolean reverse) -{ - GtdTimelinePrivate *priv; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - reverse = !!reverse; - - priv = gtd_timeline_get_instance_private (self); - - if (priv->auto_reverse != reverse) - { - priv->auto_reverse = reverse; - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_AUTO_REVERSE]); - } -} - -/** - * gtd_timeline_get_auto_reverse: - * @timeline: a #GtdTimeline - * - * Retrieves the value set by gtd_timeline_set_auto_reverse(). - * - * Return value: %TRUE if the timeline should automatically reverse, and - * %FALSE otherwise - */ -gboolean -gtd_timeline_get_auto_reverse (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), FALSE); - - priv = gtd_timeline_get_instance_private (self); - return priv->auto_reverse; -} - -/** - * gtd_timeline_set_repeat_count: - * @timeline: a #GtdTimeline - * @count: the number of times the timeline should repeat - * - * Sets the number of times the @timeline should repeat. - * - * If @count is 0, the timeline never repeats. - * - * If @count is -1, the timeline will always repeat until - * it's stopped. - */ -void -gtd_timeline_set_repeat_count (GtdTimeline *self, - gint count) -{ - GtdTimelinePrivate *priv; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - g_return_if_fail (count >= -1); - - priv = gtd_timeline_get_instance_private (self); - - if (priv->repeat_count != count) - { - priv->repeat_count = count; - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_REPEAT_COUNT]); - } -} - -/** - * gtd_timeline_get_repeat_count: - * @timeline: a #GtdTimeline - * - * Retrieves the number set using gtd_timeline_set_repeat_count(). - * - * Return value: the number of repeats - */ -gint -gtd_timeline_get_repeat_count (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), 0); - - priv = gtd_timeline_get_instance_private (self); - return priv->repeat_count; -} - -/** - * gtd_timeline_set_progress_func: - * @timeline: a #GtdTimeline - * @func: (scope notified) (allow-none): a progress function, or %NULL - * @data: (closure): data to pass to @func - * @notify: a function to be called when the progress function is removed - * or the timeline is disposed - * - * Sets a custom progress function for @timeline. The progress function will - * be called by gtd_timeline_get_progress() and will be used to compute - * the progress value based on the elapsed time and the total duration of the - * timeline. - * - * If @func is not %NULL, the #GtdTimeline:progress-mode property will - * be set to %GTD_CUSTOM_MODE. - * - * If @func is %NULL, any previously set progress function will be unset, and - * the #GtdTimeline:progress-mode property will be set to %GTD_EASE_LINEAR. - */ -void -gtd_timeline_set_progress_func (GtdTimeline *self, - GtdTimelineProgressFunc func, - gpointer data, - GDestroyNotify notify) -{ - GtdTimelinePrivate *priv; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - - priv = gtd_timeline_get_instance_private (self); - - if (priv->progress_notify != NULL) - priv->progress_notify (priv->progress_data); - - priv->progress_func = func; - priv->progress_data = data; - priv->progress_notify = notify; - - if (priv->progress_func != NULL) - priv->progress_mode = GTD_CUSTOM_MODE; - else - priv->progress_mode = GTD_EASE_LINEAR; - - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PROGRESS_MODE]); -} - -/** - * gtd_timeline_set_progress_mode: - * @timeline: a #GtdTimeline - * @mode: the progress mode, as a #GtdEaseMode - * - * Sets the progress function using a value from the #GtdEaseMode - * enumeration. The @mode cannot be %GTD_CUSTOM_MODE or bigger than - * %GTD_ANIMATION_LAST. - */ -void -gtd_timeline_set_progress_mode (GtdTimeline *self, - GtdEaseMode mode) -{ - GtdTimelinePrivate *priv; - - g_return_if_fail (GTD_IS_TIMELINE (self)); - g_return_if_fail (mode < GTD_EASE_LAST); - g_return_if_fail (mode != GTD_CUSTOM_MODE); - - priv = gtd_timeline_get_instance_private (self); - - if (priv->progress_mode == mode) - return; - - if (priv->progress_notify != NULL) - priv->progress_notify (priv->progress_data); - - priv->progress_mode = mode; - priv->progress_func = timeline_progress_func; - priv->progress_data = NULL; - priv->progress_notify = NULL; - - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PROGRESS_MODE]); -} - -/** - * gtd_timeline_get_progress_mode: - * @timeline: a #GtdTimeline - * - * Retrieves the progress mode set using gtd_timeline_set_progress_mode() - * or gtd_timeline_set_progress_func(). - * - * Return value: a #GtdEaseMode - */ -GtdEaseMode -gtd_timeline_get_progress_mode (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), GTD_EASE_LINEAR); - - priv = gtd_timeline_get_instance_private (self); - return priv->progress_mode; -} - -/** - * gtd_timeline_get_duration_hint: - * @timeline: a #GtdTimeline - * - * Retrieves the full duration of the @timeline, taking into account the - * current value of the #GtdTimeline:repeat-count property. - * - * If the #GtdTimeline:repeat-count property is set to -1, this function - * will return %G_MAXINT64. - * - * The returned value is to be considered a hint, and it's only valid - * as long as the @timeline hasn't been changed. - * - * Return value: the full duration of the #GtdTimeline - */ -gint64 -gtd_timeline_get_duration_hint (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - gint64 duration_ms; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), 0); - - priv = gtd_timeline_get_instance_private (self); - duration_ms = us_to_ms (priv->duration_us); - - if (priv->repeat_count == 0) - return duration_ms; - else if (priv->repeat_count < 0) - return G_MAXINT64; - else - return priv->repeat_count * duration_ms; -} - -/** - * gtd_timeline_get_current_repeat: - * @timeline: a #GtdTimeline - * - * Retrieves the current repeat for a timeline. - * - * Repeats start at 0. - * - * Return value: the current repeat - */ -gint -gtd_timeline_get_current_repeat (GtdTimeline *self) -{ - GtdTimelinePrivate *priv; - - g_return_val_if_fail (GTD_IS_TIMELINE (self), 0); - - priv = gtd_timeline_get_instance_private (self); - return priv->current_repeat; -} - -/** - * gtd_timeline_get_widget: - * @timeline: a #GtdTimeline - * - * Get the widget the timeline is associated with. - * - * Returns: (transfer none): the associated #GtdWidget - */ -GtdWidget * -gtd_timeline_get_widget (GtdTimeline *self) -{ - GtdTimelinePrivate *priv = gtd_timeline_get_instance_private (self); - - return priv->widget; -} diff --git a/src/animation/gtd-timeline.h b/src/animation/gtd-timeline.h deleted file mode 100644 index a8d60233..00000000 --- a/src/animation/gtd-timeline.h +++ /dev/null @@ -1,150 +0,0 @@ -/* gtd-timeline.h - * - * Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> - * - * Heavily inspired by Clutter, authored By Matthew Allum <mallum@openedhand.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 - */ - -#pragma once - -#include <glib-object.h> -#include <gtk/gtk.h> - -#include "gtd-easing.h" -#include "gtd-types.h" - -G_BEGIN_DECLS - -#define GTD_TYPE_TIMELINE (gtd_timeline_get_type()) -G_DECLARE_DERIVABLE_TYPE (GtdTimeline, gtd_timeline, GTD, TIMELINE, GObject) - -/** - * GtdTimelineProgressFunc: - * @timeline: a #GtdTimeline - * @elapsed: the elapsed time, in milliseconds - * @total: the total duration of the timeline, in milliseconds, - * @user_data: data passed to the function - * - * A function for defining a custom progress. - * - * Return value: the progress, as a floating point value between -1.0 and 2.0. - */ -typedef gdouble (* GtdTimelineProgressFunc) (GtdTimeline *timeline, - gdouble elapsed, - gdouble total, - gpointer user_data); - -/** - * GtdTimelineClass: - * @started: class handler for the #GtdTimeline::started signal - * @completed: class handler for the #GtdTimeline::completed signal - * @paused: class handler for the #GtdTimeline::paused signal - * @new_frame: class handler for the #GtdTimeline::new-frame signal - * @stopped: class handler for the #GtdTimeline::stopped signal - * - * The #GtdTimelineClass structure contains only private data - */ -struct _GtdTimelineClass -{ - /*< private >*/ - GObjectClass parent_class; - - /*< public >*/ - void (*started) (GtdTimeline *timeline); - void (*completed) (GtdTimeline *timeline); - void (*paused) (GtdTimeline *timeline); - - void (*new_frame) (GtdTimeline *timeline, - gint msecs); - - void (*stopped) (GtdTimeline *timeline, - gboolean is_finished); -}; - -GtdTimeline* gtd_timeline_new_for_widget (GtdWidget *widget, - guint duration_ms); - -GtdWidget* gtd_timeline_get_widget (GtdTimeline *timeline); - -void gtd_timeline_set_widget (GtdTimeline *timeline, - GtdWidget *widget); - -guint gtd_timeline_get_duration (GtdTimeline *timeline); - -void gtd_timeline_set_duration (GtdTimeline *timeline, - guint msecs); - -GtdTimelineDirection gtd_timeline_get_direction (GtdTimeline *timeline); - -void gtd_timeline_set_direction (GtdTimeline *timeline, - GtdTimelineDirection direction); - -void gtd_timeline_start (GtdTimeline *timeline); - -void gtd_timeline_pause (GtdTimeline *timeline); - -void gtd_timeline_stop (GtdTimeline *timeline); - -void gtd_timeline_set_auto_reverse (GtdTimeline *timeline, - gboolean reverse); - -gboolean gtd_timeline_get_auto_reverse (GtdTimeline *timeline); - -void gtd_timeline_set_repeat_count (GtdTimeline *timeline, - gint count); - -gint gtd_timeline_get_repeat_count (GtdTimeline *timeline); - -void gtd_timeline_rewind (GtdTimeline *timeline); - -void gtd_timeline_skip (GtdTimeline *timeline, - guint msecs); - -void gtd_timeline_advance (GtdTimeline *timeline, - guint msecs); - -guint gtd_timeline_get_elapsed_time (GtdTimeline *timeline); - -gdouble gtd_timeline_get_progress (GtdTimeline *timeline); - -gboolean gtd_timeline_is_playing (GtdTimeline *timeline); - -void gtd_timeline_set_delay (GtdTimeline *timeline, - guint msecs); - -guint gtd_timeline_get_delay (GtdTimeline *timeline); - -guint gtd_timeline_get_delta (GtdTimeline *timeline); - -void gtd_timeline_set_progress_func (GtdTimeline *timeline, - GtdTimelineProgressFunc func, - gpointer data, - GDestroyNotify notify); - -void gtd_timeline_set_progress_mode (GtdTimeline *timeline, - GtdEaseMode mode); - -GtdEaseMode gtd_timeline_get_progress_mode (GtdTimeline *timeline); - -gint64 gtd_timeline_get_duration_hint (GtdTimeline *timeline); -gint gtd_timeline_get_current_repeat (GtdTimeline *timeline); - -G_END_DECLS - - -G_END_DECLS diff --git a/src/animation/gtd-transition.c b/src/animation/gtd-transition.c deleted file mode 100644 index 0ca1d3f4..00000000 --- a/src/animation/gtd-transition.c +++ /dev/null @@ -1,655 +0,0 @@ -/* gtd-transition.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 - */ - - -/** - * SECTION:gtd-transition - * @Title: GtdTransition - * @Short_Description: Transition between two values - * - * #GtdTransition is an abstract subclass of #GtdTimeline that - * computes the interpolation between two values, stored by a #GtdInterval. - */ - -#include "gtd-transition.h" - -#include "gtd-animatable.h" -#include "gtd-debug.h" -#include "gtd-interval.h" -#include "gtd-timeline.h" - -#include <gobject/gvaluecollector.h> - -typedef struct -{ - GtdInterval *interval; - GtdAnimatable *animatable; - - guint remove_on_complete : 1; -} GtdTransitionPrivate; - -enum -{ - PROP_0, - PROP_INTERVAL, - PROP_ANIMATABLE, - PROP_REMOVE_ON_COMPLETE, - PROP_LAST, -}; - -static GParamSpec *obj_props[PROP_LAST] = { NULL, }; - -static GQuark quark_animatable_set = 0; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtdTransition, gtd_transition, GTD_TYPE_TIMELINE) - -static void -gtd_transition_attach (GtdTransition *self, - GtdAnimatable *animatable) -{ - GTD_TRANSITION_GET_CLASS (self)->attached (self, animatable); -} - -static void -gtd_transition_detach (GtdTransition *self, - GtdAnimatable *animatable) -{ - GTD_TRANSITION_GET_CLASS (self)->detached (self, animatable); -} - -static void -gtd_transition_real_compute_value (GtdTransition *self, - GtdAnimatable *animatable, - GtdInterval *interval, - gdouble progress) -{ -} - -static void -gtd_transition_real_attached (GtdTransition *self, - GtdAnimatable *animatable) -{ -} - -static void -gtd_transition_real_detached (GtdTransition *self, - GtdAnimatable *animatable) -{ -} - -static void -gtd_transition_new_frame (GtdTimeline *timeline, - gint elapsed) -{ - GtdTransition *self = GTD_TRANSITION (timeline); - GtdTransitionPrivate *priv = gtd_transition_get_instance_private (self); - gdouble progress; - - if (!priv->interval || !priv->animatable) - return; - - progress = gtd_timeline_get_progress (timeline); - - GTD_TRANSITION_GET_CLASS (timeline)->compute_value (self, - priv->animatable, - priv->interval, - progress); -} - -static void -gtd_transition_stopped (GtdTimeline *timeline, - gboolean is_finished) -{ - GtdTransition *self = GTD_TRANSITION (timeline); - GtdTransitionPrivate *priv = gtd_transition_get_instance_private (self); - - if (is_finished && - priv->animatable != NULL && - priv->remove_on_complete) - { - gtd_transition_detach (GTD_TRANSITION (timeline), - priv->animatable); - g_clear_object (&priv->animatable); - } -} - -static void -gtd_transition_set_property (GObject *gobject, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtdTransition *self = GTD_TRANSITION (gobject); - - switch (prop_id) - { - case PROP_INTERVAL: - gtd_transition_set_interval (self, g_value_get_object (value)); - break; - - case PROP_ANIMATABLE: - gtd_transition_set_animatable (self, g_value_get_object (value)); - break; - - case PROP_REMOVE_ON_COMPLETE: - gtd_transition_set_remove_on_complete (self, g_value_get_boolean (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - break; - } -} - -static void -gtd_transition_get_property (GObject *gobject, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtdTransition *self = GTD_TRANSITION (gobject); - GtdTransitionPrivate *priv = gtd_transition_get_instance_private (self); - - switch (prop_id) - { - case PROP_INTERVAL: - g_value_set_object (value, priv->interval); - break; - - case PROP_ANIMATABLE: - g_value_set_object (value, priv->animatable); - break; - - case PROP_REMOVE_ON_COMPLETE: - g_value_set_boolean (value, priv->remove_on_complete); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - break; - } -} - -static void -gtd_transition_dispose (GObject *gobject) -{ - GtdTransition *self = GTD_TRANSITION (gobject); - GtdTransitionPrivate *priv = gtd_transition_get_instance_private (self); - - if (priv->animatable != NULL) - gtd_transition_detach (GTD_TRANSITION (gobject), - priv->animatable); - - g_clear_object (&priv->interval); - g_clear_object (&priv->animatable); - - G_OBJECT_CLASS (gtd_transition_parent_class)->dispose (gobject); -} - -static void -gtd_transition_class_init (GtdTransitionClass *klass) -{ - GtdTimelineClass *timeline_class = GTD_TIMELINE_CLASS (klass); - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - quark_animatable_set = - g_quark_from_static_string ("-gtd-transition-animatable-set"); - - klass->compute_value = gtd_transition_real_compute_value; - klass->attached = gtd_transition_real_attached; - klass->detached = gtd_transition_real_detached; - - timeline_class->new_frame = gtd_transition_new_frame; - timeline_class->stopped = gtd_transition_stopped; - - gobject_class->set_property = gtd_transition_set_property; - gobject_class->get_property = gtd_transition_get_property; - gobject_class->dispose = gtd_transition_dispose; - - /** - * GtdTransition:interval: - * - * The #GtdInterval used to describe the initial and final states - * of the transition. - */ - obj_props[PROP_INTERVAL] = - g_param_spec_object ("interval", - "Interval", - "The interval of values to transition", - GTD_TYPE_INTERVAL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdTransition:animatable: - * - * The #GtdAnimatable instance currently being animated. - */ - obj_props[PROP_ANIMATABLE] = - g_param_spec_object ("animatable", - "Animatable", - "The animatable object", - GTD_TYPE_ANIMATABLE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdTransition:remove-on-complete: - * - * Whether the #GtdTransition should be automatically detached - * from the #GtdTransition:animatable instance whenever the - * #GtdTimeline::stopped signal is emitted. - * - * The #GtdTransition:remove-on-complete property takes into - * account the value of the #GtdTimeline:repeat-count property, - * and it only detaches the transition if the transition is not - * repeating. - */ - obj_props[PROP_REMOVE_ON_COMPLETE] = - g_param_spec_boolean ("remove-on-complete", - "Remove on Complete", - "Detach the transition when completed", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); -} - -static void -gtd_transition_init (GtdTransition *self) -{ -} - -/** - * gtd_transition_set_interval: - * @transition: a #GtdTransition - * @interval: (allow-none): a #GtdInterval, or %NULL - * - * Sets the #GtdTransition:interval property using @interval. - * - * The @transition will acquire a reference on the @interval, sinking - * the floating flag on it if necessary. - */ -void -gtd_transition_set_interval (GtdTransition *self, - GtdInterval *interval) -{ - GtdTransitionPrivate *priv; - - g_return_if_fail (GTD_IS_TRANSITION (self)); - g_return_if_fail (interval == NULL || GTD_IS_INTERVAL (interval)); - - priv = gtd_transition_get_instance_private (self); - - if (priv->interval == interval) - return; - - g_clear_object (&priv->interval); - - if (interval != NULL) - priv->interval = g_object_ref_sink (interval); - - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_INTERVAL]); -} - -/** - * gtd_transition_get_interval: - * @transition: a #GtdTransition - * - * Retrieves the interval set using gtd_transition_set_interval() - * - * Return value: (transfer none): a #GtdInterval, or %NULL; the returned - * interval is owned by the #GtdTransition and it should not be freed - * directly - */ -GtdInterval * -gtd_transition_get_interval (GtdTransition *self) -{ - GtdTransitionPrivate *priv = gtd_transition_get_instance_private (self); - - g_return_val_if_fail (GTD_IS_TRANSITION (self), NULL); - - priv = gtd_transition_get_instance_private (self); - return priv->interval; -} - -/** - * gtd_transition_set_animatable: - * @transition: a #GtdTransition - * @animatable: (allow-none): a #GtdAnimatable, or %NULL - * - * Sets the #GtdTransition:animatable property. - * - * The @transition will acquire a reference to the @animatable instance, - * and will call the #GtdTransitionClass.attached() virtual function. - * - * If an existing #GtdAnimatable is attached to @self, the - * reference will be released, and the #GtdTransitionClass.detached() - * virtual function will be called. - */ -void -gtd_transition_set_animatable (GtdTransition *self, - GtdAnimatable *animatable) -{ - GtdTransitionPrivate *priv; - GtdWidget *widget; - - g_return_if_fail (GTD_IS_TRANSITION (self)); - g_return_if_fail (animatable == NULL || GTD_IS_ANIMATABLE (animatable)); - - priv = gtd_transition_get_instance_private (self); - - if (priv->animatable == animatable) - return; - - if (priv->animatable != NULL) - gtd_transition_detach (self, priv->animatable); - - g_clear_object (&priv->animatable); - - if (animatable != NULL) - { - priv->animatable = g_object_ref (animatable); - gtd_transition_attach (self, priv->animatable); - } - - widget = gtd_animatable_get_widget (animatable); - gtd_timeline_set_widget (GTD_TIMELINE (self), widget); -} - -/** - * gtd_transition_get_animatable: - * @transition: a #GtdTransition - * - * Retrieves the #GtdAnimatable set using gtd_transition_set_animatable(). - * - * Return value: (transfer none): a #GtdAnimatable, or %NULL; the returned - * animatable is owned by the #GtdTransition, and it should not be freed - * directly. - */ -GtdAnimatable * -gtd_transition_get_animatable (GtdTransition *self) -{ - GtdTransitionPrivate *priv; - - g_return_val_if_fail (GTD_IS_TRANSITION (self), NULL); - - priv = gtd_transition_get_instance_private (self); - return priv->animatable; -} - -/** - * gtd_transition_set_remove_on_complete: - * @transition: a #GtdTransition - * @remove_complete: whether to detach @transition when complete - * - * Sets whether @transition should be detached from the #GtdAnimatable - * set using gtd_transition_set_animatable() when the - * #GtdTimeline::completed signal is emitted. - */ -void -gtd_transition_set_remove_on_complete (GtdTransition *self, - gboolean remove_complete) -{ - GtdTransitionPrivate *priv; - - g_return_if_fail (GTD_IS_TRANSITION (self)); - - priv = gtd_transition_get_instance_private (self); - remove_complete = !!remove_complete; - - if (priv->remove_on_complete == remove_complete) - return; - - priv->remove_on_complete = remove_complete; - - g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_REMOVE_ON_COMPLETE]); -} - -/** - * gtd_transition_get_remove_on_complete: - * @transition: a #GtdTransition - * - * Retrieves the value of the #GtdTransition:remove-on-complete property. - * - * Return value: %TRUE if the @transition should be detached when complete, - * and %FALSE otherwise - */ -gboolean -gtd_transition_get_remove_on_complete (GtdTransition *self) -{ - GtdTransitionPrivate *priv; - - g_return_val_if_fail (GTD_IS_TRANSITION (self), FALSE); - - priv = gtd_transition_get_instance_private (self); - return priv->remove_on_complete; -} - -typedef void (* IntervalSetFunc) (GtdInterval *interval, - const GValue *value); - -static inline void -gtd_transition_set_value (GtdTransition *self, - IntervalSetFunc interval_set_func, - const GValue *value) -{ - GtdTransitionPrivate *priv = gtd_transition_get_instance_private (self); - GType interval_type; - - if (priv->interval == NULL) - { - priv->interval = gtd_interval_new_with_values (G_VALUE_TYPE (value), NULL, NULL); - g_object_ref_sink (priv->interval); - } - - interval_type = gtd_interval_get_value_type (priv->interval); - - if (!g_type_is_a (G_VALUE_TYPE (value), interval_type)) - { - if (g_value_type_compatible (G_VALUE_TYPE (value), interval_type)) - { - interval_set_func (priv->interval, value); - return; - } - - if (g_value_type_transformable (G_VALUE_TYPE (value), interval_type)) - { - GValue transform = G_VALUE_INIT; - - g_value_init (&transform, interval_type); - if (g_value_transform (value, &transform)) - interval_set_func (priv->interval, &transform); - else - { - g_warning ("%s: Unable to convert a value of type '%s' into " - "the value type '%s' of the interval used by the " - "transition.", - G_STRLOC, - g_type_name (G_VALUE_TYPE (value)), - g_type_name (interval_type)); - } - - g_value_unset (&transform); - } - } - else - { - interval_set_func (priv->interval, value); - } -} - -/** - * gtd_transition_set_from_value: (rename-to gtd_transition_set_from) - * @transition: a #GtdTransition - * @value: a #GValue with the initial value of the transition - * - * Sets the initial value of the transition. - * - * This is a convenience function that will either create the - * #GtdInterval used by @self, or will update it if - * the #GtdTransition:interval is already set. - * - * This function will copy the contents of @value, so it is - * safe to call g_value_unset() after it returns. - * - * If @transition already has a #GtdTransition:interval set, - * then @value must hold the same type, or a transformable type, - * as the interval's #GtdInterval:value-type property. - * - * This function is meant to be used by language bindings. - */ -void -gtd_transition_set_from_value (GtdTransition *self, - const GValue *value) -{ - g_return_if_fail (GTD_IS_TRANSITION (self)); - g_return_if_fail (G_IS_VALUE (value)); - - gtd_transition_set_value (self, gtd_interval_set_initial_value, value); -} - -/** - * gtd_transition_set_to_value: (rename-to gtd_transition_set_to) - * @transition: a #GtdTransition - * @value: a #GValue with the final value of the transition - * - * Sets the final value of the transition. - * - * This is a convenience function that will either create the - * #GtdInterval used by @self, or will update it if - * the #GtdTransition:interval is already set. - * - * This function will copy the contents of @value, so it is - * safe to call g_value_unset() after it returns. - * - * If @transition already has a #GtdTransition:interval set, - * then @value must hold the same type, or a transformable type, - * as the interval's #GtdInterval:value-type property. - * - * This function is meant to be used by language bindings. - */ -void -gtd_transition_set_to_value (GtdTransition *self, - const GValue *value) -{ - g_return_if_fail (GTD_IS_TRANSITION (self)); - g_return_if_fail (G_IS_VALUE (value)); - - gtd_transition_set_value (self, - gtd_interval_set_final_value, - value); -} - -/** - * gtd_transition_set_from: (skip) - * @transition: a #GtdTransition - * @value_type: the type of the value to set - * @...: the initial value - * - * Sets the initial value of the transition. - * - * This is a convenience function that will either create the - * #GtdInterval used by @self, or will update it if - * the #GtdTransition:interval is already set. - * - * If @transition already has a #GtdTransition:interval set, - * then @value must hold the same type, or a transformable type, - * as the interval's #GtdInterval:value-type property. - * - * This is a convenience function for the C API; language bindings - * should use gtd_transition_set_from_value() instead. - */ -void -gtd_transition_set_from (GtdTransition *self, - GType value_type, - ...) -{ - GValue value = G_VALUE_INIT; - gchar *error = NULL; - va_list args; - - g_return_if_fail (GTD_IS_TRANSITION (self)); - g_return_if_fail (value_type != G_TYPE_INVALID); - - va_start (args, value_type); - - G_VALUE_COLLECT_INIT (&value, value_type, args, 0, &error); - - va_end (args); - - if (error != NULL) - { - g_warning ("%s: %s", G_STRLOC, error); - g_free (error); - return; - } - - gtd_transition_set_value (self, gtd_interval_set_initial_value, &value); - - g_value_unset (&value); -} - -/** - * gtd_transition_set_to: (skip) - * @transition: a #GtdTransition - * @value_type: the type of the value to set - * @...: the final value - * - * Sets the final value of the transition. - * - * This is a convenience function that will either create the - * #GtdInterval used by @self, or will update it if - * the #GtdTransition:interval is already set. - * - * If @transition already has a #GtdTransition:interval set, - * then @value must hold the same type, or a transformable type, - * as the interval's #GtdInterval:value-type property. - * - * This is a convenience function for the C API; language bindings - * should use gtd_transition_set_to_value() instead. - */ -void -gtd_transition_set_to (GtdTransition *self, - GType value_type, - ...) -{ - GValue value = G_VALUE_INIT; - gchar *error = NULL; - va_list args; - - g_return_if_fail (GTD_IS_TRANSITION (self)); - g_return_if_fail (value_type != G_TYPE_INVALID); - - va_start (args, value_type); - - G_VALUE_COLLECT_INIT (&value, value_type, args, 0, &error); - - va_end (args); - - if (error != NULL) - { - g_warning ("%s: %s", G_STRLOC, error); - g_free (error); - return; - } - - gtd_transition_set_value (self, gtd_interval_set_final_value, &value); - - g_value_unset (&value); -} diff --git a/src/animation/gtd-transition.h b/src/animation/gtd-transition.h deleted file mode 100644 index 32e20fa3..00000000 --- a/src/animation/gtd-transition.h +++ /dev/null @@ -1,85 +0,0 @@ -/* gtd-transition.h - * - * 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 - */ - -#pragma once - -#include "gtd-timeline.h" - -G_BEGIN_DECLS - -#define GTD_TYPE_TRANSITION (gtd_transition_get_type()) -G_DECLARE_DERIVABLE_TYPE (GtdTransition, gtd_transition, GTD, TRANSITION, GtdTimeline) - -/** - * GtdTransitionClass: - * @attached: virtual function; called when a transition is attached to - * a #GtdAnimatable instance - * @detached: virtual function; called when a transition is detached from - * a #GtdAnimatable instance - * @compute_value: virtual function; called each frame to compute and apply - * the interpolation of the interval - * - * The #GtdTransitionClass structure contains - * private data. - * - * Since: 1.10 - */ -struct _GtdTransitionClass -{ - /*< private >*/ - GtdTimelineClass parent_class; - - /*< public >*/ - void (* attached) (GtdTransition *transition, - GtdAnimatable *animatable); - void (* detached) (GtdTransition *transition, - GtdAnimatable *animatable); - - void (* compute_value) (GtdTransition *transition, - GtdAnimatable *animatable, - GtdInterval *interval, - gdouble progress); - - /*< private >*/ - gpointer _padding[8]; -}; - -void gtd_transition_set_interval (GtdTransition *transition, - GtdInterval *interval); -GtdInterval * gtd_transition_get_interval (GtdTransition *transition); -void gtd_transition_set_from_value (GtdTransition *transition, - const GValue *value); -void gtd_transition_set_to_value (GtdTransition *transition, - const GValue *value); -void gtd_transition_set_from (GtdTransition *transition, - GType value_type, - ...); -void gtd_transition_set_to (GtdTransition *transition, - GType value_type, - ...); - -void gtd_transition_set_animatable (GtdTransition *transition, - GtdAnimatable *animatable); -GtdAnimatable * gtd_transition_get_animatable (GtdTransition *transition); -void gtd_transition_set_remove_on_complete (GtdTransition *transition, - gboolean remove_complete); -gboolean gtd_transition_get_remove_on_complete (GtdTransition *transition); - -G_END_DECLS diff --git a/src/core/gtd-utils.c b/src/core/gtd-utils.c index 33b9d855..28993b53 100644 --- a/src/core/gtd-utils.c +++ b/src/core/gtd-utils.c @@ -22,7 +22,6 @@ #include "gtd-task.h" #include "gtd-utils.h" #include "gtd-utils-private.h" -#include "gtd-widget.h" #include <gtk/gtk.h> @@ -152,5 +151,4 @@ void gtd_ensure_types (void) { g_type_ensure (GTD_TYPE_MAX_SIZE_LAYOUT); - g_type_ensure (GTD_TYPE_WIDGET); } diff --git a/src/gtd-debug.h.in b/src/gtd-debug.h index fe99339a..d2b6bea7 100644 --- a/src/gtd-debug.h.in +++ b/src/gtd-debug.h @@ -20,6 +20,8 @@ #pragma once +#include "config.h" + #include <glib.h> /** @@ -37,7 +39,7 @@ G_BEGIN_DECLS #ifndef GTD_ENABLE_TRACE -# define GTD_ENABLE_TRACE @ENABLE_TRACING@ +# define GTD_ENABLE_TRACE ENABLE_TRACING #endif #if GTD_ENABLE_TRACE != 1 # undef GTD_ENABLE_TRACE diff --git a/src/gtd-enum-types.c.template b/src/gtd-enum-types.c.template deleted file mode 100644 index ed83a710..00000000 --- a/src/gtd-enum-types.c.template +++ /dev/null @@ -1,39 +0,0 @@ -/*** BEGIN file-header ***/ -#include "gtd-enum-types.h" - -/*** END file-header ***/ - -/*** BEGIN file-production ***/ -/* enumerations from "@filename@" */ -#include "@filename@" - -/*** END file-production ***/ - -/*** BEGIN value-header ***/ -GType -@enum_name@_get_type (void) -{ - static GType the_type = 0; - - if (the_type == 0) - { - static const G@Type@Value values[] = { -/*** END value-header ***/ - -/*** BEGIN value-production ***/ - { @VALUENAME@, - "@VALUENAME@", - "@valuenick@" }, -/*** END value-production ***/ - -/*** BEGIN value-tail ***/ - { 0, NULL, NULL } - }; - the_type = g_@type@_register_static ( - g_intern_static_string ("@EnumName@"), - values); - } - return the_type; -} - -/*** END value-tail ***/ diff --git a/src/gtd-enum-types.h.template b/src/gtd-enum-types.h.template deleted file mode 100644 index f3d5156e..00000000 --- a/src/gtd-enum-types.h.template +++ /dev/null @@ -1,24 +0,0 @@ -/*** BEGIN file-header ***/ -#pragma once - -#include <glib-object.h> - -G_BEGIN_DECLS - -/*** END file-header ***/ - -/*** BEGIN file-production ***/ -/* Enumerations from "@filename@" */ - -/*** END file-production ***/ - -/*** BEGIN enumeration-production ***/ -#define GTD_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) -GType @enum_name@_get_type (void) G_GNUC_CONST; - -/*** END enumeration-production ***/ - -/*** BEGIN file-tail ***/ -G_END_DECLS - -/*** END file-tail ***/ diff --git a/src/gtd-utils.h b/src/gtd-utils.h deleted file mode 100644 index bc03170f..00000000 --- a/src/gtd-utils.h +++ /dev/null @@ -1,35 +0,0 @@ -/* gtd-utils.h - * - * Copyright 2018-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 - */ - -#pragma once - -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -gchar* gtd_normalize_casefold_and_unaccent (const gchar *str); - -gint gtd_collate_compare_strings (const gchar *string_a, - const gchar *string_b); - -GdkPaintable* gtd_create_circular_paintable (GdkRGBA *color, - gint size); - -G_END_DECLS diff --git a/src/gui/gtd-max-size-layout.c b/src/gui/gtd-max-size-layout.c index 348b2edd..b6d95cd6 100644 --- a/src/gui/gtd-max-size-layout.c +++ b/src/gui/gtd-max-size-layout.c @@ -19,7 +19,6 @@ */ #include "gtd-max-size-layout.h" -#include "gtd-widget.h" struct _GtdMaxSizeLayout { @@ -45,7 +44,6 @@ enum static GParamSpec *properties [N_PROPS]; - /* * GtkLayoutManager overrides */ @@ -152,9 +150,6 @@ gtd_max_size_layout_allocate (GtkLayoutManager *layout_manager, { GskTransform *transform = NULL; - if (GTD_IS_WIDGET (child)) - transform = gtd_widget_apply_transform (GTD_WIDGET (child), NULL); - gtk_widget_allocate (child, width, height, baseline, transform); } } diff --git a/src/gui/gtd-sidebar.c b/src/gui/gtd-sidebar.c index efad9fc9..0efd6c32 100644 --- a/src/gui/gtd-sidebar.c +++ b/src/gui/gtd-sidebar.c @@ -38,7 +38,7 @@ struct _GtdSidebar { - GtdWidget parent; + GtkWidget parent; GtkListBox *archive_listbox; GtkListBoxRow *archive_row; @@ -51,7 +51,7 @@ struct _GtdSidebar GSimpleActionGroup *action_group; }; -G_DEFINE_TYPE (GtdSidebar, gtd_sidebar, GTD_TYPE_WIDGET) +G_DEFINE_TYPE (GtdSidebar, gtd_sidebar, GTK_TYPE_WIDGET) /* @@ -813,12 +813,29 @@ gtd_sidebar_constructed (GObject *object) } static void +gtd_sidebar_dispose (GObject *object) +{ + GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (object)); + + while (child) + { + GtkWidget *next = gtk_widget_get_next_sibling (child); + + gtk_widget_unparent (child); + child = next; + } + + G_OBJECT_CLASS (gtd_sidebar_parent_class)->dispose (object); +} + +static void gtd_sidebar_class_init (GtdSidebarClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->constructed = gtd_sidebar_constructed; + object_class->dispose = gtd_sidebar_dispose; g_type_ensure (GTD_TYPE_MAX_SIZE_LAYOUT); diff --git a/src/gui/gtd-sidebar.h b/src/gui/gtd-sidebar.h index e3c78395..1bca639d 100644 --- a/src/gui/gtd-sidebar.h +++ b/src/gui/gtd-sidebar.h @@ -23,12 +23,11 @@ #include <gtk/gtk.h> #include "gtd-panel.h" -#include "gtd-widget.h" G_BEGIN_DECLS #define GTD_TYPE_SIDEBAR (gtd_sidebar_get_type()) -G_DECLARE_FINAL_TYPE (GtdSidebar, gtd_sidebar, GTD, SIDEBAR, GtdWidget) +G_DECLARE_FINAL_TYPE (GtdSidebar, gtd_sidebar, GTD, SIDEBAR, GtkWidget) void gtd_sidebar_set_panel_stack (GtdSidebar *self, GtkStack *stack); diff --git a/src/gui/gtd-sidebar.ui b/src/gui/gtd-sidebar.ui index 356eb9c5..7e41b023 100644 --- a/src/gui/gtd-sidebar.ui +++ b/src/gui/gtd-sidebar.ui @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <interface> - <template class="GtdSidebar" parent="GtdWidget"> + <template class="GtdSidebar" parent="GtkWidget"> <property name="hexpand">0</property> <property name="layout-manager"> <object class="GtdMaxSizeLayout"> diff --git a/src/gui/gtd-star-widget.c b/src/gui/gtd-star-widget.c index f7eac854..79980282 100644 --- a/src/gui/gtd-star-widget.c +++ b/src/gui/gtd-star-widget.c @@ -22,7 +22,7 @@ struct _GtdStarWidget { - GtdWidget parent; + GtkWidget parent; GtkWidget *filled_star; GtkWidget *empty_star; @@ -30,7 +30,7 @@ struct _GtdStarWidget gboolean active; }; -G_DEFINE_TYPE (GtdStarWidget, gtd_star_widget, GTD_TYPE_WIDGET) +G_DEFINE_TYPE (GtdStarWidget, gtd_star_widget, GTK_TYPE_WIDGET) enum { diff --git a/src/gui/gtd-star-widget.h b/src/gui/gtd-star-widget.h index 0c8cf480..7a103f59 100644 --- a/src/gui/gtd-star-widget.h +++ b/src/gui/gtd-star-widget.h @@ -20,12 +20,12 @@ #pragma once -#include "gtd-widget.h" +#include <gtk/gtk.h> G_BEGIN_DECLS #define GTD_TYPE_STAR_WIDGET (gtd_star_widget_get_type()) -G_DECLARE_FINAL_TYPE (GtdStarWidget, gtd_star_widget, GTD, STAR_WIDGET, GtdWidget) +G_DECLARE_FINAL_TYPE (GtdStarWidget, gtd_star_widget, GTD, STAR_WIDGET, GtkWidget) GtkWidget* gtd_star_widget_new (void); diff --git a/src/gui/gtd-task-list-popover.c b/src/gui/gtd-task-list-popover.c index 7d556a01..324371ad 100644 --- a/src/gui/gtd-task-list-popover.c +++ b/src/gui/gtd-task-list-popover.c @@ -20,7 +20,6 @@ #define G_LOG_DOMAIN "GtdTaskListPopover" -#include "models/gtd-list-model-filter.h" #include "gtd-debug.h" #include "gtd-manager.h" #include "gtd-provider.h" diff --git a/src/gui/gtd-task-list-view.c b/src/gui/gtd-task-list-view.c index 83aec5ed..7e60794e 100644 --- a/src/gui/gtd-task-list-view.c +++ b/src/gui/gtd-task-list-view.c @@ -31,7 +31,6 @@ #include "gtd-task-list.h" #include "gtd-task-row.h" #include "gtd-utils-private.h" -#include "gtd-widget.h" #include "gtd-window.h" #include <glib.h> @@ -533,7 +532,7 @@ internal_header_func (GtkListBoxRow *row, if (header) { - GtkWidget *real_header = gtd_widget_new (); + GtkWidget *real_header = adw_bin_new (); gtk_widget_insert_before (header, real_header, NULL); header = real_header; diff --git a/src/gui/gtd-task-list-view.ui b/src/gui/gtd-task-list-view.ui index aaa9d8f6..1c412287 100644 --- a/src/gui/gtd-task-list-view.ui +++ b/src/gui/gtd-task-list-view.ui @@ -26,7 +26,7 @@ <property name="min-content-height">320</property> <property name="hscrollbar-policy">never</property> <child> - <object class="GtdWidget"> + <object class="AdwBin"> <property name="hexpand">1</property> <property name="vexpand">1</property> <property name="halign">center</property> diff --git a/src/gui/gtd-task-row.c b/src/gui/gtd-task-row.c index 89fcecc6..ee512ee9 100644 --- a/src/gui/gtd-task-row.c +++ b/src/gui/gtd-task-row.c @@ -29,7 +29,6 @@ #include "gtd-task-list.h" #include "gtd-task-list-view.h" #include "gtd-utils-private.h" -#include "gtd-widget.h" #include <glib/gi18n.h> #include <gdk/gdk.h> diff --git a/src/gui/gtd-widget.c b/src/gui/gtd-widget.c deleted file mode 100644 index aedd5ce7..00000000 --- a/src/gui/gtd-widget.c +++ /dev/null @@ -1,1669 +0,0 @@ -/* gtd-widget.c - * - * Copyright 2018-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-widget.h" - -#include "gtd-animatable.h" -#include "gtd-debug.h" -#include "gtd-animation-enums.h" -#include "gtd-interval.h" -#include "gtd-timeline.h" -#include "gtd-property-transition.h" - -#include <graphene-gobject.h> -#include <gobject/gvaluecollector.h> - -enum -{ - X, - Y, - Z, -}; - -typedef struct -{ - guint easing_duration; - guint easing_delay; - GtdEaseMode easing_mode; -} AnimationState; - -typedef struct -{ - struct { - GHashTable *transitions; - GArray *states; - AnimationState *current_state; - } animation; - - graphene_point3d_t pivot_point; - gfloat rotation[3]; - gfloat scale[3]; - graphene_point3d_t translation; - - GskTransform *cached_transform; -} GtdWidgetPrivate; - -static void set_animatable_property (GtdWidget *self, - guint prop_id, - const GValue *value, - GParamSpec *pspec); - -static void gtd_animatable_iface_init (GtdAnimatableInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (GtdWidget, gtd_widget, GTK_TYPE_WIDGET, - G_ADD_PRIVATE (GtdWidget) - G_IMPLEMENT_INTERFACE (GTD_TYPE_ANIMATABLE, gtd_animatable_iface_init)) - -enum -{ - PROP_0, - PROP_PIVOT_POINT, - PROP_ROTATION_X, - PROP_ROTATION_Y, - PROP_ROTATION_Z, - PROP_SCALE_X, - PROP_SCALE_Y, - PROP_SCALE_Z, - PROP_TRANSLATION_X, - PROP_TRANSLATION_Y, - PROP_TRANSLATION_Z, - N_PROPS -}; - -enum -{ - TRANSITION_STOPPED, - TRANSITIONS_COMPLETED, - NUM_SIGNALS -}; - - -static guint signals[NUM_SIGNALS] = { 0, }; - -static GParamSpec *properties [N_PROPS] = { NULL, }; - - -/* - * Auxiliary methods - */ - -typedef struct -{ - GtdWidget *widget; - GtdTransition *transition; - gchar *name; - gulong completed_id; -} TransitionClosure; - -static void -transition_closure_free (gpointer data) -{ - if (G_LIKELY (data != NULL)) - { - TransitionClosure *closure = data; - GtdTimeline *timeline; - - timeline = GTD_TIMELINE (closure->transition); - - /* we disconnect the signal handler before stopping the timeline, - * so that we don't end up inside on_transition_stopped() from - * a call to g_hash_table_remove(). - */ - g_clear_signal_handler (&closure->completed_id, closure->transition); - - if (gtd_timeline_is_playing (timeline)) - gtd_timeline_stop (timeline); - - g_object_unref (closure->transition); - - g_free (closure->name); - - g_slice_free (TransitionClosure, closure); - } -} - -static void -on_transition_stopped_cb (GtdTransition *transition, - gboolean is_finished, - TransitionClosure *closure) -{ - GtdWidget *self = closure->widget; - GtdWidgetPrivate *priv = gtd_widget_get_instance_private (self); - GQuark t_quark; - gchar *t_name; - - if (closure->name == NULL) - return; - - /* we need copies because we emit the signal after the - * TransitionClosure data structure has been freed - */ - t_quark = g_quark_from_string (closure->name); - t_name = g_strdup (closure->name); - - if (gtd_transition_get_remove_on_complete (transition)) - { - /* this is safe, because the timeline has now stopped, - * so we won't recurse; the reference on the Animatable - * will be dropped by the ::stopped signal closure in - * GtdTransition, which is RUN_LAST, and thus will - * be called after this handler - */ - g_hash_table_remove (priv->animation.transitions, closure->name); - } - - /* we emit the ::transition-stopped after removing the - * transition, so that we can chain up new transitions - * without interfering with the one that just finished - */ - g_signal_emit (self, signals[TRANSITION_STOPPED], t_quark, t_name, is_finished); - - g_free (t_name); - - /* if it's the last transition then we clean up */ - if (g_hash_table_size (priv->animation.transitions) == 0) - { - g_hash_table_unref (priv->animation.transitions); - priv->animation.transitions = NULL; - - GTD_TRACE_MSG ("[animation] Transitions for '%p' completed", self); - - g_signal_emit (self, signals[TRANSITIONS_COMPLETED], 0); - } -} - -static void -add_transition_to_widget (GtdWidget *self, - const gchar *name, - GtdTransition *transition) -{ - GtdWidgetPrivate *priv = gtd_widget_get_instance_private (self); - TransitionClosure *closure; - GtdTimeline *timeline; - - GTD_ENTRY; - - if (!priv->animation.transitions) - { - priv->animation.transitions = g_hash_table_new_full (g_str_hash, - g_str_equal, - NULL, - transition_closure_free); - } - - if (g_hash_table_lookup (priv->animation.transitions, name) != NULL) - { - g_warning ("A transition with name '%s' already exists for the widget '%p'", - name, - self); - GTD_RETURN (); - } - - gtd_transition_set_animatable (transition, GTD_ANIMATABLE (self)); - - timeline = GTD_TIMELINE (transition); - - closure = g_slice_new (TransitionClosure); - closure->widget = self; - closure->transition = g_object_ref (transition); - closure->name = g_strdup (name); - closure->completed_id = g_signal_connect (timeline, - "stopped", - G_CALLBACK (on_transition_stopped_cb), - closure); - - GTD_TRACE_MSG ("[animation] Adding transition '%s' [%p] to widget %p", - closure->name, - closure->transition, - self); - - g_hash_table_insert (priv->animation.transitions, closure->name, closure); - gtd_timeline_start (timeline); - - GTD_EXIT; -} - -static gboolean -should_skip_implicit_transition (GtdWidget *self, - GParamSpec *pspec) -{ - GtdWidgetPrivate *priv = gtd_widget_get_instance_private (self); - - /* if the easing state has a non-zero duration we always want an - * implicit transition to occur - */ - if (priv->animation.current_state->easing_duration == 0) - return TRUE; - - /* if the widget is not mapped and is not part of a branch of the scene - * graph that is being cloned, then we always skip implicit transitions - * on the account of the fact that the widget is not going to be visible - * when those transitions happen - */ - if (!gtk_widget_get_mapped (GTK_WIDGET (self))) - return TRUE; - - return FALSE; -} - -static GtdTransition* -create_transition (GtdWidget *self, - GParamSpec *pspec, - ...) -{ - GtdWidgetPrivate *priv = gtd_widget_get_instance_private (self); - g_autofree gchar *error = NULL; - g_auto (GValue) initial = G_VALUE_INIT; - g_auto (GValue) final = G_VALUE_INIT; - TransitionClosure *closure; - GtdTimeline *timeline; - GtdInterval *interval; - GtdTransition *res = NULL; - va_list var_args; - GType ptype; - - g_assert (pspec != NULL); - - if (!priv->animation.transitions) - { - priv->animation.transitions = g_hash_table_new_full (g_str_hash, - g_str_equal, - NULL, - transition_closure_free); - } - - va_start (var_args, pspec); - - ptype = G_PARAM_SPEC_VALUE_TYPE (pspec); - - G_VALUE_COLLECT_INIT (&initial, ptype, var_args, 0, &error); - if (error != NULL) - { - g_critical ("%s: %s", G_STRLOC, error); - goto out; - } - - G_VALUE_COLLECT_INIT (&final, ptype, var_args, 0, &error); - if (error != NULL) - { - g_critical ("%s: %s", G_STRLOC, error); - goto out; - } - - if (should_skip_implicit_transition (self, pspec)) - { - GTD_TRACE_MSG ("[animation] Skipping implicit transition for '%p::%s'", - self, - pspec->name); - - /* remove a transition, if one exists */ - gtd_widget_remove_transition (self, pspec->name); - - /* we don't go through the Animatable interface because we - * already know we got here through an animatable property. - */ - set_animatable_property (self, pspec->param_id, &final, pspec); - - goto out; - } - - closure = g_hash_table_lookup (priv->animation.transitions, pspec->name); - if (closure == NULL) - { - res = gtd_property_transition_new (pspec->name); - - gtd_transition_set_remove_on_complete (res, TRUE); - - interval = gtd_interval_new_with_values (ptype, &initial, &final); - gtd_transition_set_interval (res, interval); - - timeline = GTD_TIMELINE (res); - gtd_timeline_set_delay (timeline, priv->animation.current_state->easing_delay); - gtd_timeline_set_duration (timeline, priv->animation.current_state->easing_duration); - gtd_timeline_set_progress_mode (timeline, priv->animation.current_state->easing_mode); - - /* this will start the transition as well */ - add_transition_to_widget (self, pspec->name, res); - - /* the widget now owns the transition */ - g_object_unref (res); - } - else - { - GtdEaseMode cur_mode; - guint cur_duration; - - GTD_TRACE_MSG ("[animation] Existing transition for %p:%s", - self, - pspec->name); - - timeline = GTD_TIMELINE (closure->transition); - - cur_duration = gtd_timeline_get_duration (timeline); - if (cur_duration != priv->animation.current_state->easing_duration) - gtd_timeline_set_duration (timeline, priv->animation.current_state->easing_duration); - - cur_mode = gtd_timeline_get_progress_mode (timeline); - if (cur_mode != priv->animation.current_state->easing_mode) - gtd_timeline_set_progress_mode (timeline, priv->animation.current_state->easing_mode); - - gtd_timeline_rewind (timeline); - - interval = gtd_transition_get_interval (closure->transition); - gtd_interval_set_initial_value (interval, &initial); - gtd_interval_set_final_value (interval, &final); - - res = closure->transition; - } - -out: - va_end (var_args); - - return res; -} - -static void -invalidate_cached_transform (GtdWidget *self) -{ - GtdWidgetPrivate *priv = gtd_widget_get_instance_private (self); - - g_clear_pointer (&priv->cached_transform, gsk_transform_unref); -} - -static void -calculate_transform (GtdWidget *self) -{ - GtdWidgetPrivate *priv = gtd_widget_get_instance_private (self); - graphene_point3d_t pivot; - GskTransform *transform; - gboolean pivot_is_zero; - gint height; - gint width; - - transform = NULL; - width = gtk_widget_get_width (GTK_WIDGET (self)); - height = gtk_widget_get_height (GTK_WIDGET (self)); - - /* Pivot point */ - pivot_is_zero = graphene_point3d_equal (&priv->pivot_point, graphene_point3d_zero ()); - pivot = GRAPHENE_POINT3D_INIT (width * priv->pivot_point.x, - height * priv->pivot_point.y, - priv->pivot_point.z); - if (!pivot_is_zero) - transform = gsk_transform_translate_3d (transform, &pivot); - - /* Perspective */ - transform = gsk_transform_perspective (transform, 2 * MAX (width, height)); - - /* Translation */ - if (G_APPROX_VALUE (priv->translation.z, 0.f, FLT_EPSILON)) - { - transform = gsk_transform_translate (transform, - &GRAPHENE_POINT_INIT (priv->translation.x, - priv->translation.y)); - } - else - { - transform = gsk_transform_translate_3d (transform, &priv->translation); - } - - /* Scale */ - if (G_APPROX_VALUE (priv->scale[Z], 1.f, FLT_EPSILON)) - transform = gsk_transform_scale (transform, priv->scale[X], priv->scale[Y]); - else - transform = gsk_transform_scale_3d (transform, priv->scale[X], priv->scale[Y], priv->scale[Z]); - - /* Rotation */ - transform = gsk_transform_rotate_3d (transform, priv->rotation[X], graphene_vec3_x_axis ()); - transform = gsk_transform_rotate_3d (transform, priv->rotation[Y], graphene_vec3_y_axis ()); - transform = gsk_transform_rotate_3d (transform, priv->rotation[Z], graphene_vec3_z_axis ()); - - /* Rollback pivot point */ - if (!pivot_is_zero) - transform = gsk_transform_translate_3d (transform, - &GRAPHENE_POINT3D_INIT (-pivot.x, - -pivot.y, - -pivot.z)); - - priv->cached_transform = transform; -} - -static void -set_rotation_internal (GtdWidget *self, - gfloat rotation_x, - gfloat rotation_y, - gfloat rotation_z) -{ - GtdWidgetPrivate *priv; - gboolean changed[3]; - - GTD_ENTRY; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - changed[X] = !G_APPROX_VALUE (priv->rotation[X], rotation_x, FLT_EPSILON); - changed[Y] = !G_APPROX_VALUE (priv->rotation[Y], rotation_y, FLT_EPSILON); - changed[Z] = !G_APPROX_VALUE (priv->rotation[Z], rotation_z, FLT_EPSILON); - - if (!changed[X] && !changed[Y] && !changed[Z]) - GTD_RETURN (); - - invalidate_cached_transform (self); - - priv->rotation[X] = rotation_x; - priv->rotation[Y] = rotation_y; - priv->rotation[Z] = rotation_z; - - if (changed[X]) - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ROTATION_X]); - - if (changed[Y]) - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ROTATION_Y]); - - if (changed[Z]) - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ROTATION_Z]); - - gtk_widget_queue_resize (GTK_WIDGET (self)); - - GTD_EXIT; -} - -static void -set_scale_internal (GtdWidget *self, - gfloat scale_x, - gfloat scale_y, - gfloat scale_z) -{ - GtdWidgetPrivate *priv; - gboolean changed[3]; - - GTD_ENTRY; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - changed[X] = !G_APPROX_VALUE (priv->scale[X], scale_x, FLT_EPSILON); - changed[Y] = !G_APPROX_VALUE (priv->scale[Y], scale_y, FLT_EPSILON); - changed[Z] = !G_APPROX_VALUE (priv->scale[Z], scale_z, FLT_EPSILON); - - if (!changed[X] && !changed[Y] && !changed[Z]) - GTD_RETURN (); - - invalidate_cached_transform (self); - - priv->scale[X] = scale_x; - priv->scale[Y] = scale_y; - priv->scale[Z] = scale_z; - - if (changed[X]) - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SCALE_X]); - - if (changed[Y]) - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SCALE_Y]); - - if (changed[Z]) - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SCALE_Z]); - - gtk_widget_queue_resize (GTK_WIDGET (self)); - - GTD_EXIT; -} - -static void -set_translation_internal (GtdWidget *self, - gfloat translation_x, - gfloat translation_y, - gfloat translation_z) -{ - graphene_point3d_t old_translation, translation; - GtdWidgetPrivate *priv; - - GTD_ENTRY; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - translation = GRAPHENE_POINT3D_INIT (translation_x, translation_y, translation_z); - - if (graphene_point3d_equal (&priv->translation, &translation)) - GTD_RETURN (); - - old_translation = priv->translation; - - invalidate_cached_transform (self); - priv->translation = translation; - - if (!G_APPROX_VALUE (old_translation.x, translation.x, FLT_EPSILON)) - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TRANSLATION_X]); - - if (!G_APPROX_VALUE (old_translation.y, translation.y, FLT_EPSILON)) - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TRANSLATION_Y]); - - if (!G_APPROX_VALUE (old_translation.y, translation.y, FLT_EPSILON)) - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TRANSLATION_Z]); - - gtk_widget_queue_resize (GTK_WIDGET (self)); - - GTD_EXIT; -} - -static void -set_animatable_property (GtdWidget *self, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtdWidgetPrivate *priv = gtd_widget_get_instance_private (self); - GObject *object = G_OBJECT (self); - - g_object_freeze_notify (object); - - switch (prop_id) - { - case PROP_ROTATION_X: - set_rotation_internal (self, g_value_get_float (value), priv->rotation[Y], priv->rotation[Z]); - break; - - case PROP_ROTATION_Y: - set_rotation_internal (self, priv->rotation[X], g_value_get_float (value), priv->rotation[Z]); - break; - - case PROP_ROTATION_Z: - set_rotation_internal (self, priv->rotation[X], priv->rotation[Y], g_value_get_float (value)); - break; - - case PROP_SCALE_X: - set_scale_internal (self, g_value_get_float (value), priv->scale[Y], priv->scale[Z]); - break; - - case PROP_SCALE_Y: - set_scale_internal (self, priv->scale[X], g_value_get_float (value), priv->scale[Z]); - break; - - case PROP_SCALE_Z: - set_scale_internal (self, priv->scale[X], priv->scale[Y], g_value_get_float (value)); - break; - - case PROP_TRANSLATION_X: - set_translation_internal (self, g_value_get_float (value), priv->translation.y, priv->translation.z); - break; - - case PROP_TRANSLATION_Y: - set_translation_internal (self, priv->translation.x, g_value_get_float (value), priv->translation.z); - break; - - case PROP_TRANSLATION_Z: - set_translation_internal (self, priv->translation.x, priv->translation.y, g_value_get_float (value)); - break; - - default: - g_object_set_property (object, pspec->name, value); - break; - } - - g_object_thaw_notify (object); -} - -/* - * GtdAnimatable interface - */ - -static GParamSpec * -gtd_widget_find_property (GtdAnimatable *animatable, - const gchar *property_name) -{ - return g_object_class_find_property (G_OBJECT_GET_CLASS (animatable), property_name); -} - -static void -gtd_widget_get_initial_state (GtdAnimatable *animatable, - const gchar *property_name, - GValue *initial) -{ - g_object_get_property (G_OBJECT (animatable), property_name, initial); -} - -static void -gtd_widget_set_final_state (GtdAnimatable *animatable, - const gchar *property_name, - const GValue *final) -{ - GObjectClass *obj_class = G_OBJECT_GET_CLASS (animatable); - GParamSpec *pspec; - - pspec = g_object_class_find_property (obj_class, property_name); - - if (pspec) - set_animatable_property (GTD_WIDGET (animatable), pspec->param_id, final, pspec); -} - -static GtdWidget* -gtd_widget_get_widget (GtdAnimatable *animatable) -{ - return GTD_WIDGET (animatable); -} - -static void -gtd_animatable_iface_init (GtdAnimatableInterface *iface) -{ - iface->find_property = gtd_widget_find_property; - iface->get_initial_state = gtd_widget_get_initial_state; - iface->set_final_state = gtd_widget_set_final_state; - iface->get_widget = gtd_widget_get_widget; -} - - -/* - * GObject overrides - */ - -static void -gtd_widget_dispose (GObject *object) -{ - GtdWidget *self = GTD_WIDGET (object); - GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (object)); - - while (child) - { - GtkWidget *next = gtk_widget_get_next_sibling (child); - - gtk_widget_unparent (child); - child = next; - } - - invalidate_cached_transform (self); - gtd_widget_remove_all_transitions (self); - - G_OBJECT_CLASS (gtd_widget_parent_class)->dispose (object); -} - -static void -gtd_widget_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GtdWidget *self = GTD_WIDGET (object); - GtdWidgetPrivate *priv = gtd_widget_get_instance_private (self); - - switch (prop_id) - { - case PROP_PIVOT_POINT: - g_value_set_boxed (value, &priv->pivot_point); - break; - - case PROP_ROTATION_X: - g_value_set_float (value, priv->rotation[X]); - break; - - case PROP_ROTATION_Y: - g_value_set_float (value, priv->rotation[Y]); - break; - - case PROP_ROTATION_Z: - g_value_set_float (value, priv->rotation[Z]); - break; - - case PROP_SCALE_X: - g_value_set_float (value, priv->scale[X]); - break; - - case PROP_SCALE_Y: - g_value_set_float (value, priv->scale[Y]); - break; - - case PROP_SCALE_Z: - g_value_set_float (value, priv->scale[Z]); - break; - - case PROP_TRANSLATION_X: - g_value_set_float (value, priv->translation.x); - break; - - case PROP_TRANSLATION_Y: - g_value_set_float (value, priv->translation.y); - break; - - case PROP_TRANSLATION_Z: - g_value_set_float (value, priv->translation.z); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -gtd_widget_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtdWidget *self = GTD_WIDGET (object); - GtdWidgetPrivate *priv = gtd_widget_get_instance_private (self); - - switch (prop_id) - { - case PROP_PIVOT_POINT: - gtd_widget_set_pivot_point (self, g_value_get_boxed (value)); - break; - - case PROP_ROTATION_X: - gtd_widget_set_rotation (self, g_value_get_float (value), priv->rotation[Y], priv->rotation[Z]); - break; - - case PROP_ROTATION_Y: - gtd_widget_set_rotation (self, priv->rotation[X], g_value_get_float (value), priv->rotation[Z]); - break; - - case PROP_ROTATION_Z: - gtd_widget_set_rotation (self, priv->rotation[X], priv->rotation[Y], g_value_get_float (value)); - break; - - case PROP_SCALE_X: - gtd_widget_set_scale (self, g_value_get_float (value), priv->scale[Y], priv->scale[Z]); - break; - - case PROP_SCALE_Y: - gtd_widget_set_scale (self, priv->scale[X], g_value_get_float (value), priv->scale[Z]); - break; - - case PROP_SCALE_Z: - gtd_widget_set_scale (self, priv->scale[X], priv->scale[Y], g_value_get_float (value)); - break; - - case PROP_TRANSLATION_X: - gtd_widget_set_translation (self, g_value_get_float (value), priv->translation.y, priv->translation.z); - break; - - case PROP_TRANSLATION_Y: - gtd_widget_set_translation (self, priv->translation.x, g_value_get_float (value), priv->translation.z); - break; - - case PROP_TRANSLATION_Z: - gtd_widget_set_translation (self, priv->translation.x, priv->translation.y, g_value_get_float (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -gtd_widget_class_init (GtdWidgetClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - object_class->dispose = gtd_widget_dispose; - object_class->get_property = gtd_widget_get_property; - object_class->set_property = gtd_widget_set_property; - - /** - * GtdWidget: - */ - properties[PROP_PIVOT_POINT] = g_param_spec_boxed ("pivot-point", - "Pivot point", - "Pivot point", - GRAPHENE_TYPE_POINT3D, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdWidget:rotation-x - */ - properties[PROP_ROTATION_X] = g_param_spec_float ("rotation-x", - "Rotation in the X axis", - "Rotation in the X axis", - -G_MAXFLOAT, - G_MAXFLOAT, - 0.f, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdWidget:rotation-y - */ - properties[PROP_ROTATION_Y] = g_param_spec_float ("rotation-y", - "Rotation in the Y axis", - "Rotation in the Y axis", - -G_MAXFLOAT, - G_MAXFLOAT, - 0.f, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdWidget:rotation-z - */ - properties[PROP_ROTATION_Z] = g_param_spec_float ("rotation-z", - "Rotation in the Z axis", - "Rotation in the Z axis", - -G_MAXFLOAT, - G_MAXFLOAT, - 0.f, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdWidget:scale-x - */ - properties[PROP_SCALE_X] = g_param_spec_float ("scale-x", - "Scale in the X axis", - "Scale in the X axis", - -G_MAXFLOAT, - G_MAXFLOAT, - 1.f, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdWidget:scale-y - */ - properties[PROP_SCALE_Y] = g_param_spec_float ("scale-y", - "Scale in the Y axis", - "Scale in the Y axis", - -G_MAXFLOAT, - G_MAXFLOAT, - 1.f, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdWidget:scale-z - */ - properties[PROP_SCALE_Z] = g_param_spec_float ("scale-z", - "Scale in the Z axis", - "Scale in the Z axis", - -G_MAXFLOAT, - G_MAXFLOAT, - 1.f, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdWidget:translation-x - */ - properties[PROP_TRANSLATION_X] = g_param_spec_float ("translation-x", - "Translation in the X axis", - "Translation in the X axis", - -G_MAXFLOAT, - G_MAXFLOAT, - 0.f, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdWidget:translation-y - */ - properties[PROP_TRANSLATION_Y] = g_param_spec_float ("translation-y", - "Translation in the Y axis", - "Translation in the Y axis", - -G_MAXFLOAT, - G_MAXFLOAT, - 0.f, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - /** - * GtdWidget:translation-z - */ - properties[PROP_TRANSLATION_Z] = g_param_spec_float ("translation-z", - "Translation in the Z axis", - "Translation in the Z axis", - -G_MAXFLOAT, - G_MAXFLOAT, - 0.f, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, N_PROPS, properties); - - /** - * GtdWidget::transitions-completed: - * @actor: a #GtdWidget - * - * The ::transitions-completed signal is emitted once all transitions - * involving @actor are complete. - * - * Since: 1.10 - */ - signals[TRANSITIONS_COMPLETED] = - g_signal_new ("transitions-completed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, - 0); - - /** - * GtdWidget::transition-stopped: - * @actor: a #GtdWidget - * @name: the name of the transition - * @is_finished: whether the transition was finished, or stopped - * - * The ::transition-stopped signal is emitted once a transition - * is stopped; a transition is stopped once it reached its total - * duration (including eventual repeats), it has been stopped - * using gtd_timeline_stop(), or it has been removed from the - * transitions applied on @actor, using gtd_actor_remove_transition(). - * - * Since: 1.12 - */ - signals[TRANSITION_STOPPED] = - g_signal_new ("transition-stopped", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | - G_SIGNAL_NO_HOOKS | G_SIGNAL_DETAILED, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_BOOLEAN); - - gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); -} - -static void -gtd_widget_init (GtdWidget *self) -{ - GtdWidgetPrivate *priv = gtd_widget_get_instance_private (self); - - priv->scale[X] = 1.f; - priv->scale[Y] = 1.f; - priv->scale[Z] = 1.f; - - priv->pivot_point = GRAPHENE_POINT3D_INIT (0.5, 0.5, 0.f); - - gtd_widget_save_easing_state (self); - gtd_widget_set_easing_duration (self, 0); -} - -GtkWidget* -gtd_widget_new (void) -{ - return g_object_new (GTD_TYPE_WIDGET, NULL); -} - -/** - */ -void -gtd_widget_get_pivot_point (GtdWidget *self, - graphene_point3d_t *out_pivot_point) -{ - GtdWidgetPrivate *priv; - - g_return_if_fail (GTD_IS_WIDGET (self)); - g_return_if_fail (out_pivot_point != NULL); - - priv = gtd_widget_get_instance_private (self); - *out_pivot_point = priv->pivot_point; -} - -/** - */ -void -gtd_widget_set_pivot_point (GtdWidget *self, - const graphene_point3d_t *pivot_point) -{ - GtdWidgetPrivate *priv; - - GTD_ENTRY; - - g_return_if_fail (GTD_IS_WIDGET (self)); - g_return_if_fail (pivot_point != NULL); - g_return_if_fail (pivot_point->x >= 0.f && pivot_point->x <= 1.0); - g_return_if_fail (pivot_point->y >= 0.f && pivot_point->y <= 1.0); - - priv = gtd_widget_get_instance_private (self); - - if (graphene_point3d_equal (&priv->pivot_point, pivot_point)) - GTD_RETURN (); - - invalidate_cached_transform (self); - priv->pivot_point = *pivot_point; - - gtk_widget_queue_resize (GTK_WIDGET (self)); - - GTD_EXIT; -} - -/** - */ -void -gtd_widget_get_rotation (GtdWidget *self, - gfloat *rotation_x, - gfloat *rotation_y, - gfloat *rotation_z) -{ - GtdWidgetPrivate *priv; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - if (rotation_x) - *rotation_x = priv->rotation[X]; - - if (rotation_y) - *rotation_y = priv->rotation[Y]; - - if (rotation_z) - *rotation_z = priv->rotation[Z]; -} - -/** - */ -void -gtd_widget_set_rotation (GtdWidget *self, - gfloat rotation_x, - gfloat rotation_y, - gfloat rotation_z) -{ - GtdWidgetPrivate *priv; - gboolean changed[3]; - - GTD_ENTRY; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - changed[X] = !G_APPROX_VALUE (priv->rotation[X], rotation_x, FLT_EPSILON); - changed[Y] = !G_APPROX_VALUE (priv->rotation[Y], rotation_y, FLT_EPSILON); - changed[Z] = !G_APPROX_VALUE (priv->rotation[Z], rotation_z, FLT_EPSILON); - - if (!changed[X] && !changed[Y] && !changed[Z]) - GTD_RETURN (); - - if (changed[X]) - create_transition (self, properties[PROP_ROTATION_X], priv->rotation[X], rotation_x); - - if (changed[Y]) - create_transition (self, properties[PROP_ROTATION_Y], priv->rotation[Y], rotation_y); - - if (changed[Z]) - create_transition (self, properties[PROP_ROTATION_Z], priv->rotation[Z], rotation_z); - - GTD_EXIT; -} - -/** - */ -void -gtd_widget_get_scale (GtdWidget *self, - gfloat *scale_x, - gfloat *scale_y, - gfloat *scale_z) -{ - GtdWidgetPrivate *priv; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - if (scale_x) - *scale_x = priv->scale[0]; - - if (scale_y) - *scale_y = priv->scale[1]; - - if (scale_z) - *scale_z = priv->scale[2]; -} - -/** - */ -void -gtd_widget_set_scale (GtdWidget *self, - gfloat scale_x, - gfloat scale_y, - gfloat scale_z) -{ - GtdWidgetPrivate *priv; - gboolean changed[3]; - - GTD_ENTRY; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - changed[X] = !G_APPROX_VALUE (priv->scale[X], scale_x, FLT_EPSILON); - changed[Y] = !G_APPROX_VALUE (priv->scale[Y], scale_y, FLT_EPSILON); - changed[Z] = !G_APPROX_VALUE (priv->scale[Z], scale_z, FLT_EPSILON); - - if (!changed[X] && !changed[Y] && !changed[Z]) - GTD_RETURN (); - - if (changed[X]) - create_transition (self, properties[PROP_SCALE_X], priv->scale[X], scale_x); - - if (changed[Y]) - create_transition (self, properties[PROP_SCALE_Y], priv->scale[Y], scale_y); - - if (changed[Z]) - create_transition (self, properties[PROP_SCALE_Z], priv->scale[Z], scale_z); - - GTD_EXIT; -} - -/** - */ -void -gtd_widget_get_translation (GtdWidget *self, - gfloat *translation_x, - gfloat *translation_y, - gfloat *translation_z) -{ - GtdWidgetPrivate *priv; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - if (translation_x) - *translation_x = priv->translation.x; - - if (translation_y) - *translation_y = priv->translation.y; - - if (translation_z) - *translation_z = priv->translation.z; -} - -/** - */ -void -gtd_widget_set_translation (GtdWidget *self, - gfloat translation_x, - gfloat translation_y, - gfloat translation_z) -{ - graphene_point3d_t translation; - GtdWidgetPrivate *priv; - - GTD_ENTRY; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - translation = GRAPHENE_POINT3D_INIT (translation_x, translation_y, translation_z); - - if (graphene_point3d_equal (&priv->translation, &translation)) - GTD_RETURN (); - - if (!G_APPROX_VALUE (priv->translation.x, translation.x, FLT_EPSILON)) - create_transition (self, properties[PROP_TRANSLATION_X], priv->translation.x, translation_x); - - if (!G_APPROX_VALUE (priv->translation.y, translation.y, FLT_EPSILON)) - create_transition (self, properties[PROP_TRANSLATION_Y], priv->translation.y, translation_y); - - if (!G_APPROX_VALUE (priv->translation.y, translation.y, FLT_EPSILON)) - create_transition (self, properties[PROP_TRANSLATION_Z], priv->translation.z, translation_z); - - GTD_EXIT; -} - -/** - */ -GskTransform* -gtd_widget_apply_transform (GtdWidget *self, - GskTransform *transform) -{ - GtdWidgetPrivate *priv; - - g_return_val_if_fail (GTD_IS_WIDGET (self), NULL); - - priv = gtd_widget_get_instance_private (self); - - if (!priv->cached_transform) - calculate_transform (self); - - if (!transform) - return gsk_transform_ref (priv->cached_transform); - - return gsk_transform_transform (transform, priv->cached_transform); -} - -/** - * gtd_widget_add_transition: - * @self: a #GtdWidget - * @name: the name of the transition to add - * @transition: the #GtdTransition to add - * - * Adds a @transition to the #GtdWidget's list of animations. - * - * The @name string is a per-widget unique identifier of the @transition: only - * one #GtdTransition can be associated to the specified @name. - * - * The @transition will be started once added. - * - * This function will take a reference on the @transition. - * - * This function is usually called implicitly when modifying an animatable - * property. - * - * Since: 1.10 - */ -void -gtd_widget_add_transition (GtdWidget *self, - const gchar *name, - GtdTransition *transition) -{ - g_return_if_fail (GTD_IS_WIDGET (self)); - g_return_if_fail (name != NULL); - g_return_if_fail (GTD_IS_TRANSITION (transition)); - - add_transition_to_widget (self, name, transition); -} - -/** - * gtd_widget_remove_transition: - * @self: a #GtdWidget - * @name: the name of the transition to remove - * - * Removes the transition stored inside a #GtdWidget using @name - * identifier. - * - * If the transition is currently in progress, it will be stopped. - * - * This function releases the reference acquired when the transition - * was added to the #GtdWidget. - * - * Since: 1.10 - */ -void -gtd_widget_remove_transition (GtdWidget *self, - const gchar *name) -{ - GtdWidgetPrivate *priv; - TransitionClosure *closure; - gboolean was_playing; - GQuark t_quark; - gchar *t_name; - - g_return_if_fail (GTD_IS_WIDGET (self)); - g_return_if_fail (name != NULL); - - priv = gtd_widget_get_instance_private (self); - - if (priv->animation.transitions == NULL) - return; - - closure = g_hash_table_lookup (priv->animation.transitions, name); - if (closure == NULL) - return; - - was_playing = - gtd_timeline_is_playing (GTD_TIMELINE (closure->transition)); - t_quark = g_quark_from_string (closure->name); - t_name = g_strdup (closure->name); - - g_hash_table_remove (priv->animation.transitions, name); - - /* we want to maintain the invariant that ::transition-stopped is - * emitted after the transition has been removed, to allow replacing - * or chaining; removing the transition from the hash table will - * stop it, but transition_closure_free() will disconnect the signal - * handler we install in add_transition_internal(), to avoid loops - * or segfaults. - * - * since we know already that a transition will stop once it's removed - * from an widget, we can simply emit the ::transition-stopped here - * ourselves, if the timeline was playing (if it wasn't, then the - * signal was already emitted at least once). - */ - if (was_playing) - g_signal_emit (self, signals[TRANSITION_STOPPED], t_quark, t_name, FALSE); - - g_free (t_name); -} - -/** - * gtd_widget_remove_all_transitions: - * @self: a #GtdWidget - * - * Removes all transitions associated to @self. - * - * Since: 1.10 - */ -void -gtd_widget_remove_all_transitions (GtdWidget *self) -{ - GtdWidgetPrivate *priv; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - if (priv->animation.transitions == NULL) - return; - - g_hash_table_remove_all (priv->animation.transitions); -} - -/** - * gtd_widget_set_easing_duration: - * @self: a #GtdWidget - * @msecs: the duration of the easing, or %NULL - * - * Sets the duration of the tweening for animatable properties - * of @self for the current easing state. - * - * Since: 1.10 - */ -void -gtd_widget_set_easing_duration (GtdWidget *self, - guint msecs) -{ - GtdWidgetPrivate *priv; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - if (priv->animation.current_state == NULL) - { - g_warning ("You must call gtd_widget_save_easing_state() prior " - "to calling gtd_widget_set_easing_duration()."); - return; - } - - if (priv->animation.current_state->easing_duration != msecs) - priv->animation.current_state->easing_duration = msecs; -} - -/** - * gtd_widget_get_easing_duration: - * @self: a #GtdWidget - * - * Retrieves the duration of the tweening for animatable - * properties of @self for the current easing state. - * - * Return value: the duration of the tweening, in milliseconds - * - * Since: 1.10 - */ -guint -gtd_widget_get_easing_duration (GtdWidget *self) -{ - GtdWidgetPrivate *priv; - - g_return_val_if_fail (GTD_IS_WIDGET (self), 0); - - priv = gtd_widget_get_instance_private (self); - if (priv->animation.current_state != NULL) - return priv->animation.current_state->easing_duration; - - return 0; -} - -/** - * gtd_widget_set_easing_mode: - * @self: a #GtdWidget - * @mode: an easing mode, excluding %GTD_CUSTOM_MODE - * - * Sets the easing mode for the tweening of animatable properties - * of @self. - * - * Since: 1.10 - */ -void -gtd_widget_set_easing_mode (GtdWidget *self, - GtdEaseMode mode) -{ - GtdWidgetPrivate *priv; - - g_return_if_fail (GTD_IS_WIDGET (self)); - g_return_if_fail (mode != GTD_CUSTOM_MODE); - g_return_if_fail (mode < GTD_EASE_LAST); - - priv = gtd_widget_get_instance_private (self); - if (priv->animation.current_state == NULL) - { - g_warning ("You must call gtd_widget_save_easing_state() prior " - "to calling gtd_widget_set_easing_mode()."); - return; - } - - if (priv->animation.current_state->easing_mode != mode) - priv->animation.current_state->easing_mode = mode; -} - -/** - * gtd_widget_get_easing_mode: - * @self: a #GtdWidget - * - * Retrieves the easing mode for the tweening of animatable properties - * of @self for the current easing state. - * - * Return value: an easing mode - * - * Since: 1.10 - */ -GtdEaseMode -gtd_widget_get_easing_mode (GtdWidget *self) -{ - GtdWidgetPrivate *priv; - - g_return_val_if_fail (GTD_IS_WIDGET (self), GTD_EASE_OUT_CUBIC); - - priv = gtd_widget_get_instance_private (self); - - if (priv->animation.current_state != NULL) - return priv->animation.current_state->easing_mode; - - return GTD_EASE_OUT_CUBIC; -} - -/** - * gtd_widget_set_easing_delay: - * @self: a #GtdWidget - * @msecs: the delay before the start of the tweening, in milliseconds - * - * Sets the delay that should be applied before tweening animatable - * properties. - * - * Since: 1.10 - */ -void -gtd_widget_set_easing_delay (GtdWidget *self, - guint msecs) -{ - GtdWidgetPrivate *priv; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - if (priv->animation.current_state == NULL) - { - g_warning ("You must call gtd_widget_save_easing_state() prior " - "to calling gtd_widget_set_easing_delay()."); - return; - } - - if (priv->animation.current_state->easing_delay != msecs) - priv->animation.current_state->easing_delay = msecs; -} - -/** - * gtd_widget_get_easing_delay: - * @self: a #GtdWidget - * - * Retrieves the delay that should be applied when tweening animatable - * properties. - * - * Return value: a delay, in milliseconds - * - * Since: 1.10 - */ -guint -gtd_widget_get_easing_delay (GtdWidget *self) -{ - GtdWidgetPrivate *priv; - - g_return_val_if_fail (GTD_IS_WIDGET (self), 0); - - priv = gtd_widget_get_instance_private (self); - - if (priv->animation.current_state != NULL) - return priv->animation.current_state->easing_delay; - - return 0; -} - -/** - * gtd_widget_get_transition: - * @self: a #GtdWidget - * @name: the name of the transition - * - * Retrieves the #GtdTransition of a #GtdWidget by using the - * transition @name. - * - * Transitions created for animatable properties use the name of the - * property itself, for instance the code below: - * - * |[<!-- language="C" --> - * gtd_widget_set_easing_duration (widget, 1000); - * gtd_widget_set_rotation_angle (widget, GTD_Y_AXIS, 360.0); - * - * transition = gtd_widget_get_transition (widget, "rotation-angle-y"); - * g_signal_connect (transition, "stopped", - * G_CALLBACK (on_transition_stopped), - * widget); - * ]| - * - * will call the `on_transition_stopped` callback when the transition - * is finished. - * - * If you just want to get notifications of the completion of a transition, - * you should use the #GtdWidget::transition-stopped signal, using the - * transition name as the signal detail. - * - * Return value: (transfer none): a #GtdTransition, or %NULL is none - * was found to match the passed name; the returned instance is owned - * by Gtd and it should not be freed - */ -GtdTransition * -gtd_widget_get_transition (GtdWidget *self, - const gchar *name) -{ - TransitionClosure *closure; - GtdWidgetPrivate *priv; - - g_return_val_if_fail (GTD_IS_WIDGET (self), NULL); - g_return_val_if_fail (name != NULL, NULL); - - priv = gtd_widget_get_instance_private (self); - if (priv->animation.transitions == NULL) - return NULL; - - closure = g_hash_table_lookup (priv->animation.transitions, name); - if (closure == NULL) - return NULL; - - return closure->transition; -} - -/** - * gtd_widget_has_transitions: (skip) - */ -gboolean -gtd_widget_has_transitions (GtdWidget *self) -{ - GtdWidgetPrivate *priv; - - g_return_val_if_fail (GTD_IS_WIDGET (self), FALSE); - - priv = gtd_widget_get_instance_private (self); - if (priv->animation.transitions == NULL) - return FALSE; - - return g_hash_table_size (priv->animation.transitions) > 0; -} - -/** - * gtd_widget_save_easing_state: - * @self: a #GtdWidget - * - * Saves the current easing state for animatable properties, and creates - * a new state with the default values for easing mode and duration. - * - * New transitions created after calling this function will inherit the - * duration, easing mode, and delay of the new easing state; this also - * applies to transitions modified in flight. - */ -void -gtd_widget_save_easing_state (GtdWidget *self) -{ - GtdWidgetPrivate *priv; - AnimationState new_state; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - if (priv->animation.states == NULL) - priv->animation.states = g_array_new (FALSE, FALSE, sizeof (AnimationState)); - - new_state.easing_mode = GTD_EASE_OUT_CUBIC; - new_state.easing_duration = 250; - new_state.easing_delay = 0; - - g_array_append_val (priv->animation.states, new_state); - - priv->animation.current_state = &g_array_index (priv->animation.states, - AnimationState, - priv->animation.states->len - 1); -} - -/** - * gtd_widget_restore_easing_state: - * @self: a #GtdWidget - * - * Restores the easing state as it was prior to a call to - * gtd_widget_save_easing_state(). - * - * Since: 1.10 - */ -void -gtd_widget_restore_easing_state (GtdWidget *self) -{ - GtdWidgetPrivate *priv; - - g_return_if_fail (GTD_IS_WIDGET (self)); - - priv = gtd_widget_get_instance_private (self); - - if (priv->animation.states == NULL) - { - g_critical ("The function gtd_widget_restore_easing_state() has " - "been called without a previous call to " - "gtd_widget_save_easing_state()."); - return; - } - - g_array_remove_index (priv->animation.states, priv->animation.states->len - 1); - - if (priv->animation.states->len > 0) - priv->animation.current_state = &g_array_index (priv->animation.states, AnimationState, priv->animation.states->len - 1); - else - { - g_array_unref (priv->animation.states); - priv->animation.states = NULL; - priv->animation.current_state = NULL; - } -} diff --git a/src/gui/gtd-widget.h b/src/gui/gtd-widget.h deleted file mode 100644 index c7b4ad27..00000000 --- a/src/gui/gtd-widget.h +++ /dev/null @@ -1,110 +0,0 @@ -/* gtd-'gtd-widget.c',.h - * - * Copyright 2018-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 - */ - -#pragma once - -#include <gtk/gtk.h> - -#include "gtd-animation-enums.h" -#include "gtd-types.h" - -G_BEGIN_DECLS - -#define GTD_TYPE_WIDGET (gtd_widget_get_type ()) -G_DECLARE_DERIVABLE_TYPE (GtdWidget, gtd_widget, GTD, WIDGET, GtkWidget) - -struct _GtdWidgetClass -{ - GtkWidgetClass parent; -}; - -GtkWidget* gtd_widget_new (void); - -void gtd_widget_get_pivot_point (GtdWidget *self, - graphene_point3d_t *out_pivot_point); - -void gtd_widget_set_pivot_point (GtdWidget *self, - const graphene_point3d_t *pivot_point); - -void gtd_widget_get_rotation (GtdWidget *self, - gfloat *rotation_x, - gfloat *rotation_y, - gfloat *rotation_z); - -void gtd_widget_set_rotation (GtdWidget *self, - gfloat rotation_x, - gfloat rotation_y, - gfloat rotation_z); - -void gtd_widget_get_scale (GtdWidget *self, - gfloat *scale_x, - gfloat *scale_y, - gfloat *scale_z); - -void gtd_widget_set_scale (GtdWidget *self, - gfloat scale_x, - gfloat scale_y, - gfloat scale_z); - -void gtd_widget_get_translation (GtdWidget *self, - gfloat *translation_x, - gfloat *translation_y, - gfloat *translation_z); - -void gtd_widget_set_translation (GtdWidget *self, - gfloat translation_x, - gfloat translation_y, - gfloat translation_z); - -GskTransform* gtd_widget_apply_transform (GtdWidget *self, - GskTransform *transform); - -void gtd_widget_save_easing_state (GtdWidget *self); - -void gtd_widget_restore_easing_state (GtdWidget *self); - -void gtd_widget_set_easing_mode (GtdWidget *self, - GtdEaseMode mode); - -GtdEaseMode gtd_widget_get_easing_mode (GtdWidget *self); - -void gtd_widget_set_easing_duration (GtdWidget *self, - guint msecs); - -guint gtd_widget_get_easing_duration (GtdWidget *self); - -void gtd_widget_set_easing_delay (GtdWidget *self, - guint msecs); - -guint gtd_widget_get_easing_delay (GtdWidget *self); - -GtdTransition* gtd_widget_get_transition (GtdWidget *self, - const gchar *name); - -void gtd_widget_add_transition (GtdWidget *self, - const gchar *name, - GtdTransition *transition); - -void gtd_widget_remove_transition (GtdWidget *self, - const gchar *name); - -void gtd_widget_remove_all_transitions (GtdWidget *self); - -G_END_DECLS diff --git a/src/meson.build b/src/meson.build index 85ce891a..8b2ec8c8 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,8 +1,8 @@ sources = [] -####### -# VCS # -####### +########## +# Config # +########## configure_file(output: 'config.h', configuration: config_h) @@ -15,31 +15,11 @@ vcs_identifier_h = declare_dependency(sources: vcs_tag) endeavour_deps += vcs_identifier_h -######### -# Enums # -######### - -enum_headers = files( - join_paths('animation', 'gtd-animation-enums.h'), -) - -enum_types = 'gtd-enum-types' - -gtd_enum_types = gnome.mkenums( - enum_types, - sources: enum_headers, - c_template: enum_types + '.c.template', - h_template: enum_types + '.h.template' -) - -sources += gtd_enum_types - -########### -# Plugins # -########### +################ +# Header files # +################ incs = include_directories( - 'animation', 'core', 'engine', 'gui', @@ -53,73 +33,10 @@ incs = include_directories( subdir('gui') ################ -# Header files # -################ - -headers = files( - 'animation/gtd-animatable.h', - 'animation/gtd-animation-utils.h', - 'animation/gtd-easing.h', - 'animation/gtd-interval.h', - 'animation/gtd-keyframe-transition.h', - 'animation/gtd-property-transition.h', - 'animation/gtd-timeline.h', - 'animation/gtd-transition.h', - 'core/gtd-clock.h', - 'core/gtd-manager.h', - 'core/gtd-notification.h', - 'core/gtd-object.h', - 'core/gtd-provider.h', - 'core/gtd-task.h', - 'core/gtd-task-list.h', - 'core/gtd-utils.h', - 'engine/e-source-endeavour.h', - 'engine/gtd-engine.h', - 'engine/gtd-provider-eds.h', - 'engine/gtd-provider-goa.h', - 'engine/gtd-provider-local.h', - 'engine/gtd-task-eds.h', - 'engine/gtd-task-list-eds.h', - 'gui/gtd-max-size-layout.h', - 'gui/gtd-menu-button.h', - 'gui/gtd-panel.h', - 'gui/gtd-panel-all-tasks.h', - 'gui/gtd-panel-inbox.h', - 'gui/gtd-panel-next-week.h', - 'gui/gtd-panel-task-list.h', - 'gui/gtd-panel-today.h', - 'gui/gtd-provider-popover.h', - 'gui/gtd-sidebar.h', - 'gui/gtd-sidebar-list-row.h', - 'gui/gtd-sidebar-panel-row.h', - 'gui/gtd-sidebar-provider-row.h', - 'gui/gtd-star-widget.h', - 'gui/gtd-task-lists-workspace.h', - 'gui/gtd-task-list-view.h', - 'gui/gtd-widget.h', - 'gui/gtd-window.h', - 'gui/gtd-workspace.h', - 'models/gtd-list-model-filter.h', - 'models/gtd-list-store.h', - 'gtd-types.h' -) - -install_headers(headers, subdir: meson.project_name()) - - -################ # Source files # ################ sources += files( - 'animation/gtd-animatable.c', - 'animation/gtd-animation-utils.c', - 'animation/gtd-easing.c', - 'animation/gtd-interval.c', - 'animation/gtd-keyframe-transition.c', - 'animation/gtd-property-transition.c', - 'animation/gtd-timeline.c', - 'animation/gtd-transition.c', 'core/gtd-clock.c', 'core/gtd-log.c', 'core/gtd-manager.c', @@ -136,13 +53,19 @@ sources += files( 'engine/gtd-provider-local.c', 'engine/gtd-task-eds.c', 'engine/gtd-task-list-eds.c', + 'gui/gtd-application.c', + 'gui/gtd-color-button.c', + 'gui/gtd-edit-pane.c', + 'gui/gtd-markdown-renderer.c', + 'gui/gtd-max-size-layout.c', + 'gui/gtd-menu-button.c', + 'gui/gtd-new-task-row.c', 'gui/gtd-panel.c', 'gui/gtd-panel-all-tasks.c', 'gui/gtd-panel-inbox.c', 'gui/gtd-panel-next-week.c', 'gui/gtd-panel-task-list.c', 'gui/gtd-panel-today.c', - 'gui/gtd-workspace.c', 'gui/gtd-provider-popover.c', 'gui/gtd-provider-row.c', 'gui/gtd-provider-selector.c', @@ -150,29 +73,19 @@ sources += files( 'gui/gtd-sidebar-list-row.c', 'gui/gtd-sidebar-panel-row.c', 'gui/gtd-sidebar-provider-row.c', - 'gui/gtd-edit-pane.c', - 'gui/gtd-markdown-renderer.c', - 'gui/gtd-new-task-row.c', + 'gui/gtd-star-widget.c', 'gui/gtd-task-list-popover.c', 'gui/gtd-task-lists-workspace.c', 'gui/gtd-task-list-view.c', 'gui/gtd-task-row.c', - 'gui/gtd-color-button.c', - 'gui/gtd-menu-button.c', - 'gui/gtd-star-widget.c', - 'gui/gtd-application.c', - 'gui/gtd-max-size-layout.c', - 'gui/gtd-widget.c', 'gui/gtd-window.c', - 'models/gtd-list-model-filter.c', - 'models/gtd-list-model-sort.c', + 'gui/gtd-workspace.c', 'models/gtd-list-store.c', 'models/gtd-task-list-view-model.c', 'models/gtd-task-model.c', 'main.c' ) - ############# # Resources # ############# @@ -204,27 +117,11 @@ cflags = [ ldflags = [ '-Wl,--export-dynamic' ] - -######### -# Debug # -######### - -debug_conf = configuration_data() -debug_conf.set10('ENABLE_TRACING', endeavour_tracing) - - -sources += configure_file( - input: 'gtd-debug.h.in', - output: 'gtd-debug.h', - configuration: debug_conf, -) - - ############## -# endeavour # +# Endeavour # ############## -endeavour = executable( +executable( meson.project_name(), sources, include_directories: incs, @@ -234,13 +131,3 @@ endeavour = executable( install: true, install_dir: endeavour_bindir ) - -libgtd = shared_library( - 'gtd', - sources: sources, - version: libversion, - soversion: soversion, - include_directories: incs, - dependencies: endeavour_deps, - c_args: cflags -) |