[libadwaita] animation: Split out AdwTimedAnimation



commit 5993cbba16cbcb35f8ad525d1b8f4f332563b559
Author: Manuel Genovés <manuel genoves gmail com>
Date:   Tue Nov 16 13:41:50 2021 +0500

    animation: Split out AdwTimedAnimation

 src/adw-animation-private.h        |  31 ----
 src/adw-animation.c                | 250 +-----------------------------
 src/adw-carousel-indicator-dots.c  |   4 +-
 src/adw-carousel-indicator-lines.c |   4 +-
 src/adw-carousel.c                 |  10 +-
 src/adw-flap.c                     |  23 +--
 src/adw-tab-box.c                  |  51 ++++---
 src/adw-tab.c                      |  18 +--
 src/adw-timed-animation-private.h  |  54 +++++++
 src/adw-timed-animation.c          | 306 +++++++++++++++++++++++++++++++++++++
 src/adw-toast-overlay.c            |  10 +-
 src/meson.build                    |   2 +
 12 files changed, 429 insertions(+), 334 deletions(-)
---
diff --git a/src/adw-animation-private.h b/src/adw-animation-private.h
index 73467c1b..faca2343 100644
--- a/src/adw-animation-private.h
+++ b/src/adw-animation-private.h
@@ -26,15 +26,6 @@ G_BEGIN_DECLS
 
 G_DECLARE_DERIVABLE_TYPE (AdwAnimation, adw_animation, ADW, ANIMATION, GObject)
 
-typedef void   (*AdwAnimationDoneCallback)  (gpointer user_data);
-typedef double (*AdwAnimationEasingFunc)    (double   t);
-
-typedef enum {
-  ADW_ANIMATION_INTERPOLATOR_EASE_IN,
-  ADW_ANIMATION_INTERPOLATOR_EASE_OUT,
-  ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT,
-} AdwAnimationInterpolator;
-
 typedef enum {
   ADW_ANIMATION_IDLE,
   ADW_ANIMATION_PAUSED,
@@ -52,12 +43,6 @@ struct _AdwAnimationClass
                              guint         t);
 };
 
-AdwAnimation *adw_animation_new (GtkWidget          *widget,
-                                 double              from,
-                                 double              to,
-                                 guint               duration,
-                                 AdwAnimationTarget *target) G_GNUC_WARN_UNUSED_RESULT;
-
 GtkWidget *adw_animation_get_widget (AdwAnimation *self);
 
 AdwAnimationTarget *adw_animation_get_target (AdwAnimation *self);
@@ -72,20 +57,4 @@ void adw_animation_resume (AdwAnimation *self);
 void adw_animation_reset  (AdwAnimation *self);
 void adw_animation_skip   (AdwAnimation *self);
 
-double adw_animation_get_value_from (AdwAnimation *self);
-void   adw_animation_set_value_from (AdwAnimation *self,
-                                     double        value);
-
-double adw_animation_get_value_to (AdwAnimation *self);
-void   adw_animation_set_value_to (AdwAnimation *self,
-                                   double        value);
-
-guint adw_animation_get_duration (AdwAnimation *self);
-void  adw_animation_set_duration (AdwAnimation *self,
-                                  guint         duration);
-
-AdwAnimationInterpolator adw_animation_get_interpolator (AdwAnimation             *self);
-void                     adw_animation_set_interpolator (AdwAnimation             *self,
-                                                         AdwAnimationInterpolator  interpolator);
-
 G_END_DECLS
diff --git a/src/adw-animation.c b/src/adw-animation.c
index 7d233501..fbe3355e 100644
--- a/src/adw-animation.c
+++ b/src/adw-animation.c
@@ -16,17 +16,11 @@ typedef struct
 
   double value;
 
-  double value_from;
-  double value_to;
-  guint duration; /* ms */
-
   gint64 start_time; /* ms */
   gint64 paused_time;
   guint tick_cb_id;
   gulong unmap_cb_id;
 
-  AdwAnimationInterpolator interpolator;
-  AdwAnimationTargetFunc value_cb;
   AdwAnimationTarget *target;
   gpointer user_data;
 
