[libadwaita/wip/exalm/swipeable-animations: 2/7] squeezer: Port to AdwAnimation




commit f457b17fd4c4ca4ec6997f6732406886a54aabd9
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Sun Dec 5 02:01:51 2021 +0500

    squeezer: Port to AdwAnimation

 src/adw-squeezer.c | 148 ++++++++++++++++++++---------------------------------
 1 file changed, 56 insertions(+), 92 deletions(-)
---
diff --git a/src/adw-squeezer.c b/src/adw-squeezer.c
index d16d975d..8c989cb2 100644
--- a/src/adw-squeezer.c
+++ b/src/adw-squeezer.c
@@ -18,10 +18,10 @@
 
 #include "adw-squeezer.h"
 
-#include "gtkprogresstrackerprivate.h"
 #include "adw-animation-util.h"
-#include "adw-animation-private.h"
+#include "adw-easing.h"
 #include "adw-macros-private.h"
+#include "adw-timed-animation.h"
 #include "adw-widget-utils-private.h"
 
 /**
@@ -96,15 +96,12 @@ struct _AdwSqueezer
   guint transition_duration;
 
   AdwSqueezerPage *last_visible_child;
-  guint tick_id;
-  GtkProgressTracker tracker;
-  gboolean first_frame_skipped;
+  gboolean transition_running;
+  AdwAnimation *animation;
 
   int last_visible_widget_width;
   int last_visible_widget_height;
 
-  AdwSqueezerTransitionType active_transition_type;
-
   gboolean interpolate_size;
 
   float xalign;
@@ -381,96 +378,37 @@ find_page_for_widget (AdwSqueezer *self,
 }
 
 static void
-adw_squeezer_progress_updated (AdwSqueezer *self)
+transition_cb (AdwSqueezer *self,
+               double       value)
 {
   if (!self->homogeneous)
     gtk_widget_queue_resize (GTK_WIDGET (self));
   else
     gtk_widget_queue_draw (GTK_WIDGET (self));
-
-  if (gtk_progress_tracker_get_state (&self->tracker) == GTK_PROGRESS_STATE_AFTER &&
-      self->last_visible_child != NULL) {
-    gtk_widget_set_child_visible (self->last_visible_child->widget, FALSE);
-    self->last_visible_child = NULL;
-  }
-}
-
-static gboolean
-adw_squeezer_transition_cb (GtkWidget     *widget,
-                            GdkFrameClock *frame_clock,
-                            gpointer       user_data)
-{
-  AdwSqueezer *self = ADW_SQUEEZER (widget);
-
-  if (self->first_frame_skipped) {
-    gtk_progress_tracker_advance_frame (&self->tracker,
-                                        gdk_frame_clock_get_frame_time (frame_clock));
-  } else {
-    self->first_frame_skipped = TRUE;
-  }
-
-  /* Finish the animation early if the widget isn't mapped anymore. */
-  if (!gtk_widget_get_mapped (widget))
-    gtk_progress_tracker_finish (&self->tracker);
-
-  adw_squeezer_progress_updated (ADW_SQUEEZER (widget));
-
-  if (gtk_progress_tracker_get_state (&self->tracker) == GTK_PROGRESS_STATE_AFTER) {
-    self->tick_id = 0;
-    g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRANSITION_RUNNING]);
-
-    return FALSE;
-  }
-
-  return TRUE;
 }
 
 static void
-adw_squeezer_schedule_ticks (AdwSqueezer *self)
+set_transition_running (AdwSqueezer *self,
+                        gboolean     running)
 {
-  if (self->tick_id == 0) {
-    self->tick_id =
-      gtk_widget_add_tick_callback (GTK_WIDGET (self), adw_squeezer_transition_cb, self, NULL);
-    g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRANSITION_RUNNING]);
-  }
-}
+  if (self->transition_running == running)
+    return;
 
-static void
-adw_squeezer_unschedule_ticks (AdwSqueezer *self)
-{
-  if (self->tick_id != 0) {
-    gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick_id);
-    self->tick_id = 0;
-    g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRANSITION_RUNNING]);
-  }
+  self->transition_running = running;
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRANSITION_RUNNING]);
 }
 
 static void
-adw_squeezer_start_transition (AdwSqueezer               *self,
-                               AdwSqueezerTransitionType  transition_type,
-                               guint                      transition_duration)
+transition_done_cb (AdwSqueezer *self)
 {
-  GtkWidget *widget = GTK_WIDGET (self);
-
-  if (gtk_widget_get_mapped (widget) &&
-      adw_get_enable_animations (widget) &&
-      transition_type != ADW_SQUEEZER_TRANSITION_TYPE_NONE &&
-      transition_duration != 0 &&
-      (self->last_visible_child != NULL || self->allow_none)) {
-    self->active_transition_type = transition_type;
-    self->first_frame_skipped = FALSE;
-    adw_squeezer_schedule_ticks (self);
-    gtk_progress_tracker_start (&self->tracker,
-                                self->transition_duration * 1000,
-                                0,
-                                1.0);
-  } else {
-    adw_squeezer_unschedule_ticks (self);
-    self->active_transition_type = ADW_SQUEEZER_TRANSITION_TYPE_NONE;
-    gtk_progress_tracker_finish (&self->tracker);
+  if (self->last_visible_child) {
+    gtk_widget_set_child_visible (self->last_visible_child->widget, FALSE);
+    self->last_visible_child = NULL;
   }
 
-  adw_squeezer_progress_updated (ADW_SQUEEZER (widget));
+  adw_animation_reset (self->animation);
+
+  set_transition_running (self, FALSE);
 }
 
 static void
@@ -541,9 +479,8 @@ set_visible_child (AdwSqueezer               *self,
                                (gpointer *)&self->visible_child->last_focus);
   }
 
