ferroui_base/animation/transitions/
effect_transition.rs1use crate::animation::animators::{BlurEffectAnimator, DropShadowEffectAnimator};
2use crate::animation::{AnimatorTransitionObservable, Transition, TransitionBase, TransitionObservableBase};
3use crate::ferro_transition_class;
4use crate::media::effects::{IEffect, ImmutableBlurEffect, ImmutableDropShadowDirectionEffect};
5use crate::media::Color;
6use crate::reactive::IObservable;
7use std::rc::Rc;
8
9ferro_transition_class!(
10 EffectTransition: Option<Rc<dyn IEffect>>
16);
17
18type EffectValue = Option<Rc<dyn IEffect>>;
19
20fn try_with_kind(
23 old_value: &EffectValue,
24 new_value: &EffectValue,
25 is_kind: impl Fn(&dyn IEffect) -> bool,
26 default_value: impl FnOnce() -> Rc<dyn IEffect>,
27) -> Option<(EffectValue, EffectValue)> {
28 let of_kind = |value: &EffectValue| value.as_ref().is_some_and(|effect| is_kind(&**effect));
29
30 if of_kind(old_value) {
31 if of_kind(new_value) {
32 Some((old_value.clone(), new_value.clone()))
33 } else if new_value.is_none() {
34 Some((old_value.clone(), Some(default_value())))
35 } else {
36 None
37 }
38 } else if of_kind(new_value) {
39 Some((Some(default_value()), new_value.clone()))
40 } else {
41 None
42 }
43}
44
45impl Transition<EffectValue> for EffectTransition {
46 fn do_transition(
47 this: &Self,
48 progress: Rc<dyn IObservable<f64>>,
49 old_value: EffectValue,
50 new_value: EffectValue,
51 ) -> Rc<dyn IObservable<EffectValue>> {
52 if old_value.is_some() || new_value.is_some() {
53 if let Some((old_i, new_i)) = try_with_kind(
54 &old_value,
55 &new_value,
56 |effect| effect.as_blur_effect().is_some(),
57 || Rc::new(ImmutableBlurEffect::new(0.0)),
58 ) {
59 return AnimatorTransitionObservable::create(
60 BlurEffectAnimator::interpolate_core,
61 progress,
62 this.easing(),
63 old_i,
64 new_i,
65 );
66 }
67
68 if let Some((old_i, new_i)) = try_with_kind(
69 &old_value,
70 &new_value,
71 |effect| effect.as_drop_shadow_effect().is_some(),
72 || Rc::new(ImmutableDropShadowDirectionEffect::new(0.0, 0.0, 0.0, Color::default(), 0.0)),
73 ) {
74 return AnimatorTransitionObservable::create(
75 DropShadowEffectAnimator::interpolate_core,
76 progress,
77 this.easing(),
78 old_i,
79 new_i,
80 );
81 }
82 }
83
84 TransitionObservableBase::new(progress, this.easing(), move |progress| {
85 if progress >= 0.5 {
86 new_value.clone()
87 } else {
88 old_value.clone()
89 }
90 })
91 }
92}