@@ -39,10 +33,6 @@ enum {
   PROP_0,
   PROP_VALUE,
   PROP_WIDGET,
-  PROP_VALUE_FROM,
-  PROP_VALUE_TO,
-  PROP_DURATION,
-  PROP_INTERPOLATOR,
   PROP_TARGET,
   PROP_STATE,
   LAST_PROP,
@@ -141,37 +131,14 @@ tick_cb (GtkWidget     *widget,
 static guint
 adw_animation_estimate_duration (AdwAnimation *animation)
 {
-  AdwAnimationPrivate *priv = adw_animation_get_instance_private (animation);
-
-  return priv->duration;
+  g_assert_not_reached ();
 }
 
 static double
 adw_animation_calculate_value (AdwAnimation *animation,
                                guint         t)
 {
-  AdwAnimationPrivate *priv = adw_animation_get_instance_private (animation);
-  double value;
-
-  if (priv->duration > 0) {
-    switch (priv->interpolator) {
-      case ADW_ANIMATION_INTERPOLATOR_EASE_IN:
-        value = adw_ease_in_cubic ((double) t / priv->duration);
-        break;
-      case ADW_ANIMATION_INTERPOLATOR_EASE_OUT:
-        value = adw_ease_out_cubic ((double) t / priv->duration);
-        break;
-      case ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT:
-        value = adw_ease_in_out_cubic ((double) t / priv->duration);
-        break;
-      default:
-        g_assert_not_reached ();
-  }
-  } else {
-    value = 1;
-  }
-
-  return adw_lerp (priv->value_from, priv->value_to, value);
+  g_assert_not_reached ();
 }
 
 static void
@@ -255,22 +222,6 @@ adw_animation_get_property (GObject    *object,
     g_value_set_object (value, adw_animation_get_widget (self));
     break;
 
-  case PROP_VALUE_FROM:
-    g_value_set_double (value, adw_animation_get_value_from (self));
-    break;
-
-  case PROP_VALUE_TO:
-    g_value_set_double (value, adw_animation_get_value_to (self));
-    break;
-
-  case PROP_DURATION:
-    g_value_set_uint (value, adw_animation_get_duration (self));
-    break;
-
-  case PROP_INTERPOLATOR:
-    g_value_set_enum (value, adw_animation_get_interpolator (self));
-    break;
-
   case PROP_TARGET:
     g_value_set_object (value, adw_animation_get_target (self));
     break;
@@ -298,22 +249,6 @@ adw_animation_set_property (GObject      *object,
     set_widget (self, g_value_get_object (value));
     break;
 
-  case PROP_VALUE_FROM:
-    adw_animation_set_value_from (self, g_value_get_double (value));
-    break;
-
-  case PROP_VALUE_TO:
-    adw_animation_set_value_to (self, g_value_get_double (value));
-    break;
-
-  case PROP_DURATION:
-    adw_animation_set_duration (self, g_value_get_uint (value));
-    break;
-
-  case PROP_INTERPOLATOR:
-    adw_animation_set_interpolator (self, g_value_get_enum (value));
-    break;
-
   case PROP_TARGET:
     g_set_object (&priv->target, g_value_get_object (value));
     break;
@@ -352,41 +287,6 @@ adw_animation_class_init (AdwAnimationClass *klass)
                          GTK_TYPE_WIDGET,
                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
 
-  props[PROP_VALUE_FROM] =
-    g_param_spec_double ("value-from",
-                         "Initial value",
-                         "Initial value of the animation",
-                         -G_MAXDOUBLE,
-                         G_MAXDOUBLE,
-                         0,
-                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
-
-  props[PROP_VALUE_TO] =
-    g_param_spec_double ("value-to",
-                         "Final value",
-                         "Final value of the animation",
-                         -G_MAXDOUBLE,
-                         G_MAXDOUBLE,
-                         0,
-                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
-
-  props[PROP_DURATION] =
-    g_param_spec_uint ("duration",
-                       "Duration",
-                       "Duration of the animation",
-                       0,
-                       G_MAXUINT,
-                       0,
-                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
-
-  props[PROP_INTERPOLATOR] =
-    g_param_spec_enum ("interpolator",
-                       "Interpolator",
-                       "Easing function used in the animation",
-                       ADW_TYPE_ANIMATION_INTERPOLATOR,
-                       ADW_ANIMATION_INTERPOLATOR_EASE_OUT,
-                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
-
   props[PROP_TARGET] =
     g_param_spec_object ("target",
                          "Target",
@@ -422,31 +322,6 @@ adw_animation_init (AdwAnimation *self)
   priv->state = ADW_ANIMATION_IDLE;
 }
 
-AdwAnimation *
-adw_animation_new (GtkWidget          *widget,
-                   double              from,
-                   double              to,
-                   guint               duration,
-                   AdwAnimationTarget *target)
-{
-  AdwAnimation *animation;
-
-  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
-  g_return_val_if_fail (ADW_IS_ANIMATION_TARGET (target), NULL);
-
-  animation = g_object_new (ADW_TYPE_ANIMATION,
-                            "widget", widget,
-                            "value-from", from,
-                            "value-to", to,
-                            "duration", duration,
-                            "target", target,
-                            NULL);
-
-  g_object_unref (target);
-
-  return animation;
-}
-
 GtkWidget *
 adw_animation_get_widget (AdwAnimation *self)
 {
@@ -623,124 +498,3 @@ adw_animation_reset (AdwAnimation *self)
   if (was_playing)
     g_object_unref (self);
 }
-
-double
-adw_animation_get_value_from (AdwAnimation *self)
-{
-  AdwAnimationPrivate *priv;
-
-  g_return_val_if_fail (ADW_IS_ANIMATION (self), 0.0);
-
-  priv = adw_animation_get_instance_private (self);
-
-  return priv->value_from;
-}
-
-void
-adw_animation_set_value_from (AdwAnimation *self,
-                              double        value)
-{
-  AdwAnimationPrivate *priv;
-
-  g_return_if_fail (ADW_IS_ANIMATION (self));
-
-  priv = adw_animation_get_instance_private (self);
-
-  if (priv->value_from == value)
-    return;
-
-  priv->value_from = value;
-
-  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VALUE_FROM]);
-}
-
-double
-adw_animation_get_value_to (AdwAnimation *self)
-{
-  AdwAnimationPrivate *priv;
-
-  g_return_val_if_fail (ADW_IS_ANIMATION (self), 0.0);
-
-  priv = adw_animation_get_instance_private (self);
-
-  return priv->value_to;
-}
-
-void
-adw_animation_set_value_to (AdwAnimation *self,
-                            double        value)
-{
-  AdwAnimationPrivate *priv;
-
-  g_return_if_fail (ADW_IS_ANIMATION (self));
-
-  priv = adw_animation_get_instance_private (self);
-
-  if (priv->value_to == value)
-    return;
-
-  priv->value_to = value;
-
-  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VALUE_TO]);
-}
-
-guint
-adw_animation_get_duration (AdwAnimation *self)
-{
-  AdwAnimationPrivate *priv;
-
-  g_return_val_if_fail (ADW_IS_ANIMATION (self), 0);
-
-  priv = adw_animation_get_instance_private (self);
-
-  return priv->duration;
-}
-
-void
-adw_animation_set_duration (AdwAnimation *self,
-                            guint         duration)
-{
-  AdwAnimationPrivate *priv;
-
-  g_return_if_fail (ADW_IS_ANIMATION (self));
-
-  priv = adw_animation_get_instance_private (self);
-
-  if (priv->duration == duration)
-    return;
-
-  priv->duration = duration;
-
-  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DURATION]);
-}
-
-AdwAnimationInterpolator
-adw_animation_get_interpolator (AdwAnimation *self)
-{
-  AdwAnimationPrivate *priv;
-
-  g_return_val_if_fail (ADW_IS_ANIMATION (self), ADW_ANIMATION_INTERPOLATOR_EASE_OUT);
-
-  priv = adw_animation_get_instance_private (self);
-
-  return priv->interpolator;
-}
-
-void
-adw_animation_set_interpolator (AdwAnimation             *self,
-                                AdwAnimationInterpolator  interpolator)
-{
-  AdwAnimationPrivate *priv;
-
-  g_return_if_fail (ADW_IS_ANIMATION (self));
-  g_return_if_fail (interpolator <= ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT);
-
-  priv = adw_animation_get_instance_private (self);
-
-  if (priv->interpolator == interpolator)
-    return;
-
-  priv->interpolator = interpolator;
-
-  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INTERPOLATOR]);
-}
diff --git a/src/adw-carousel-indicator-dots.c b/src/adw-carousel-indicator-dots.c
index 17873b74..ac9f3000 100644
--- a/src/adw-carousel-indicator-dots.c
+++ b/src/adw-carousel-indicator-dots.c
@@ -9,9 +9,9 @@
 #include "adw-carousel-indicator-dots.h"
 
 #include "adw-animation-util-private.h"