-  if (self->last_visible_child != NULL)
-    gtk_widget_set_child_visible (self->last_visible_child->widget, FALSE);
-  self->last_visible_child = NULL;
+  if (self->transition_running)
+    adw_animation_skip (self->animation);
 
   if (self->visible_child && self->visible_child->widget) {
     if (gtk_widget_is_visible (widget)) {
@@ -588,7 +525,15 @@ set_visible_child (AdwSqueezer               *self,
                                              MAX (old_pos, new_pos) - MIN (old_pos, new_pos) + 1);
   }
 
-  adw_squeezer_start_transition (self, transition_type, transition_duration);
+  if (self->transition_type == ADW_SQUEEZER_TRANSITION_TYPE_NONE ||
+      (self->last_visible_child == NULL && !self->allow_none))
+    adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->animation), 0);
+  else
+    adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->animation),
+                                      self->transition_duration);
+
+  set_transition_running (self, TRUE);
+  adw_animation_play (self->animation);
 }
 
 static void
@@ -789,7 +734,7 @@ adw_squeezer_snapshot_crossfade (GtkWidget   *widget,
                                  GtkSnapshot *snapshot)
 {
   AdwSqueezer *self = ADW_SQUEEZER (widget);
-  double progress = gtk_progress_tracker_get_progress (&self->tracker, FALSE);
+  double progress = adw_animation_get_value (self->animation);
 
   gtk_snapshot_push_cross_fade (snapshot, progress);
 
@@ -815,7 +760,8 @@ adw_squeezer_snapshot (GtkWidget   *widget,
   AdwSqueezer *self = ADW_SQUEEZER (widget);
 
   if (self->visible_child || self->allow_none) {
-    if (gtk_progress_tracker_get_state (&self->tracker) != GTK_PROGRESS_STATE_AFTER) {
+    if (self->transition_running &&
+        self->transition_type != ADW_SQUEEZER_TRANSITION_TYPE_NONE) {
       gtk_snapshot_push_clip (snapshot,
                               &GRAPHENE_RECT_INIT(
                                   0, 0,
@@ -823,7 +769,7 @@ adw_squeezer_snapshot (GtkWidget   *widget,
                                   gtk_widget_get_height (widget)
                               ));
 
-      switch (self->active_transition_type)
+      switch (self->transition_type)
         {
         case ADW_SQUEEZER_TRANSITION_TYPE_CROSSFADE:
           adw_squeezer_snapshot_crossfade (widget, snapshot);
@@ -1024,7 +970,8 @@ adw_squeezer_measure (GtkWidget      *widget,
   if (self->orientation != orientation && !self->homogeneous &&
       self->interpolate_size &&
       (self->last_visible_child != NULL || self->allow_none)) {
-    double t = gtk_progress_tracker_get_ease_out_cubic (&self->tracker, FALSE);
+    double t = adw_animation_get_value (self->animation);
+    t = adw_easing_ease (ADW_EASE_OUT_CUBIC, t);
 
     if (orientation == GTK_ORIENTATION_VERTICAL) {
       min = adw_lerp (self->last_visible_widget_height, min, t);
@@ -1058,6 +1005,8 @@ adw_squeezer_dispose (GObject *object)
   while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
     squeezer_remove (self, child, TRUE);
 
+  g_clear_object (&self->animation);
+
   G_OBJECT_CLASS (adw_squeezer_parent_class)->dispose (object);
 }
 
@@ -1070,8 +1019,6 @@ adw_squeezer_finalize (GObject *object)
     g_object_remove_weak_pointer (G_OBJECT (self->pages),
                                   (gpointer *) &self->pages);
 
-  adw_squeezer_unschedule_ticks (self);
-
   G_OBJECT_CLASS (adw_squeezer_parent_class)->finalize (object);
 }
 
@@ -1203,6 +1150,10 @@ adw_squeezer_class_init (AdwSqueezerClass *klass)
    *
    * Whether a transition is currently running.
    *
+   * If a transition is impossible, the property value will be set to `TRUE` and
+   * then immediately to `FALSE`, so it's possible to rely on its notifications
+   * to know that a transition has happened.
+   *
    * Since: 1.0
    */
   props[PROP_TRANSITION_RUNNING] =
@@ -1298,11 +1249,23 @@ adw_squeezer_class_init (AdwSqueezerClass *klass)
 static void
 adw_squeezer_init (AdwSqueezer *self)
 {
+  AdwAnimationTarget *target;
+
   self->homogeneous = TRUE;
   self->transition_duration = 200;
   self->transition_type = ADW_SQUEEZER_TRANSITION_TYPE_NONE;
   self->xalign = 0.5;
   self->yalign = 0.5;
+
+  target = adw_callback_animation_target_new ((AdwAnimationTargetFunc) transition_cb,
+                                              self, NULL);
+  self->animation = adw_timed_animation_new (GTK_WIDGET (self), 0, 1,
+                                             self->transition_duration,
+                                             target);
+  adw_timed_animation_set_easing (ADW_TIMED_ANIMATION (self->animation),
+                                  ADW_LINEAR);
+  g_signal_connect_swapped (self->animation, "done",
+                            G_CALLBACK (transition_done_cb), self);
 }
 
 static void
@@ -1665,6 +1628,7 @@ adw_squeezer_set_transition_duration (AdwSqueezer *self,
     return;
 
   self->transition_duration = duration;
+
   g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRANSITION_DURATION]);
 }
 
@@ -1723,7 +1687,7 @@ adw_squeezer_get_transition_running (AdwSqueezer *self)
 {
   g_return_val_if_fail (ADW_IS_SQUEEZER (self), FALSE);
 
-  return (self->tick_id != 0);
+  return self->transition_running;
 }
 
 /**


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