diff --git a/src/window/progress_icon.rs b/src/window/progress_icon.rs index 5b4a60ea..2ae57f9a 100644 --- a/src/window/progress_icon.rs +++ b/src/window/progress_icon.rs @@ -4,13 +4,20 @@ use std::{ }; use adw::prelude::*; -use gtk::{cairo, glib, graphene::Rect, subclass::prelude::*}; +use gtk::{ + cairo, + glib::{self, clone}, + graphene::Rect, + subclass::prelude::*, +}; const LINE_WIDTH: f64 = 4.0; -// TODO: make progress animation smooth +const ANIMATION_DURATION_MS: u32 = 300; mod imp { + use std::cell::OnceCell; + use super::*; #[derive(Default, glib::Properties)] @@ -18,6 +25,9 @@ mod imp { pub struct ProgressIcon { #[property(get, set = Self::set_progress, minimum = 0.0, maximum = 1.0, explicit_notify)] pub(super) progress: Cell, + + pub(super) animation: OnceCell, + pub(super) display_progress: Cell, } #[glib::object_subclass] @@ -28,7 +38,26 @@ mod imp { } #[glib::derived_properties] - impl ObjectImpl for ProgressIcon {} + impl ObjectImpl for ProgressIcon { + fn constructed(&self) { + self.parent_constructed(); + + let obj = self.obj(); + + let animation_target = + adw::CallbackAnimationTarget::new(clone!(@weak obj => move |value| { + let imp = obj.imp(); + imp.display_progress.set(value); + obj.queue_draw(); + })); + let animation = adw::TimedAnimation::builder() + .widget(&*obj) + .duration(ANIMATION_DURATION_MS) + .target(&animation_target) + .build(); + self.animation.set(animation).unwrap(); + } + } impl WidgetImpl for ProgressIcon { fn snapshot(&self, snapshot: >k::Snapshot) { @@ -41,7 +70,7 @@ mod imp { let cx = width as f64 / 2.0; let cy = height as f64 / 2.0; let radius = width as f64 / 2.0 - LINE_WIDTH / 2.0; - let arc_end = self.progress.get() * TAU - FRAC_PI_2; + let arc_end = self.display_progress.get() * TAU - FRAC_PI_2; let ctx = snapshot.append_cairo(&Rect::new(0.0, 0.0, width as f32, height as f32)); ctx.set_line_width(LINE_WIDTH); @@ -66,8 +95,14 @@ mod imp { } let obj = self.obj(); + self.progress.set(progress); - obj.queue_draw(); + + let animation = self.animation.get().unwrap(); + animation.set_value_from(animation.value()); + animation.set_value_to(progress); + animation.play(); + obj.notify_progress(); } }