-#include "adw-animation-private.h"
 #include "adw-macros-private.h"
 #include "adw-swipeable.h"
+#include "adw-timed-animation-private.h"
 
 #include <math.h>
 
@@ -343,7 +343,7 @@ adw_carousel_indicator_dots_init (AdwCarouselIndicatorDots *self)
                                          self, NULL);
 
   self->animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 1, 0, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 1, 0, target);
 }
 
 /**
diff --git a/src/adw-carousel-indicator-lines.c b/src/adw-carousel-indicator-lines.c
index 6078d63e..030951e5 100644
--- a/src/adw-carousel-indicator-lines.c
+++ b/src/adw-carousel-indicator-lines.c
@@ -8,9 +8,9 @@
 
 #include "adw-carousel-indicator-lines.h"
 
-#include "adw-animation-private.h"
 #include "adw-macros-private.h"
 #include "adw-swipeable.h"
+#include "adw-timed-animation-private.h"
 
 #include <math.h>
 
@@ -328,7 +328,7 @@ adw_carousel_indicator_lines_init (AdwCarouselIndicatorLines *self)
                                          self, NULL);
 
   self->animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 1, 0, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 1, 0, target);
 }
 
 /**
diff --git a/src/adw-carousel.c b/src/adw-carousel.c
index 6abb5a72..1bcf4060 100644
--- a/src/adw-carousel.c
+++ b/src/adw-carousel.c
@@ -9,11 +9,11 @@
 #include "adw-carousel.h"
 
 #include "adw-animation-util-private.h"
-#include "adw-animation-private.h"
 #include "adw-macros-private.h"
 #include "adw-navigation-direction.h"
 #include "adw-swipe-tracker.h"
 #include "adw-swipeable.h"
+#include "adw-timed-animation-private.h"
 #include "adw-widget-utils-private.h"
 
 #include <math.h>
@@ -330,7 +330,8 @@ animate_child_resize (AdwCarousel *self,
                                               resize_animation_value_cb,
                                               child, NULL);
   child->resize_animation =
-    adw_animation_new (GTK_WIDGET (self), old_size, value, duration, target);
+    adw_timed_animation_new (GTK_WIDGET (self), old_size,
+                             value, duration, target);
 
   g_signal_connect_swapped (child->resize_animation, "done",
                             G_CALLBACK (resize_animation_done_cb), child);
@@ -386,7 +387,8 @@ scroll_to (AdwCarousel *self,
 
   self->animation_source_position = self->position;
 
-  adw_animation_set_duration (self->animation, duration);
+  adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->animation),
+                                    duration);
   adw_animation_play (self->animation);
 }
 
@@ -1082,7 +1084,7 @@ adw_carousel_init (AdwCarousel *self)
                                               scroll_animation_value_cb,
                                               self, NULL);
   self->animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 1, 0, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 1, 0, target);
 
   g_signal_connect_swapped (self->animation, "done",
                             G_CALLBACK (scroll_animation_done_cb), self);
diff --git a/src/adw-flap.c b/src/adw-flap.c
index 34cea260..f361acf0 100644
--- a/src/adw-flap.c
+++ b/src/adw-flap.c
@@ -11,12 +11,12 @@
 #include <math.h>
 
 #include "adw-animation-util-private.h"
-#include "adw-animation-private.h"
 #include "adw-gizmo-private.h"
 #include "adw-macros-private.h"
 #include "adw-shadow-helper-private.h"
 #include "adw-swipeable.h"
 #include "adw-swipe-tracker-private.h"
+#include "adw-timed-animation-private.h"
 #include "adw-widget-utils-private.h"
 
 /**
@@ -288,11 +288,13 @@ fold_animation_value_cb (AdwFlap *self,
 static void
 animate_fold (AdwFlap *self)
 {
-  adw_animation_set_value_from (self->fold_animation, self->fold_progress);
-  adw_animation_set_value_to (self->fold_animation, self->folded ? 1 : 0);
+  adw_timed_animation_set_value_from (ADW_TIMED_ANIMATION (self->fold_animation),
+                                      self->fold_progress);
+  adw_timed_animation_set_value_to (ADW_TIMED_ANIMATION (self->fold_animation),
+                                    self->folded ? 1 : 0);
 
   /* When the flap is completely hidden, we can skip animation */
