ferroui_base/animation/
clock.rs1use crate::animation::{ClockBase, IClock, IGlobalClock, PlayState, TimeSpan};
2use crate::reactive::{IDisposable, IObservable, IObserver, ObservableError};
3use crate::{FerroLocator, LocatorExtensions};
4use std::cell::RefCell;
5use std::rc::Rc;
6
7pub struct Clock {
15 base: ClockBase,
16 parent_subscription: RefCell<Option<Rc<dyn IDisposable>>>,
17}
18
19struct ParentObserver(Rc<Clock>);
20
21impl IObserver<TimeSpan> for ParentObserver {
22 fn on_next(&self, value: TimeSpan) {
23 let clock = &self.0;
24 clock.base.pulse(value, || clock.stop());
25 }
26
27 fn on_error(&self, _error: ObservableError) {}
28
29 fn on_completed(&self) {}
30}
31
32impl Clock {
33 pub fn global_clock() -> Rc<dyn IClock> {
37 FerroLocator::current().get_required_service::<dyn IGlobalClock>()
38 }
39
40 pub fn new() -> Rc<Clock> {
42 Self::with_parent(&Self::global_clock())
43 }
44
45 pub fn with_parent(parent: &Rc<dyn IClock>) -> Rc<Clock> {
47 let clock = Rc::new(Clock { base: ClockBase::new(), parent_subscription: RefCell::new(None) });
48 let subscription = parent.subscribe(Rc::new(ParentObserver(clock.clone())));
49 *clock.parent_subscription.borrow_mut() = Some(subscription);
50 clock
51 }
52
53 fn stop(&self) {
54 let subscription = self.parent_subscription.borrow_mut().take();
55 if let Some(subscription) = subscription {
56 subscription.dispose();
57 }
58 }
59}
60
61impl IObservable<TimeSpan> for Clock {
62 fn subscribe(&self, observer: Rc<dyn IObserver<TimeSpan>>) -> Rc<dyn IDisposable> {
63 self.base.subscribe(observer)
64 }
65}
66
67impl IClock for Clock {
68 fn play_state(&self) -> PlayState {
69 self.base.play_state()
70 }
71
72 fn set_play_state(&self, value: PlayState) {
73 self.base.set_play_state(value)
74 }
75}