-  adw_animation_set_duration (self->fold_animation,
+  adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->fold_animation),
                              (self->reveal_progress > 0) ? self->fold_duration : 0);
 
   adw_animation_play (self->fold_animation);
@@ -315,9 +317,12 @@ animate_reveal (AdwFlap *self,
                 double   to,
                 guint    duration)
 {
-  adw_animation_set_value_from (self->reveal_animation, self->reveal_progress);
-  adw_animation_set_value_to (self->reveal_animation, to);
-  adw_animation_set_duration (self->reveal_animation, duration);
+  adw_timed_animation_set_value_from (ADW_TIMED_ANIMATION (self->reveal_animation),
+                                      self->reveal_progress);
+  adw_timed_animation_set_value_to (ADW_TIMED_ANIMATION (self->reveal_animation),
+                                    to);
+  adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->reveal_animation),
+                                    duration);
 
   adw_animation_play (self->reveal_animation);
 }
@@ -1598,13 +1603,13 @@ adw_flap_init (AdwFlap *self)
                                               fold_animation_value_cb,
                                               self, NULL);
   self->fold_animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 0, 0, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 0, 0, target);
 
   target = adw_callback_animation_target_new ((AdwAnimationTargetFunc)
                                               set_reveal_progress,
                                               self, NULL);
   self->reveal_animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 0, 0, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 0, 0, target);
 
   g_signal_connect_swapped (self->reveal_animation, "done",
                             G_CALLBACK (reveal_animation_done_cb), self);
diff --git a/src/adw-tab-box.c b/src/adw-tab-box.c
index cb10f406..8f975cff 100644
--- a/src/adw-tab-box.c
+++ b/src/adw-tab-box.c
@@ -10,12 +10,12 @@
 
 #include "adw-tab-box-private.h"
 #include "adw-animation-util-private.h"
-#include "adw-animation-private.h"
 #include "adw-gizmo-private.h"
 #include "adw-macros-private.h"
 #include "adw-tab-private.h"
 #include "adw-tab-bar-private.h"
 #include "adw-tab-view-private.h"
+#include "adw-timed-animation-private.h"
 #include <math.h>
 
 /* Border collapsing without glitches */
@@ -772,7 +772,8 @@ animate_scroll (AdwTabBox *self,
   self->scroll_animation_tab = info;
   self->scroll_animation_offset = offset;
 
-  adw_animation_set_duration (self->scroll_animation, duration);
+  adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->scroll_animation),
+                                    duration);
   adw_animation_play (self->scroll_animation);
 }
 
@@ -999,8 +1000,8 @@ animate_reordering (AdwTabBox *self,
                                               reorder_animation_value_cb,
                                               dest_tab, NULL);
   self->reorder_animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 1,
-                       REORDER_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 1,
+                             REORDER_ANIMATION_DURATION, target);
 
   g_signal_connect_swapped (self->reorder_animation, "done",
                             G_CALLBACK (reorder_animation_done_cb), self);
@@ -1052,8 +1053,8 @@ animate_reorder_offset (AdwTabBox *self,
                                               reorder_offset_animation_value_cb,
                                               info, NULL);
   info->reorder_animation =
-    adw_animation_new (GTK_WIDGET (self), info->reorder_offset, offset,
-                       REORDER_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), info->reorder_offset, offset,
+                             REORDER_ANIMATION_DURATION, target);
 
   g_signal_connect_swapped (info->reorder_animation, "done",
                             G_CALLBACK (reorder_offset_animation_done_cb), info);
@@ -1632,8 +1633,8 @@ page_attached_cb (AdwTabBox  *self,
                                               appear_animation_value_cb,
                                               info, NULL);
   info->appear_animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 1,
-                       OPEN_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 1,
+                             OPEN_ANIMATION_DURATION, target);
 
   g_signal_connect_swapped (info->appear_animation, "done",
                             G_CALLBACK (open_animation_done_cb), info);
@@ -1741,8 +1742,8 @@ page_detached_cb (AdwTabBox  *self,
                                               appear_animation_value_cb,
                                               info, NULL);
   info->appear_animation =
-    adw_animation_new (GTK_WIDGET (self), info->appear_progress, 0,
-                       CLOSE_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), info->appear_progress, 0,
+                             CLOSE_ANIMATION_DURATION, target);
 
   g_signal_connect_swapped (info->appear_animation, "done",
                             G_CALLBACK (close_animation_done_cb), info);
@@ -1936,8 +1937,8 @@ insert_placeholder (AdwTabBox  *self,
                                               insert_animation_value_cb,
                                               info, NULL);
   info->appear_animation =
-    adw_animation_new (GTK_WIDGET (self), initial_progress, 1,
-                       OPEN_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), initial_progress, 1,
+                             OPEN_ANIMATION_DURATION, target);
 
   g_signal_connect_swapped (info->appear_animation, "done",
                             G_CALLBACK (open_animation_done_cb), info);
@@ -1987,8 +1988,8 @@ replace_placeholder (AdwTabBox  *self,
                                               appear_animation_value_cb,
                                               info, NULL);
   info->appear_animation =
-    adw_animation_new (GTK_WIDGET (self), initial_progress, 1,
-                       OPEN_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), initial_progress, 1,
+                             OPEN_ANIMATION_DURATION, target);
 
   g_signal_connect_swapped (info->appear_animation, "done",
                             G_CALLBACK (replace_animation_done_cb), info);
@@ -2062,8 +2063,8 @@ remove_placeholder (AdwTabBox *self)
                                               appear_animation_value_cb,
                                               info, NULL);
   info->appear_animation =
-    adw_animation_new (GTK_WIDGET (self), info->appear_progress, 0,
-                       CLOSE_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), info->appear_progress, 0,
+                             CLOSE_ANIMATION_DURATION, target);
 
   g_signal_connect_swapped (info->appear_animation, "done",
                             G_CALLBACK (remove_animation_done_cb), info);
@@ -2264,8 +2265,8 @@ create_drag_icon (AdwTabBox *self,
                                               icon_resize_animation_value_cb,
                                               icon, NULL);
   icon->resize_animation =
-    adw_animation_new (GTK_WIDGET (icon->tab), 0, 0,
-                       ICON_RESIZE_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (icon->tab), 0, 0,
+                             ICON_RESIZE_ANIMATION_DURATION, target);
 
   self->drag_icon = icon;
 }
@@ -2281,8 +2282,10 @@ resize_drag_icon (AdwTabBox *self,
 
   icon->target_width = width;
 
-  adw_animation_set_value_from (icon->resize_animation, icon->width);
-  adw_animation_set_value_to (icon->resize_animation, width);
+  adw_timed_animation_set_value_from (ADW_TIMED_ANIMATION (icon->resize_animation),
+                                      icon->width);
+  adw_timed_animation_set_value_to (ADW_TIMED_ANIMATION (icon->resize_animation),
+                                    width);
   adw_animation_play (icon->resize_animation);
 }
 
@@ -3434,8 +3437,8 @@ adw_tab_box_init (AdwTabBox *self)
                                               resize_animation_value_cb,
                                               self, NULL);
   self->resize_animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 1,
-                       RESIZE_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 1,
+                             RESIZE_ANIMATION_DURATION, target);
 
   /* The actual update will be done in size_allocate(). After the animation
    * finishes, don't remove it right away, it will be done in size-allocate as
@@ -3445,8 +3448,8 @@ adw_tab_box_init (AdwTabBox *self)
                                               gtk_widget_queue_resize,
                                               self, NULL);
   self->scroll_animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 1,
-                       SCROLL_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 1,
+                             SCROLL_ANIMATION_DURATION, target);
 
   g_signal_connect_swapped (self->scroll_animation, "done",
                             G_CALLBACK (scroll_animation_done_cb), self);
diff --git a/src/adw-tab.c b/src/adw-tab.c
index 4ab8fd77..f4686351 100644
--- a/src/adw-tab.c
+++ b/src/adw-tab.c
@@ -10,10 +10,10 @@
 #include "adw-tab-private.h"
 
 #include "adw-animation-util-private.h"
-#include "adw-animation-private.h"
 #include "adw-bidi-private.h"
 #include "adw-fading-label-private.h"
 #include "adw-macros-private.h"
+#include "adw-timed-animation-private.h"
 
 #define FADE_WIDTH 18
 #define CLOSE_BTN_ANIMATION_DURATION 150
@@ -115,10 +115,10 @@ update_state (AdwTab *self)
   if (self->show_close != show_close) {
     self->show_close = show_close;
 
-    adw_animation_set_value_from (self->close_btn_animation,
-                                  gtk_widget_get_opacity (self->close_btn));
-    adw_animation_set_value_to (self->close_btn_animation,
-                                self->show_close ? 1 : 0);
+    adw_timed_animation_set_value_from (ADW_TIMED_ANIMATION (self->close_btn_animation),
+                                        gtk_widget_get_opacity (self->close_btn));
+    adw_timed_animation_set_value_to (ADW_TIMED_ANIMATION (self->close_btn_animation),
+                                      self->show_close ? 1 : 0);
     adw_animation_play (self->close_btn_animation);
   }
 }
@@ -842,11 +842,11 @@ adw_tab_init (AdwTab *self)
                                               close_btn_animation_value_cb,
                                               self, NULL);
   self->close_btn_animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 0,
-                       CLOSE_BTN_ANIMATION_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 0,
+                             CLOSE_BTN_ANIMATION_DURATION, target);
 
-  adw_animation_set_interpolator (self->close_btn_animation,
-                                  ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT);
+  adw_timed_animation_set_interpolator (ADW_TIMED_ANIMATION (self->close_btn_animation),
+                                        ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT);
 }
 
 AdwTab *
diff --git a/src/adw-timed-animation-private.h b/src/adw-timed-animation-private.h
new file mode 100644
index 00000000..80320bb4
--- /dev/null
+++ b/src/adw-timed-animation-private.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 Manuel Genovés <manuel genoves gmail com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#if !defined(_ADWAITA_INSIDE) && !defined(ADWAITA_COMPILATION)
+#error "Only <adwaita.h> can be included directly."
+#endif
+
+#include "adw-version.h"
+
+#include <gtk/gtk.h>
+
+#include "adw-animation-private.h"
+#include "adw-enums.h"
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_TIMED_ANIMATION (adw_timed_animation_get_type())
+
+GDK_DECLARE_INTERNAL_TYPE (AdwTimedAnimation, adw_timed_animation, ADW, TIMED_ANIMATION, AdwAnimation)
+
+typedef enum {
+  ADW_ANIMATION_INTERPOLATOR_EASE_IN,
+  ADW_ANIMATION_INTERPOLATOR_EASE_OUT,
+  ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT,
+} AdwAnimationInterpolator;
+
+AdwAnimation *adw_timed_animation_new (GtkWidget          *widget,
+                                       double              from,
+                                       double              to,
+                                       guint               duration,
+                                       AdwAnimationTarget *target) G_GNUC_WARN_UNUSED_RESULT;
+
+double adw_timed_animation_get_value_from (AdwTimedAnimation *self);
+void   adw_timed_animation_set_value_from (AdwTimedAnimation *self,
+                                           double             value);
+
+double adw_timed_animation_get_value_to (AdwTimedAnimation *self);
+void   adw_timed_animation_set_value_to (AdwTimedAnimation *self,
+                                         double             value);
+
+guint adw_timed_animation_get_duration (AdwTimedAnimation *self);
+void  adw_timed_animation_set_duration (AdwTimedAnimation *self,
+                                        guint              duration);
+
+AdwAnimationInterpolator adw_timed_animation_get_interpolator (AdwTimedAnimation        *self);
+void                     adw_timed_animation_set_interpolator (AdwTimedAnimation        *self,
+                                                               AdwAnimationInterpolator  interpolator);
+
+G_END_DECLS
diff --git a/src/adw-timed-animation.c b/src/adw-timed-animation.c
new file mode 100644
index 00000000..06ccfa34
--- /dev/null
+++ b/src/adw-timed-animation.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2021 Manuel Genovés <manuel genoves gmail com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "adw-timed-animation-private.h"
+
+#include "adw-animation-private.h"
+#include "adw-animation-util-private.h"
+
+struct _AdwTimedAnimation
+{
+  AdwAnimation parent_instance;
+
+  double value_from;
+  double value_to;
+  guint duration; /* ms */
+
+  AdwAnimationInterpolator interpolator;
+};
+
+struct _AdwTimedAnimationClass
+{
+  AdwAnimationClass parent_class;
+};
+
+G_DEFINE_TYPE (AdwTimedAnimation, adw_timed_animation, ADW_TYPE_ANIMATION)
+
+enum {
+  PROP_0,
+  PROP_VALUE_FROM,
+  PROP_VALUE_TO,
+  PROP_DURATION,
+  PROP_INTERPOLATOR,
+  LAST_PROP,
+};
+
+static GParamSpec *props[LAST_PROP];
+
+static guint
+adw_timed_animation_estimate_duration (AdwAnimation *animation)
+{
+  AdwTimedAnimation *self = ADW_TIMED_ANIMATION (animation);
+
+  return self->duration;
+}
+
+static double
+adw_timed_animation_calculate_value (AdwAnimation *animation,
+                                     guint         t)
+{
+  AdwTimedAnimation *self = ADW_TIMED_ANIMATION (animation);
+  double value;
+
+  if (self->duration == 0)
+    return self->value_to;
+
+  switch (self->interpolator) {
+    case ADW_ANIMATION_INTERPOLATOR_EASE_IN:
+      value = adw_ease_in_cubic ((double) t / self->duration);
+      break;
+    case ADW_ANIMATION_INTERPOLATOR_EASE_OUT:
+      value = adw_ease_out_cubic ((double) t / self->duration);
+      break;
+    case ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT:
+      value = adw_ease_in_out_cubic ((double) t / self->duration);
+      break;
+    default:
+      g_assert_not_reached ();
+  }
+
+  return adw_lerp (self->value_from, self->value_to, value);
+}
+
+static void
+adw_timed_animation_get_property (GObject    *object,
+                                  guint       prop_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+  AdwTimedAnimation *self = ADW_TIMED_ANIMATION (object);
+
+  switch (prop_id) {
+  case PROP_VALUE_FROM:
+    g_value_set_double (value, adw_timed_animation_get_value_from (self));
+    break;
+
+  case PROP_VALUE_TO:
+    g_value_set_double (value, adw_timed_animation_get_value_to (self));
+    break;
+
+  case PROP_DURATION:
+    g_value_set_uint (value, adw_timed_animation_get_duration (self));
+    break;
+
+  case PROP_INTERPOLATOR:
+    g_value_set_enum (value, adw_timed_animation_get_interpolator (self));
+    break;
+
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
+static void
+adw_timed_animation_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  AdwTimedAnimation *self = ADW_TIMED_ANIMATION (object);
+
+  switch (prop_id) {
+  case PROP_VALUE_FROM:
+    adw_timed_animation_set_value_from (self, g_value_get_double (value));
+    break;
+
+  case PROP_VALUE_TO:
+    adw_timed_animation_set_value_to (self, g_value_get_double (value));
+    break;
+
+  case PROP_DURATION:
+    adw_timed_animation_set_duration (self, g_value_get_uint (value));
+    break;
+
+  case PROP_INTERPOLATOR:
+    adw_timed_animation_set_interpolator (self, g_value_get_enum (value));
+    break;
+
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
+static void
+adw_timed_animation_class_init (AdwTimedAnimationClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  AdwAnimationClass *animation_class = ADW_ANIMATION_CLASS (klass);
+
+  object_class->set_property = adw_timed_animation_set_property;
+  object_class->get_property = adw_timed_animation_get_property;
+
+  animation_class->estimate_duration = adw_timed_animation_estimate_duration;
+  animation_class->calculate_value = adw_timed_animation_calculate_value;
+
+  props[PROP_VALUE_FROM] =
+    g_param_spec_double ("value-from",
+                         "Initial value",
+                         "Initial value of the animation",
+                         -G_MAXDOUBLE,
+                         G_MAXDOUBLE,
+                         0,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  props[PROP_VALUE_TO] =
+    g_param_spec_double ("value-to",
+                         "Final value",
+                         "Final value of the animation",
+                         -G_MAXDOUBLE,
+                         G_MAXDOUBLE,
+                         0,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  props[PROP_DURATION] =
+    g_param_spec_uint ("duration",
+                       "Duration",
+                       "Duration of the animation in ms",
+                       0,
+                       ADW_DURATION_INFINITE,
+                       0,
+                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  props[PROP_INTERPOLATOR] =
+    g_param_spec_enum ("interpolator",
+                       "Interpolator",
+                       "Easing function used in the animation",
+                       ADW_TYPE_ANIMATION_INTERPOLATOR,
+                       ADW_ANIMATION_INTERPOLATOR_EASE_OUT,
+                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  g_object_class_install_properties (object_class, LAST_PROP, props);
+}
+
+static void
+adw_timed_animation_init (AdwTimedAnimation *self)
+{
+}
+
+AdwAnimation *
+adw_timed_animation_new (GtkWidget          *widget,
+                         double              from,
+                         double              to,
+                         guint               duration,
+                         AdwAnimationTarget *target)
+{
+  AdwAnimation *animation;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+  g_return_val_if_fail (ADW_IS_ANIMATION_TARGET (target), NULL);
+
+  animation = g_object_new (ADW_TYPE_TIMED_ANIMATION,
+                            "widget", widget,
+                            "value-from", from,
+                            "value-to", to,
+                            "duration", duration,
+                            "target", target,
+                            NULL);
+
+  g_object_unref (target);
+
+  return animation;
+}
+
+double
+adw_timed_animation_get_value_from (AdwTimedAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_TIMED_ANIMATION (self), 0.0);
+
+  return self->value_from;
+}
+
+void
+adw_timed_animation_set_value_from (AdwTimedAnimation *self,
+                                    double             value)
+{
+  g_return_if_fail (ADW_IS_TIMED_ANIMATION (self));
+
+  if (self->value_from == value)
+    return;
+
+  self->value_from = value;
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VALUE_FROM]);
+}
+
+double
+adw_timed_animation_get_value_to (AdwTimedAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_TIMED_ANIMATION (self), 0.0);
+
+  return self->value_to;
+}
+
+void
+adw_timed_animation_set_value_to (AdwTimedAnimation *self,
+                                  double             value)
+{
+  g_return_if_fail (ADW_IS_TIMED_ANIMATION (self));
+
+  if (self->value_to == value)
+    return;
+
+  self->value_to = value;
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VALUE_TO]);
+}
+
+guint
+adw_timed_animation_get_duration (AdwTimedAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_TIMED_ANIMATION (self), 0);
+
+  return self->duration;
+}
+
+void
+adw_timed_animation_set_duration (AdwTimedAnimation *self,
+                                  guint              duration)
+{
+  g_return_if_fail (ADW_IS_TIMED_ANIMATION (self));
+
+  if (self->duration == duration)
+    return;
+
+  self->duration = duration;
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DURATION]);
+}
+
+AdwAnimationInterpolator
+adw_timed_animation_get_interpolator (AdwTimedAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_TIMED_ANIMATION (self),
+                        ADW_ANIMATION_INTERPOLATOR_EASE_IN);
+
+  return self->interpolator;
+}
+
+void
+adw_timed_animation_set_interpolator (AdwTimedAnimation        *self,
+                                      AdwAnimationInterpolator  interpolator)
+{
+  g_return_if_fail (ADW_IS_TIMED_ANIMATION (self));
+  g_return_if_fail (interpolator <= ADW_ANIMATION_INTERPOLATOR_EASE_IN_OUT);
+
+  if (self->interpolator == interpolator)
+    return;
+
+  self->interpolator = interpolator;
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INTERPOLATOR]);
+}
diff --git a/src/adw-toast-overlay.c b/src/adw-toast-overlay.c
index 0a9f9918..8c3b2d14 100644
--- a/src/adw-toast-overlay.c
+++ b/src/adw-toast-overlay.c
@@ -8,9 +8,9 @@
 
 #include "adw-toast-overlay.h"
 
-#include "adw-animation-private.h"
 #include "adw-animation-util-private.h"
 #include "adw-macros-private.h"
+#include "adw-timed-animation-private.h"
 #include "adw-toast-private.h"
 #include "adw-toast-widget-private.h"
 #include "adw-widget-utils-private.h"
@@ -174,7 +174,7 @@ hide_current_toast (AdwToastOverlay *self)
                                               hide_value_cb,
                                               info, NULL);
   info->hide_animation =
-    adw_animation_new (GTK_WIDGET (self), 1, 0, HIDE_DURATION, target);
+    adw_timed_animation_new (GTK_WIDGET (self), 1, 0, HIDE_DURATION, target);
 
   g_signal_connect_swapped (info->hide_animation, "done",
                             G_CALLBACK (hide_done_cb), info);
@@ -230,9 +230,9 @@ show_toast (AdwToastOverlay *self,
                                               gtk_widget_queue_allocate,
                                               self, NULL);
   info->show_animation =
-    adw_animation_new (GTK_WIDGET (self), 0, 1,
-                       self->hiding_toasts ? REPLACE_DURATION : SHOW_DURATION,
-                       target);
+    adw_timed_animation_new (GTK_WIDGET (self), 0, 1,
+                             self->hiding_toasts ? REPLACE_DURATION : SHOW_DURATION,
+                             target);
 
   g_signal_connect_swapped (info->show_animation, "done",
                             G_CALLBACK (show_done_cb), info);
diff --git a/src/meson.build b/src/meson.build
index d7329b6d..2ae88545 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -24,6 +24,7 @@ adw_public_enum_headers = [
 adw_private_enum_headers = [
   'adw-animation-private.h',
   'adw-settings-private.h',
+  'adw-timed-animation-private.h',
 ]
 
 version_data = configuration_data()
@@ -180,6 +181,7 @@ src_sources = [
   'adw-tab-bar.c',
   'adw-tab-box.c',
   'adw-tab-view.c',
+  'adw-timed-animation.c',
   'adw-toast.c',
   'adw-toast-overlay.c',
   'adw-toast-widget.c',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]