zng_var/
var.rs

1use core::fmt;
2use std::{any::TypeId, marker::PhantomData, ops, sync::Arc, time::Duration};
3
4use crate::{
5    AnyVar, AnyVarHookArgs, BoxAnyVarValue, VarHandle, VarHandles, VarImpl, VarIsReadOnlyError, VarModify, VarValue, WeakAnyVar,
6    animation::{
7        Animation, AnimationHandle, ChaseAnimation, Transition, TransitionKeyed, Transitionable,
8        easing::{EasingStep, EasingTime},
9    },
10    contextual_var,
11};
12
13use zng_clone_move::clmv;
14use zng_txt::{ToTxt, Txt};
15use zng_unit::{Factor, FactorUnits as _};
16
17/// Variable of type `T`.
18pub struct Var<T: VarValue> {
19    pub(crate) any: AnyVar,
20    _t: PhantomData<fn() -> T>,
21}
22impl<T: VarValue> Clone for Var<T> {
23    fn clone(&self) -> Self {
24        Self {
25            any: self.any.clone(),
26            _t: PhantomData,
27        }
28    }
29}
30impl<T: VarValue> From<Var<T>> for AnyVar {
31    fn from(var: Var<T>) -> Self {
32        var.any
33    }
34}
35impl<T: VarValue> TryFrom<AnyVar> for Var<T> {
36    type Error = AnyVar;
37
38    fn try_from(var: AnyVar) -> Result<Self, Self::Error> {
39        var.downcast()
40    }
41}
42impl<T: VarValue> ops::Deref for Var<T> {
43    type Target = AnyVar;
44
45    fn deref(&self) -> &Self::Target {
46        self.as_any()
47    }
48}
49impl<T: VarValue> Var<T> {
50    pub(crate) fn new_any(any: AnyVar) -> Self {
51        Var { any, _t: PhantomData }
52    }
53}
54impl<T: VarValue> fmt::Debug for Var<T> {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        f.debug_tuple("Var").field(&self.any.0).finish()
57    }
58}
59
60/// Value.
61impl<T: VarValue> Var<T> {
62    /// Visit a reference to the current value.
63    pub fn with<O>(&self, visitor: impl FnOnce(&T) -> O) -> O {
64        let mut once = Some(visitor);
65        let mut output = None;
66        self.0.with(&mut |v| {
67            output = Some(once.take().unwrap()(v.downcast_ref().unwrap()));
68        });
69        output.unwrap()
70    }
71
72    /// Get a clone of the current value.
73    pub fn get(&self) -> T {
74        self.with(|v| v.clone())
75    }
76
77    /// Get a clone of the current value into `value`.
78    ///
79    /// This uses [`Clone::clone_from`] to reuse the `value` memory if supported.
80    pub fn get_into(&self, value: &mut T) {
81        self.with(|v| value.clone_from(v));
82    }
83
84    /// Visit a reference to the current value if it [`is_new`].
85    ///
86    /// [`is_new`]: AnyVar::is_new
87    pub fn with_new<O>(&self, visitor: impl FnOnce(&T) -> O) -> Option<O> {
88        if self.is_new() { Some(self.with(visitor)) } else { None }
89    }
90
91    /// Gets a clone of the current value if it [`is_new`].
92    ///
93    /// [`is_new`]: AnyVar::is_new
94    pub fn get_new(&self) -> Option<T> {
95        if self.is_new() { Some(self.get()) } else { None }
96    }
97
98    /// Gets a clone of the current value into `value` if it [`is_new`].
99    ///
100    /// This uses [`Clone::clone_from`] to reuse the `value` memory if supported.
101    ///
102    /// [`is_new`]: AnyVar::is_new
103    pub fn get_new_into(&self, value: &mut T) -> bool {
104        self.with_new(|v| value.clone_from(v)).is_some()
105    }
106
107    /// Schedule `new_value` to be assigned next update.
108    pub fn try_set(&self, new_value: impl Into<T>) -> Result<(), VarIsReadOnlyError> {
109        self.any.try_set(BoxAnyVarValue::new(new_value.into()))
110    }
111
112    /// Schedule `new_value` to be assigned next update.
113    ///
114    /// If the variable is read-only this is ignored and a DEBUG level log is recorded.
115    /// Use [`try_set`] to get an error for read-only vars.
116    ///
117    /// [`try_set`]: Self::try_set
118    pub fn set(&self, new_value: impl Into<T>) {
119        trace_debug_error!(self.try_set(new_value))
120    }
121
122    /// Schedule `modify` to be called on the value for the next update.
123    ///
124    /// If the [`VarModify`] value is deref mut the variable will notify an update.
125    pub fn try_modify(&self, modify: impl FnOnce(&mut VarModify<T>) + Send + 'static) -> Result<(), VarIsReadOnlyError> {
126        self.any.try_modify(move |value| {
127            modify(&mut value.downcast::<T>().unwrap());
128        })
129    }
130
131    /// Schedule `modify` to be called on the value for the next update.
132    ///
133    /// If the [`VarModify`] value is deref mut the variable will notify an update.
134    ///
135    /// If the variable is read-only this is ignored and a DEBUG level log is recorded.
136    /// Use [`try_modify`] to get an error for read-only vars.
137    ///
138    /// [`try_modify`]: Self::try_modify
139    pub fn modify(&self, modify: impl FnOnce(&mut VarModify<T>) + Send + 'static) {
140        trace_debug_error!(self.try_modify(modify))
141    }
142
143    /// Schedule a new `value` for the variable, it will be set in the end of the current app update to the updated
144    /// value of `other`, so if the other var has already scheduled an update, the updated value will be used.
145    ///  
146    /// This can be used just before creating a binding to start with synchronized values.
147    pub fn try_set_from(&self, other: &Var<T>) -> Result<(), VarIsReadOnlyError> {
148        self.any.try_set_from(other)
149    }
150
151    /// Schedule a new `value` for the variable, it will be set in the end of the current app update to the updated
152    /// value of `other`, so if the other var has already scheduled an update, the updated value will be used.
153    ///  
154    /// This can be used just before creating a binding to start with synchronized values.
155    ///
156    /// If the variable is read-only this is ignored and a DEBUG level log is recorded.
157    /// Use [`try_set_from`] to get an error for read-only vars.
158    ///
159    /// [`try_set_from`]: Self::try_set_from
160    pub fn set_from(&self, other: &Var<T>) {
161        trace_debug_error!(self.try_set_from(other))
162    }
163
164    /// Like [`try_set_from`], but uses `map` to produce the new value from the updated value of `other`.
165    ///
166    /// [`try_set_from`]: Self::try_set_from
167    pub fn try_set_from_map<O: VarValue>(
168        &self,
169        other: &Var<O>,
170        map: impl FnOnce(&O) -> T + Send + 'static,
171    ) -> Result<(), VarIsReadOnlyError> {
172        self.any
173            .try_set_from_map(other, move |v| BoxAnyVarValue::new(map(v.downcast_ref::<O>().unwrap())))
174    }
175
176    /// Like [`set_from`], but uses `map` to produce the new value from the updated value of `other`.
177    ///
178    /// If the variable is read-only this is ignored and a DEBUG level log is recorded.
179    /// Use [`try_set_from_map`] to get an error for read-only vars.
180    ///
181    /// [`try_set_from_map`]: Self::try_set_from_map
182    /// [`set_from`]: Self::set_from
183    pub fn set_from_map<O: VarValue>(&self, other: &Var<O>, map: impl FnOnce(&O) -> T + Send + 'static) {
184        trace_debug_error!(self.try_set_from_map(other, map))
185    }
186
187    /// Setups a callback for just after the variable value update is applied, the closure runs in the root app context, just like
188    /// the `modify` closure. The closure must return `true` to be retained and `false` to be dropped.
189    ///
190    /// If you modify another variable in the closure modification applies in the same update, variable mapping and
191    /// binding is implemented using hooks.
192    ///
193    /// The variable store a weak reference to the callback if it has the `MODIFY` or `CAPS_CHANGE` capabilities, otherwise
194    /// the callback is discarded and [`VarHandle::dummy`] returned.
195    pub fn hook(&self, mut on_update: impl FnMut(&VarHookArgs<T>) -> bool + Send + 'static) -> VarHandle {
196        self.any
197            .hook(move |args: &AnyVarHookArgs| -> bool { on_update(&args.downcast().unwrap()) })
198    }
199
200    ///Awaits for a value that passes the `predicate`, including the current value.
201    #[allow(clippy::manual_async_fn)] // false positive, async fn futures are not Send + Sync
202    pub fn wait_match(&self, predicate: impl Fn(&T) -> bool + Send + Sync) -> impl Future<Output = ()> + Send + Sync {
203        self.any.wait_match(move |v| predicate(v.downcast_ref::<T>().unwrap()))
204    }
205
206    /// Awaits for an update them [`get`] the value.
207    ///
208    /// [`get`]: Self::get
209    #[allow(clippy::manual_async_fn)] // false positive, async fn futures are not Send + Sync
210    pub fn wait_next(&self) -> impl Future<Output = T> + Send + Sync {
211        async {
212            self.wait_update().await;
213            self.get()
214        }
215    }
216
217    /// Debug helper for tracing the lifetime of a value in this variable.
218    ///
219    /// The `enter_value` closure is called every time the variable updates, it can return
220    /// an implementation agnostic *scope* or *span* `S` that is only dropped when the variable updates again.
221    ///
222    /// The `enter_value` is also called immediately when this method is called to start tracking the first value.
223    ///
224    /// Returns a [`VarHandle`] that can be used to stop tracing.
225    ///
226    /// If this variable can never update the span is immediately dropped and a dummy handle is returned.
227    pub fn trace_value<S: Send + 'static>(&self, mut enter_value: impl FnMut(&VarHookArgs<T>) -> S + Send + 'static) -> VarHandle {
228        self.any.trace_value(move |args| enter_value(&args.downcast::<T>().unwrap()))
229    }
230}
231/// Value mapping.
232impl<T: VarValue> Var<T> {
233    /// Create a read-only mapping variable.
234    ///
235    /// The `map` closure must produce a mapped value from this variable's value.
236    ///
237    /// # Examples
238    ///
239    /// Basic usage:
240    ///
241    /// ```
242    /// # use zng_var::*;
243    /// # use zng_txt::*;
244    /// let n_var = var(0u32);
245    /// let n_10_var = n_var.map(|n| *n * 10);
246    /// let txt_var = n_10_var.map(|n| if *n < 100 { formatx!("{n}!") } else { formatx!("Done!") });
247    /// ```
248    ///
249    /// In the example above the `txt_var` will update every time the `n_var` updates.
250    ///
251    /// # Capabilities
252    ///
253    /// If this variable is static the `map` closure is called immediately and dropped, the mapping variable is also static.
254    ///
255    /// If this variable is a shared reference the `map` closure is called immediately to init the mapping variable and
256    /// is called again for every update of this variable. The mapping variable is another shared reference and it holds
257    /// a strong reference to this variable.
258    ///
259    /// If this variable is contextual the initial `map` call is deferred until first usage of the mapping variable. The
260    /// mapping variable is also contextual and will init for every context it is used in.
261    ///
262    /// The mapping variable is read-only, see [`map_bidi`] for read-write mapping.
263    ///
264    /// If the `map` closure produce an equal value the mapping variable will not update, see also [`filter_map`]
265    /// to skip updating for some input values.
266    ///
267    /// [`map_bidi`]: Self::map_bidi
268    /// [`filter_map`]: Self::filter_map
269    pub fn map<O: VarValue>(&self, mut map: impl FnMut(&T) -> O + Send + 'static) -> Var<O> {
270        self.any.map(move |v| map(v.downcast_ref::<T>().unwrap()))
271    }
272
273    /// Create a [`map`] that converts from `T` to `O` using [`Into<O>`].
274    ///
275    /// [`map`]: Var::map
276    pub fn map_into<O>(&self) -> Var<O>
277    where
278        O: VarValue,
279        T: Into<O>,
280    {
281        self.map(|v| v.clone().into())
282    }
283
284    /// Create a [`map`] that converts from `T` to [`Txt`] using [`ToTxt`].
285    ///
286    /// [`map`]: Var::map
287    /// [`Txt`]: Txt
288    /// [`ToTxt`]: ToTxt
289    pub fn map_to_txt(&self) -> Var<Txt>
290    where
291        T: ToTxt,
292    {
293        self.map(ToTxt::to_txt)
294    }
295
296    /// Create a [`map`] that references and clones `O` from `T` using `std::ops::Deref<Target = O>`.
297    ///
298    /// The mapping variable is read-only, see [`map_deref_mut`] for mutable referencing.
299    ///
300    /// [`map`]: Self::map
301    /// [`map_deref_mut`]: Self::map_deref_mut
302    pub fn map_deref<O>(&self) -> Var<O>
303    where
304        O: VarValue,
305        T: ops::Deref<Target = O>,
306    {
307        self.map(|v| ops::Deref::deref(v).clone())
308    }
309
310    /// Create a mapping variable that can skip updates.
311    ///
312    /// The `map` closure is called for every update this variable and if it returns a new value the mapping variable updates.
313    ///
314    /// If the `map` closure does not produce a value on init the `fallback_init` closure is called.
315    ///
316    /// # Examples
317    ///
318    /// Basic usage:
319    ///
320    /// ```
321    /// # use zng_var::*;
322    /// # use zng_txt::*;
323    /// let n_var = var(100u32);
324    /// let txt_var = n_var.filter_map(|n| if *n < 100 { Some(formatx!("{n}!")) } else { None }, || "starting...".into());
325    /// ```
326    ///
327    /// In the example above the `txt_var` will update every time the `n_var` updates with value `n < 100`. Because
328    /// the `n_var` initial value does not match the filter the fallback value `"starting..."` is used.
329    ///
330    /// # Capabilities
331    ///
332    /// If this variable is static the closures are called immediately and dropped, the mapping variable is also static.
333    ///
334    /// If this variable is a shared reference the closures are called immediately to init the mapping variable and
335    /// are called again for every update of this variable. The mapping variable is another shared reference and it holds
336    /// a strong reference to this variable.
337    ///
338    /// If this variable is contextual the initial closures call is deferred until first usage of the mapping variable. The
339    /// mapping variable is also contextual and will init for every context it is used in.
340    ///
341    /// The mapping variable is read-only, see [`filter_map_bidi`] for read-write mapping.
342    ///
343    /// [`filter_map_bidi`]: Self::filter_map_bidi
344    pub fn filter_map<O: VarValue>(
345        &self,
346        mut map: impl FnMut(&T) -> Option<O> + Send + 'static,
347        fallback_init: impl Fn() -> O + Send + 'static,
348    ) -> Var<O> {
349        self.any.filter_map(move |v| map(v.downcast_ref::<T>().unwrap()), fallback_init)
350    }
351
352    /// Create a [`filter_map`] that tries to convert from `T` to `O` using [`TryInto<O>`].
353    ///
354    /// [`filter_map`]: Var::filter_map
355    pub fn filter_try_into<O, I>(&self, fallback_init: I) -> Var<O>
356    where
357        O: VarValue,
358        T: TryInto<O>,
359        I: Fn() -> O + Send + Sync + 'static,
360    {
361        self.filter_map(|v| v.clone().try_into().ok(), fallback_init)
362    }
363
364    /// Create a [`filter_map`] that tries to convert from `T` to `O` using [`FromStr`].
365    ///
366    /// [`filter_map`]: Var::filter_map
367    /// [`FromStr`]: std::str::FromStr
368    pub fn filter_parse<O, I>(&self, fallback_init: I) -> Var<O>
369    where
370        O: VarValue + std::str::FromStr,
371        T: AsRef<str>,
372        I: Fn() -> O + Send + Sync + 'static,
373    {
374        self.filter_map(|v| v.as_ref().parse().ok(), fallback_init)
375    }
376
377    /// Create a bidirectional mapping variable.
378    ///
379    /// # Examples
380    ///
381    /// Basic usage:
382    ///
383    /// ```
384    /// # use zng_var::*;
385    /// # use zng_txt::*;
386    /// let n_var = var(0u32);
387    /// let n_100_var = n_var.map_bidi(|n| n * 100, |n_100| n_100 / 100);
388    /// ```
389    ///
390    /// In the example above the `n_100_var` will update every time the `n_var` updates and the `n_var` will
391    /// update every time the `n_100_var` updates.
392    ///
393    /// # Capabilities
394    ///
395    /// If this variable is static the `map` closure is called immediately and dropped, the mapping variable is also static,
396    /// the `map_back` closure is ignored.
397    ///
398    /// If this variable is a shared reference the `map` closure is called immediately to init the mapping variable.
399    /// The mapping variable is another shared reference and it holds a strong reference to this variable.
400    /// The `map` closure is called again for every update of this variable that is not caused by the mapping variable.
401    /// The `map_back` closure is called for every update of the mapping variable that was not caused by this variable.
402    ///
403    /// If this variable is contextual the initial `map` call is deferred until first usage of the mapping variable. The
404    /// mapping variable is also contextual and will init for every context it is used in.
405    pub fn map_bidi<O: VarValue>(
406        &self,
407        mut map: impl FnMut(&T) -> O + Send + 'static,
408        mut map_back: impl FnMut(&O) -> T + Send + 'static,
409    ) -> Var<O> {
410        let mapping = self.map_bidi_any(
411            move |input| BoxAnyVarValue::new(map(input.downcast_ref::<T>().unwrap())),
412            move |output| BoxAnyVarValue::new(map_back(output.downcast_ref::<O>().unwrap())),
413            TypeId::of::<O>(),
414        );
415        Var::new_any(mapping)
416    }
417
418    /// Create a bidirectional mapping variable that modifies back instead of mapping back.
419    ///
420    /// # Examples
421    ///
422    /// Basic usage:
423    ///
424    /// ```
425    /// # use zng_var::*;
426    /// # use zng_txt::*;
427    /// let list_var = var(vec!['a', 'b', 'c']);
428    /// let first_var = list_var.map_bidi_modify(
429    ///     // map:
430    ///     |l| l.first().copied().unwrap_or('_'),
431    ///     // modify_back:
432    ///     |c, l| if l.is_empty() { l.push(*c) } else { l[0] = *c },
433    /// );
434    /// ```
435    ///
436    /// In the example above the `first_var` represents the first item on the vector in `list_var`. Note that the `map` closure
437    /// works the same as in [`map_bidi`], but the `modify_back` closure modifies the list. This is not a mapping that can be declared
438    /// with [`map_bidi`] as the mapping variable does not have the full list to map back.
439    ///
440    /// # Capabilities
441    ///
442    /// If this variable is static the `map` closure is called immediately and dropped, the mapping variable is also static,
443    /// the `modify_back` closure is ignored.
444    ///
445    /// If this variable is a shared reference the `map` closure is called immediately to init the mapping variable.
446    /// The mapping variable is another shared reference and it holds a strong reference to this variable.
447    /// The `map` closure is called again for every update of this variable that is not caused by the mapping variable.
448    /// The `modify_back` closure is called for every update of the mapping variable that was not caused by this variable.
449    ///
450    /// If this variable is contextual the initial `map` call is deferred until first usage of the mapping variable. The
451    /// mapping variable is also contextual and will init for every context it is used in.
452    ///
453    /// Like other mappings and bindings cyclic updates are avoided automatically, if the `modify_back` closure touches/updates the value
454    /// a var instance tag is inserted after the closure returns, you do not need to mark it manually.
455    ///
456    /// [`map_bidi`]: Self::map_bidi
457    pub fn map_bidi_modify<O: VarValue>(
458        &self,
459        mut map: impl FnMut(&T) -> O + Send + 'static,
460        mut modify_back: impl FnMut(&O, &mut VarModify<T>) + Send + 'static,
461    ) -> Var<O> {
462        let mapping = self.map_bidi_modify_any(
463            move |input| BoxAnyVarValue::new(map(input.downcast_ref::<T>().unwrap())),
464            move |v, m| modify_back(v.downcast_ref::<O>().unwrap(), &mut m.downcast::<T>().unwrap()),
465            TypeId::of::<O>(),
466        );
467        Var::new_any(mapping)
468    }
469
470    /// Create a [`map_bidi`] that converts between `T` and `O` using [`Into`].
471    ///
472    /// [`map_bidi`]: Var::map_bidi
473    pub fn map_into_bidi<O>(&self) -> Var<O>
474    where
475        O: VarValue + Into<T>,
476        T: Into<O>,
477    {
478        self.map_bidi(|t| t.clone().into(), |o| o.clone().into())
479    }
480
481    /// Create a [`map_bidi_modify`] that references and clones `O` from `T` using `std::ops::Deref<Target = O>` and
482    /// modifies back using `std::ops::DerefMut<Target = O>`.
483    ///
484    /// [`map_bidi_modify`]: Self::map_bidi_modify
485    pub fn map_deref_mut<O>(&self) -> Var<O>
486    where
487        O: VarValue,
488        T: ops::Deref<Target = O>,
489        T: ops::DerefMut<Target = O>,
490    {
491        self.map_bidi_modify(
492            |input| T::deref(input).clone(),
493            |output, modify| *T::deref_mut(modify) = output.clone(),
494        )
495    }
496
497    /// Create a bidirectional mapping variable that can skip updates.
498    ///
499    /// If the `map` closure does not produce a value on init the `fallback_init` closure is called.
500    ///
501    /// # Examples
502    ///
503    /// Basic usage:
504    ///
505    /// ```
506    /// # use zng_var::*;
507    /// # use zng_txt::*;
508    /// let n_var = var(0u32);
509    /// let n_100_var = n_var.filter_map_bidi(
510    ///     |n| Some(n * 100),
511    ///     |n_100| {
512    ///         let r = n_100 / 100;
513    ///         if r < 100 { Some(r) } else { None }
514    ///     },
515    ///     || 0,
516    /// );
517    /// ```
518    ///
519    /// In the example above the `n_100_var` will update every time the `n_var` updates with any value and the `n_var` will
520    /// update every time the `n_100_var` updates with a value that `(n_100 / 100) < 100`.
521    ///
522    /// # Capabilities
523    ///
524    /// If this variable is static the `map` closure is called immediately and dropped, the mapping variable is also static,
525    /// the `map_back` closure is ignored.
526    ///
527    /// If this variable is a shared reference the `map` closure is called immediately to init the mapping variable.
528    /// The mapping variable is another shared reference and it holds a strong reference to this variable.
529    /// The `map` closure is called again for every update of this variable that is not caused by the mapping variable.
530    /// The `map_back` closure is called for every update of the mapping variable that was not caused by this variable.
531    ///
532    /// If this variable is contextual the initial `map` call is deferred until first usage of the mapping variable. The
533    /// mapping variable is also contextual and will init for every context it is used in.
534    pub fn filter_map_bidi<O: VarValue>(
535        &self,
536        mut map: impl FnMut(&T) -> Option<O> + Send + 'static,
537        mut map_back: impl FnMut(&O) -> Option<T> + Send + 'static,
538        fallback_init: impl Fn() -> O + Send + 'static,
539    ) -> Var<O> {
540        let mapping = self.filter_map_bidi_any(
541            move |t| map(t.downcast_ref::<T>().unwrap()).map(BoxAnyVarValue::new),
542            move |o| map_back(o.downcast_ref::<O>().unwrap()).map(BoxAnyVarValue::new),
543            move || BoxAnyVarValue::new(fallback_init()),
544            TypeId::of::<O>(),
545        );
546        Var::new_any(mapping)
547    }
548
549    /// Create a [`filter_map_bidi`] that tries to convert between `T` to `O` using [`TryInto`].
550    ///
551    /// [`filter_map_bidi`]: Var::filter_map_bidi
552    pub fn filter_try_into_bidi<O, I>(&self, fallback_init: I) -> Var<O>
553    where
554        O: VarValue,
555        T: TryInto<O>,
556        O: TryInto<T>,
557        I: Fn() -> O + Send + Sync + 'static,
558    {
559        self.filter_map_bidi(|v| v.clone().try_into().ok(), |o| o.clone().try_into().ok(), fallback_init)
560    }
561
562    /// Create a flat mapping variable that *unwraps* an inner variable stored in the the value of this variable.
563    ///
564    /// # Capabilities
565    ///
566    /// If this variable is static the `map` closure is called immediately and dropped and the inner variable is returned.
567    ///
568    /// If this variable is a shared reference the `map` closure is called immediately to init the mapping variable and
569    /// is called again for every update of this variable. The mapping variable is another shared reference and it holds
570    /// a strong reference to this variable and to the inner variable.
571    ///
572    /// If this variable is contextual the initial `map` call is deferred until first usage of the mapping variable. The
573    /// mapping variable is also contextual and will init for every context it is used in.
574    ///
575    /// The mapping variable has the same capabilities of the inner variable, plus [`MODIFY_CHANGES`]. When the inner variable
576    /// is writeable the return variable is too.
577    ///
578    /// [`map`]: Var::map
579    /// [`MODIFY_CHANGES`]: crate::VarCapability::MODIFY_CHANGES
580    pub fn flat_map<O: VarValue>(&self, mut map: impl FnMut(&T) -> Var<O> + Send + 'static) -> Var<O> {
581        self.any.flat_map(move |v| map(v.downcast_ref::<T>().unwrap()))
582    }
583}
584impl<T: VarValue> Var<crate::VarEq<T>> {
585    /// Create a [`flat_map`] to the inner variable.
586    ///
587    /// [`flat_map`]: Self::flat_map
588    pub fn flatten(&self) -> Var<T> {
589        self.flat_map(|v| v.0.clone())
590    }
591}
592/// Binding
593impl<T: VarValue> Var<T> {
594    /// Bind `other` to receive the new values from this variable.
595    ///
596    /// # Examples
597    ///
598    /// Basic usage:
599    ///
600    /// ```
601    /// # use zng_var::*;
602    /// #
603    /// let a = var(10);
604    /// let b = var(0);
605    ///
606    /// a.bind(&b).perm();
607    /// ```
608    ///
609    /// In the example above the variable `b` will be set every time the variable `a` updates. Note that the current
610    /// value is not propagated, only updates. You can use [`set_bind`] to assign the current value and bind.
611    ///
612    /// # Capabilities
613    ///
614    /// If this variable is const or the other variable is always read-only does nothing and returns a dummy handle.
615    ///
616    /// If any variable is contextual the binding is set on the current context inner variable.
617    ///
618    /// Neither variable holds the other, only a weak reference is used, if either variable or the handle is dropped the binding
619    /// is dropped.
620    ///
621    /// [`set_bind`]: Self::set_bind
622    pub fn bind(&self, other: &Var<T>) -> VarHandle {
623        self.any.bind(other)
624    }
625
626    /// Like [`bind`] but also sets `other` to the current value.
627    ///
628    /// Basic usage:
629    ///
630    /// ```
631    /// # fn demo() {
632    /// # use zng_var::*;
633    /// #
634    /// let a = var(10);
635    /// let b = var(0);
636    ///
637    /// a.set_bind(&b).perm();
638    /// # }
639    /// ```
640    ///
641    /// In the example above the variable `b` will be set to the current value of `a` and every time the variable `a` updates.
642    ///
643    /// # Capabilities
644    ///
645    /// If this variable is const or the other variable is always read-only does nothing and returns a dummy handle.
646    ///
647    /// If any variable is contextual the binding is set on the current context inner variable.
648    ///
649    /// Neither variable holds the other, only a weak reference is used, if either variable or the handle is dropped the binding
650    /// is dropped.
651    ///
652    /// [`bind`]: Self::bind
653    pub fn set_bind(&self, other: &Var<T>) -> VarHandle {
654        self.any.set_bind(other)
655    }
656
657    /// Bind `other` to receive the new values mapped from this variable.
658    ///
659    /// This has the same capabilities as [`bind`], but the `map` closure is called to produce the new value for `other`.
660    ///
661    /// # Examples
662    ///
663    /// Basic usage:
664    ///
665    /// ```
666    /// # use zng_var::*;
667    /// # use zng_txt::*;
668    /// let a = var(10);
669    /// let b = var(Txt::from(""));
670    ///
671    /// a.bind_map(&b, |&a| formatx!("{:?}", a * 2)).perm();
672    /// ```
673    ///
674    /// In the example above every time the variable `a` updates the variable `b` will be set to the text representation of the value times two.
675    ///
676    /// [`bind`]: Self::bind
677    pub fn bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&T) -> O + Send + 'static) -> VarHandle {
678        self.any.bind_map(other, move |v| map(v.downcast_ref::<T>().unwrap()))
679    }
680
681    /// Like [`bind_map`] but also sets `other` to the current value.
682    ///
683    /// This has the same capabilities as [`set_bind`], but the `map` closure is called to produce the new value for `other`.
684    ///
685    /// [`bind_map`]: Self::bind_map
686    /// [`set_bind`]: Self::set_bind
687    pub fn set_bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&T) -> O + Send + 'static) -> VarHandle {
688        self.any.set_bind_map(other, move |v| map(v.downcast_ref::<T>().unwrap()))
689    }
690
691    /// Bind `other` to be modified when this variable updates.
692    ///
693    /// This has the same capabilities as [`bind`], but the `modify` closure is called to modify `other` using a reference to the new value.
694    ///
695    /// # Examples
696    ///
697    /// Basic usage:
698    ///
699    /// ```
700    /// # use zng_var::*;
701    /// #
702    /// let a = var(10);
703    /// let b = var(vec![1, 2, 3]);
704    /// a.bind_modify(&b, |&a, b| {
705    ///     if b.is_empty() {
706    ///         b.push(a);
707    ///     } else {
708    ///         b[0] = a;
709    ///     }
710    /// })
711    /// .perm();
712    /// ```
713    ///
714    /// In the example above the variable `b` first element is set to the updated value of `a`.
715    ///
716    /// [`bind`]: Self::bind
717    pub fn bind_modify<O: VarValue>(&self, other: &Var<O>, mut modify: impl FnMut(&T, &mut VarModify<O>) + Send + 'static) -> VarHandle {
718        self.any.bind_modify(other, move |v, m| modify(v.downcast_ref::<T>().unwrap(), m))
719    }
720
721    /// Bind `other` to receive the new values from this variable and this variable to receive new values from `other`.
722    ///
723    /// # Capabilities
724    ///
725    /// This has the same capabilities as [`bind`], it is equivalent of setting two bindings.
726    ///
727    /// The bindings are protected against cyclic updates, like all other mappings and bindings.
728    ///
729    /// [`bind`]: Self::bind
730    pub fn bind_bidi(&self, other: &Var<T>) -> VarHandles {
731        self.any.bind_bidi(other)
732    }
733
734    /// Bind `other` to receive the new mapped values from this variable and this variable to receive new mapped values from `other`.
735    ///
736    /// This has the same capabilities as [`bind_bidi`], but the `map` closure is called to produce the new value for `other`
737    /// and `map_back` is called to produce the new value for this variable.
738    ///
739    /// [`bind_bidi`]: Self::bind_bidi
740    pub fn bind_map_bidi<O: VarValue>(
741        &self,
742        other: &Var<O>,
743        mut map: impl FnMut(&T) -> O + Send + 'static,
744        mut map_back: impl FnMut(&O) -> T + Send + 'static,
745    ) -> VarHandles {
746        self.any.bind_map_bidi_any(
747            other,
748            move |v| BoxAnyVarValue::new(map(v.downcast_ref::<T>().unwrap())),
749            move |v| BoxAnyVarValue::new(map_back(v.downcast_ref::<O>().unwrap())),
750        )
751    }
752
753    /// Bind `other` to be modified when this variable updates and this variable to be modified when `other` updates.
754    ///
755    /// This has the same capabilities as [`bind_bidi`], but the `modify` closure is called to modify `other`
756    /// and `modify_back` is called to modify this variable.
757    ///
758    /// [`bind_bidi`]: Self::bind_bidi
759    pub fn bind_modify_bidi<O: VarValue>(
760        &self,
761        other: &Var<O>,
762        mut modify: impl FnMut(&T, &mut VarModify<O>) + Send + 'static,
763        mut modify_back: impl FnMut(&O, &mut VarModify<T>) + Send + 'static,
764    ) -> VarHandles {
765        self.any.bind_modify_bidi(
766            other,
767            move |v, m| modify(v.downcast_ref::<T>().unwrap(), m),
768            move |v, m| modify_back(v, &mut m.downcast::<T>().unwrap()),
769        )
770    }
771
772    /// Bind `other` to receive the new values filtered mapped from this variable.
773    ///
774    /// This has the same capabilities as [`bind_map`], except that `other` will only receive a new value if `map` returns a value.
775    ///
776    /// [`bind_map`]: Self::bind_map
777    pub fn bind_filter_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&T) -> Option<O> + Send + 'static) -> VarHandle {
778        self.any.bind_filter_map(other, move |v| map(v.downcast_ref::<T>().unwrap()))
779    }
780
781    /// Bind `other` to receive the new filtered mapped values from this variable and this variable to receive
782    /// new filtered mapped values from `other`.
783    pub fn bind_filter_map_bidi<O: VarValue>(
784        &self,
785        other: &Var<O>,
786        mut map: impl FnMut(&T) -> Option<O> + Send + 'static,
787        mut map_back: impl FnMut(&O) -> Option<T> + Send + 'static,
788    ) -> VarHandles {
789        self.any.bind_filter_map_bidi_any(
790            other,
791            move |v| map(v.downcast_ref::<T>().unwrap()).map(BoxAnyVarValue::new),
792            move |v| map_back(v.downcast_ref::<O>().unwrap()).map(BoxAnyVarValue::new),
793        )
794    }
795}
796/// Animation
797impl<T: VarValue> Var<T> {
798    /// Schedule a custom animation that targets this variable.
799    ///
800    /// The `animate` closure is called every frame, starting after next frame, the closure inputs are
801    /// the [`Animation`] args and *modify* access to the variable value, the args
802    /// can be used to calculate the new variable value and to control or stop the animation.
803    ///
804    /// # Examples
805    ///
806    /// Customs animation that displays the animation elapsed time:
807    ///
808    /// ```
809    /// # fn demo() {
810    /// # use zng_var::*;
811    /// # use zng_txt::*;
812    /// # use zng_unit::*;
813    /// let status = var(Txt::from("not animating"));
814    ///
815    /// status
816    ///     .animate(|animation, value| {
817    ///         let elapsed = animation.elapsed_dur();
818    ///         if elapsed < 5.secs() {
819    ///             value.set(formatx!("animating: elapsed {}ms", elapsed.as_millis()));
820    ///         } else {
821    ///             animation.stop();
822    ///             value.set("not animating");
823    ///         }
824    ///     })
825    ///     .perm();
826    /// # }
827    /// ```
828    ///
829    /// # Capabilities
830    ///
831    /// If the variable is always read-only no animation is created and a dummy handle returned.
832    ///
833    /// If this var is contextual the animation targets the current context var.
834    ///
835    /// The animation is stopped if this variable is dropped.
836    ///
837    /// [`Animation`]: Animation
838    pub fn animate(&self, mut animate: impl FnMut(&Animation, &mut VarModify<T>) + Send + 'static) -> AnimationHandle {
839        self.any.animate(move |a, v| animate(a, &mut v.downcast::<T>().unwrap()))
840    }
841
842    /// Schedule animations started by `animate`, the closure is called once at the start to begin, then again every time
843    /// the variable stops animating.
844    ///
845    /// This can be used to create a sequence of animations or to repeat an animation.
846    ///
847    /// # Examples
848    ///
849    /// Running multiple animations in sequence:
850    ///
851    /// ```
852    /// # fn demo() {
853    /// # use zng_var::{*, animation::*};
854    /// # use zng_txt::*;
855    /// # use zng_unit::*;
856    /// let status = var(Txt::from("not animating"));
857    ///
858    /// let mut stage = 0;
859    /// status
860    ///     .sequence(move |status| {
861    ///         stage += 1;
862    ///         if stage < 5 {
863    ///             status.animate(move |animation, value| {
864    ///                 let elapsed = animation.elapsed_stop(5.secs());
865    ///                 value.set(formatx!("animation {stage}: {}", elapsed.pct()));
866    ///             })
867    ///         } else {
868    ///             status.set("not animating");
869    ///             AnimationHandle::dummy()
870    ///         }
871    ///     })
872    ///     .perm();
873    /// # }
874    /// ```
875    ///
876    /// # Capabilities
877    ///
878    /// The sequence stops when `animate` returns a dummy handle, or the variable is modified outside of `animate`,
879    /// or animations are disabled, or the returned handle is dropped.
880    pub fn sequence(&self, mut animate: impl FnMut(Var<T>) -> AnimationHandle + Send + 'static) -> VarHandle {
881        self.any.sequence(move |v| animate(Var::new_any(v)))
882    }
883
884    /// Schedule an easing transition from the `start_value` to `end_value`.
885    ///
886    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
887    ///
888    /// # Examples
889    ///
890    /// Basic usage:
891    ///
892    /// ```
893    /// # fn demo() {
894    /// # use zng_var::{*, animation::easing};
895    /// # use zng_unit::*;
896    /// let progress = var(0.pct());
897    ///
898    /// progress.set_ease(0.pct(), 100.pct(), 5.secs(), easing::linear).perm();
899    /// # }
900    /// ```
901    ///
902    /// Variable is reset to 0% at the start and them transition to 100% in 5 seconds with linear progression.
903    ///
904    /// # Capabilities
905    ///
906    /// See [`animate`] for details about animation capabilities.
907    ///
908    /// [`animate`]: Self::animate
909    pub fn set_ease(
910        &self,
911        start_value: impl Into<T>,
912        end_value: impl Into<T>,
913        duration: Duration,
914        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
915    ) -> AnimationHandle
916    where
917        T: Transitionable,
918    {
919        self.set_ease_with(start_value, end_value, duration, easing, Transition::sample)
920    }
921
922    /// Oscillate between `start_value` to `end_value` with an easing transition.
923    ///
924    /// The `duration` defines the easing duration between the two values. The animation will continue running
925    /// until the handle or the variable is dropped.
926    ///
927    /// Note that you can use [`sequence`] to create more complex looping animations.
928    ///
929    /// [`sequence`]: Var::sequence
930    pub fn set_ease_oci(
931        &self,
932        start_value: impl Into<T>,
933        end_value: impl Into<T>,
934        duration: Duration,
935        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
936    ) -> AnimationHandle
937    where
938        T: Transitionable,
939    {
940        self.set_ease_oci_with(start_value, end_value, duration, easing, Transition::sample)
941    }
942
943    /// Schedule an easing transition from the `start_value` to `end_value` using a custom value sampler.
944    ///
945    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
946    ///
947    /// See [`animate`] for details about animation capabilities.
948    ///
949    /// [`animate`]: Self::animate
950    pub fn set_ease_with(
951        &self,
952        start_value: impl Into<T>,
953        end_value: impl Into<T>,
954        duration: Duration,
955        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
956        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
957    ) -> AnimationHandle
958    where
959        T: Transitionable,
960    {
961        self.ease_impl(start_value.into(), end_value.into(), duration, easing, 999.fct(), sampler)
962    }
963
964    /// Oscillate between `start_value` to `end_value` with an easing transition using a custom value sampler.
965    ///
966    /// The `duration` defines the easing duration between the two values.
967    ///
968    /// Note that you can use [`sequence`] to create more complex looping animations.
969    ///
970    /// [`sequence`]: Self::sequence
971    pub fn set_ease_oci_with(
972        &self,
973        start_value: impl Into<T>,
974        end_value: impl Into<T>,
975        duration: Duration,
976        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
977        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
978    ) -> AnimationHandle
979    where
980        T: Transitionable,
981    {
982        self.ease_oci_impl(start_value.into(), end_value.into(), duration, easing, 999.fct(), sampler)
983    }
984
985    /// Schedule an easing transition from the current value to `new_value`.
986    ///
987    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
988    ///
989    /// See [`animate`] for details about animation capabilities.
990    ///
991    /// [`animate`]: Var::animate
992    pub fn ease(
993        &self,
994        new_value: impl Into<T>,
995        duration: Duration,
996        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
997    ) -> AnimationHandle
998    where
999        T: Transitionable,
1000    {
1001        self.ease_with(new_value, duration, easing, Transition::sample)
1002    }
1003
1004    /// Oscillate between the current value and `new_value` with an easing transition.
1005    ///
1006    /// The `duration` defines the easing duration between the two values.
1007    ///
1008    /// Note that you can use [`sequence`] to create more complex looping animations.
1009    ///
1010    /// [`sequence`]: Var::sequence
1011    pub fn ease_oci(
1012        &self,
1013        new_value: impl Into<T>,
1014        duration: Duration,
1015        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1016    ) -> AnimationHandle
1017    where
1018        T: Transitionable,
1019    {
1020        self.ease_oci_with(new_value, duration, easing, Transition::sample)
1021    }
1022
1023    /// Schedule an easing transition from the current value to `new_value` using a custom value sampler.
1024    ///
1025    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
1026    ///
1027    /// See [`animate`] for details about animation capabilities.
1028    ///
1029    /// [`animate`]: Var::animate
1030    pub fn ease_with(
1031        &self,
1032        new_value: impl Into<T>,
1033        duration: Duration,
1034        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1035        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
1036    ) -> AnimationHandle
1037    where
1038        T: Transitionable,
1039    {
1040        self.ease_impl(self.get(), new_value.into(), duration, easing, 0.fct(), sampler)
1041    }
1042
1043    /// Oscillate between the current value and `new_value` with an easing transition and a custom value sampler.
1044    ///
1045    /// The `duration` defines the easing duration between the two values.
1046    ///
1047    /// Note that you can use [`sequence`] to create more complex looping animations.
1048    ///
1049    /// [`sequence`]: Self::sequence
1050    pub fn ease_oci_with(
1051        &self,
1052        new_value: impl Into<T>,
1053        duration: Duration,
1054        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1055        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
1056    ) -> AnimationHandle
1057    where
1058        T: Transitionable,
1059    {
1060        self.ease_oci_impl(self.get(), new_value.into(), duration, easing, 0.fct(), sampler)
1061    }
1062
1063    /// Schedule a keyframed transition animation for the variable, starting from the first key.
1064    ///
1065    /// The variable will be set to the first keyframe, then animated across all other keys.
1066    ///
1067    /// See [`animate`] for details about animations.
1068    ///
1069    /// [`animate`]: Self::animate
1070    pub fn set_ease_keyed(
1071        &self,
1072        keys: Vec<(Factor, T)>,
1073        duration: Duration,
1074        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1075    ) -> AnimationHandle
1076    where
1077        T: Transitionable,
1078    {
1079        self.set_ease_keyed_with(keys, duration, easing, TransitionKeyed::sample)
1080    }
1081
1082    /// Schedule a keyframed transition animation for the variable, starting from the first key, using a custom value sampler.
1083    ///
1084    /// The variable will be set to the first keyframe, then animated across all other keys.
1085    ///
1086    /// See [`animate`] for details about animations.
1087    ///
1088    /// [`animate`]: Self::animate
1089    pub fn set_ease_keyed_with(
1090        &self,
1091        keys: Vec<(Factor, T)>,
1092        duration: Duration,
1093        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1094        sampler: impl Fn(&TransitionKeyed<T>, EasingStep) -> T + Send + 'static,
1095    ) -> AnimationHandle
1096    where
1097        T: Transitionable,
1098    {
1099        if let Some(transition) = TransitionKeyed::new(keys) {
1100            self.ease_keyed_impl(transition, duration, easing, 999.fct(), sampler)
1101        } else {
1102            AnimationHandle::dummy()
1103        }
1104    }
1105
1106    /// Schedule a keyframed transition animation for the variable, starting from the current value.
1107    ///
1108    /// The variable will be set to the first keyframe, then animated across all other keys.
1109    ///
1110    /// See [`animate`] for details about animations.
1111    ///
1112    /// [`animate`]: Self::animate
1113    pub fn ease_keyed(
1114        &self,
1115        keys: Vec<(Factor, T)>,
1116        duration: Duration,
1117        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1118    ) -> AnimationHandle
1119    where
1120        T: Transitionable,
1121    {
1122        self.ease_keyed_with(keys, duration, easing, TransitionKeyed::sample)
1123    }
1124
1125    /// Schedule a keyframed transition animation for the variable, starting from the current value, using a custom value sampler.
1126    ///
1127    /// The variable will be set to the first keyframe, then animated across all other keys.
1128    ///
1129    /// See [`animate`] for details about animations.
1130    ///
1131    /// [`animate`]: Self::animate
1132    pub fn ease_keyed_with(
1133        &self,
1134        mut keys: Vec<(Factor, T)>,
1135        duration: Duration,
1136        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1137        sampler: impl Fn(&TransitionKeyed<T>, EasingStep) -> T + Send + 'static,
1138    ) -> AnimationHandle
1139    where
1140        T: Transitionable,
1141    {
1142        keys.insert(0, (0.fct(), self.get()));
1143
1144        let transition = TransitionKeyed::new(keys).unwrap();
1145        self.ease_keyed_impl(transition, duration, easing, 0.fct(), sampler)
1146    }
1147
1148    /// Set the variable to `new_value` after a `delay`.
1149    ///
1150    /// The variable [`is_animating`] until the delay elapses and the value is set.
1151    ///
1152    /// See [`animate`] for details about animations.
1153    ///
1154    /// [`is_animating`]: AnyVar::is_animating
1155    /// [`animate`]: Self::animate
1156    pub fn step(&self, new_value: impl Into<T>, delay: Duration) -> AnimationHandle {
1157        self.step_impl(new_value.into(), delay)
1158    }
1159
1160    /// Oscillate between the current value and `new_value`, every time the `delay` elapses the variable is set to the next value.
1161    pub fn step_oci(&self, new_value: impl Into<T>, delay: Duration) -> AnimationHandle {
1162        self.step_oci_impl([self.get(), new_value.into()], delay, false)
1163    }
1164
1165    /// Oscillate between `from` and `to`, the variable is set to `from` to start and every time the `delay` elapses
1166    /// the variable is set to the next value.
1167    pub fn set_step_oci(&self, from: impl Into<T>, to: impl Into<T>, delay: Duration) -> AnimationHandle {
1168        self.step_oci_impl([from.into(), to.into()], delay, true)
1169    }
1170
1171    /// Set the variable to a sequence of values as a time `duration` elapses.
1172    ///
1173    /// An animation curve is used to find the first factor in `steps` above or at the curve line at the current time,
1174    /// the variable is set to this step value, continuing animating across the next steps until the last or the animation end.
1175    /// The variable [`is_animating`] from the start, even if no step applies and stays *animating* until the last *step* applies
1176    /// or the duration is reached.
1177    ///
1178    /// # Examples
1179    ///
1180    /// Creates a variable that outputs text every 5% of a 5 seconds animation, advanced linearly.
1181    ///
1182    /// ```
1183    /// # use zng_var::{*, animation::easing};
1184    /// # use zng_txt::*;
1185    /// # use zng_unit::*;
1186    /// # fn demo(text_var: Var<Txt>) {
1187    /// let steps = (0..=100).step_by(5).map(|i| (i.pct().fct(), formatx!("{i}%"))).collect();
1188    /// # let _ =
1189    /// text_var.steps(steps, 5.secs(), easing::linear)
1190    /// # ;}
1191    /// ```
1192    ///
1193    /// The variable is set to `"0%"`, after 5% of the `duration` elapses it is set to `"5%"` and so on
1194    /// until the value is set to `"100%` at the end of the animation.
1195    ///
1196    /// Returns an [`AnimationHandle`]. See [`Var::animate`] for details about animations.
1197    ///
1198    /// [`is_animating`]: AnyVar::is_animating
1199    /// [`AnimationHandle`]: crate::animation::AnimationHandle
1200    pub fn steps(
1201        &self,
1202        steps: Vec<(Factor, T)>,
1203        duration: Duration,
1204        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1205    ) -> AnimationHandle {
1206        let mut prev_step = 999.fct();
1207        self.animate(move |a, vm| {
1208            let step = easing(a.elapsed_stop(duration));
1209            if step != prev_step {
1210                prev_step = step;
1211                if let Some(val) = steps.iter().find(|(f, _)| *f >= step).map(|(_, step)| step.clone()) {
1212                    vm.set(val);
1213                }
1214            }
1215        })
1216    }
1217
1218    /// Starts an easing animation that *chases* a target value that can be changed using the [`ChaseAnimation<T>`] handle.
1219    pub fn chase(
1220        &self,
1221        first_target: impl Into<T>,
1222        duration: Duration,
1223        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1224    ) -> ChaseAnimation<T>
1225    where
1226        T: Transitionable,
1227    {
1228        self.chase_impl(first_target.into(), duration, easing)
1229    }
1230    fn chase_impl(
1231        &self,
1232        first_target: T,
1233        duration: Duration,
1234        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1235    ) -> ChaseAnimation<T>
1236    where
1237        T: Transitionable,
1238    {
1239        ChaseAnimation {
1240            handle: self.ease(first_target.clone(), duration, easing),
1241            target: first_target,
1242            var: self.current_context(),
1243        }
1244    }
1245
1246    /// Create a vars that [`ease`] to each new value of `self`.
1247    ///
1248    /// Note that the mapping var can be [contextualized], see [`map`] for more details.
1249    ///
1250    /// If `self` can change the output variable will keep it alive.
1251    ///
1252    /// [contextualized]: crate::contextual_var
1253    /// [`ease`]: Var::ease
1254    /// [`map`]: Var::map
1255    pub fn easing(&self, duration: Duration, easing: impl Fn(EasingTime) -> EasingStep + Send + Sync + 'static) -> Var<T>
1256    where
1257        T: Transitionable,
1258    {
1259        self.easing_with(duration, easing, Transition::sample)
1260    }
1261
1262    /// Create a vars that [`ease_with`] to each new value of `self`.
1263    ///
1264    /// Note that the mapping var can be contextualized, see [`map`] for more details.
1265    /// If `self` is shared the output variable will hold a strong reference to it.
1266    ///
1267    /// [`ease_with`]: Var::ease_with
1268    /// [`map`]: Var::map
1269    pub fn easing_with(
1270        &self,
1271        duration: Duration,
1272        easing: impl Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
1273        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + Sync + 'static,
1274    ) -> Var<T>
1275    where
1276        T: Transitionable,
1277    {
1278        let caps = self.capabilities();
1279        if caps.is_const() {
1280            return self.clone();
1281        }
1282
1283        let fns = Arc::new((easing, sampler));
1284
1285        if caps.is_contextual() {
1286            let me = self.clone();
1287            return contextual_var(move || me.clone().easing_with_tail(duration, fns.clone()));
1288        }
1289
1290        self.easing_with_tail(duration, fns)
1291    }
1292    // to avoid infinite closure type (contextual case)
1293    fn easing_with_tail(
1294        &self,
1295        duration: Duration,
1296        fns: Arc<(
1297            impl Fn(EasingTime) -> Factor + Send + Sync + 'static,
1298            impl Fn(&Transition<T>, Factor) -> T + Send + Sync + 'static,
1299        )>,
1300    ) -> Var<T>
1301    where
1302        T: Transitionable,
1303    {
1304        let me = self.current_context();
1305
1306        let output = crate::var(me.get());
1307
1308        let weak_output = output.downgrade();
1309        let mut _ease_handle = AnimationHandle::dummy();
1310        me.hook(move |args| {
1311            if let Some(output) = weak_output.upgrade() {
1312                _ease_handle = output.ease_with(
1313                    args.value().clone(),
1314                    duration,
1315                    clmv!(fns, |t| fns.0(t)),
1316                    clmv!(fns, |t, s| fns.1(t, s)),
1317                );
1318                true
1319            } else {
1320                false
1321            }
1322        })
1323        .perm();
1324        output.hold(me).perm();
1325
1326        output.read_only()
1327    }
1328
1329    fn ease_impl(
1330        &self,
1331        start_value: T,
1332        end_value: T,
1333        duration: Duration,
1334        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1335        init_step: Factor, // set to 0 skips first frame, set to 999 includes first frame.
1336        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
1337    ) -> AnimationHandle
1338    where
1339        T: Transitionable,
1340    {
1341        let transition = Transition::new(start_value, end_value);
1342        let mut prev_step = init_step;
1343        self.animate(move |a, vm| {
1344            let step = easing(a.elapsed_stop(duration));
1345
1346            if prev_step != step {
1347                vm.set(sampler(&transition, step));
1348                prev_step = step;
1349            }
1350        })
1351    }
1352
1353    fn ease_oci_impl(
1354        &self,
1355        start_value: T,
1356        end_value: T,
1357        duration: Duration,
1358        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1359        init_step: EasingStep, // set to 0 skips first frame, set to 999 includes first frame.
1360        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
1361    ) -> AnimationHandle
1362    where
1363        T: Transitionable,
1364    {
1365        let transition = Transition::new(start_value, end_value);
1366        let mut prev_step = init_step;
1367        self.animate(move |a, vm| {
1368            let t = a.elapsed(duration);
1369            let mut step = easing(t);
1370            if a.restart_count() % 2 != 0 {
1371                step = step.flip()
1372            }
1373            if t.is_end() {
1374                a.restart();
1375            }
1376
1377            if prev_step != step {
1378                vm.set(sampler(&transition, step));
1379                prev_step = step;
1380            }
1381        })
1382    }
1383
1384    fn ease_keyed_impl(
1385        &self,
1386        transition: TransitionKeyed<T>,
1387        duration: Duration,
1388        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1389        init_step: EasingStep,
1390        sampler: impl Fn(&TransitionKeyed<T>, EasingStep) -> T + Send + 'static,
1391    ) -> AnimationHandle
1392    where
1393        T: Transitionable,
1394    {
1395        let mut prev_step = init_step;
1396        self.animate(move |a, value| {
1397            let step = easing(a.elapsed_stop(duration));
1398
1399            if prev_step != step {
1400                value.set(sampler(&transition, step));
1401                prev_step = step;
1402            }
1403        })
1404    }
1405
1406    fn step_impl(&self, new_value: T, delay: Duration) -> AnimationHandle {
1407        let mut new_value = Some(new_value);
1408        self.animate(move |a, vm| {
1409            if !a.animations_enabled() || a.elapsed_dur() >= delay {
1410                a.stop();
1411                if let Some(nv) = new_value.take() {
1412                    vm.set(nv);
1413                }
1414            } else {
1415                a.sleep(delay);
1416            }
1417        })
1418    }
1419
1420    fn step_oci_impl(&self, values: [T; 2], delay: Duration, mut set: bool) -> AnimationHandle {
1421        let mut first = false;
1422        self.animate(move |a, vm| {
1423            if !a.animations_enabled() || std::mem::take(&mut set) {
1424                vm.set(values[0].clone());
1425            } else if a.elapsed_dur() >= delay {
1426                if first {
1427                    vm.set(values[0].clone());
1428                } else {
1429                    vm.set(values[1].clone());
1430                }
1431                first = !first;
1432            }
1433            a.sleep(delay);
1434        })
1435    }
1436}
1437/// Transition animations
1438impl<T: VarValue + Transitionable> Var<T> {}
1439/// Value type.
1440impl<T: VarValue> Var<T> {
1441    /// Reference the variable without the strong value type.
1442    pub fn as_any(&self) -> &AnyVar {
1443        &self.any
1444    }
1445}
1446/// Variable type.
1447impl<T: VarValue> Var<T> {
1448    /// Create a weak reference to this variable.
1449    pub fn downgrade(&self) -> WeakVar<T> {
1450        WeakVar {
1451            any: self.any.downgrade(),
1452            _t: PhantomData,
1453        }
1454    }
1455
1456    /// Gets a clone of the var that is always read-only.
1457    ///
1458    /// The returned variable can still update if `self` is modified, but it does not have the `MODIFY` capability.
1459    pub fn read_only(&self) -> Var<T> {
1460        Var::new_any(self.any.read_only())
1461    }
1462
1463    /// Create a var that redirects to this variable until the first value update, then it disconnects as a separate variable.
1464    ///
1465    /// The return variable is *clone-on-write* and has the `MODIFY` capability independent of the source capabilities, when
1466    /// a modify request is made the source value is cloned and offered for modification, if modified the source variable is dropped,
1467    /// if the modify closure does not update the source variable is retained.
1468    pub fn cow(&self) -> Var<T> {
1469        Var::new_any(self.any.cow())
1470    }
1471
1472    /// Gets the underlying var in the current calling context.
1473    ///
1474    /// If this variable is [`CONTEXT`] returns a clone of the inner variable,
1475    /// otherwise returns a clone of this variable.
1476    ///
1477    /// [`CONTEXT`]: crate::VarCapability::CONTEXT
1478    pub fn current_context(&self) -> Var<T> {
1479        Var::new_any(self.any.current_context())
1480    }
1481
1482    /// Gets if this variable is the same as `other`.
1483    ///
1484    /// If this variable is [`SHARE`] compares the *pointer*. If this variable is local this is always `false`.
1485    ///
1486    /// [`SHARE`]: crate::VarCapability::SHARE
1487    pub fn var_eq(&self, other: &Self) -> bool {
1488        self.any.var_eq(&other.any)
1489    }
1490}
1491
1492/// Weak reference to a [`Var<T>`].
1493pub struct WeakVar<T: VarValue> {
1494    any: WeakAnyVar,
1495    _t: PhantomData<T>,
1496}
1497impl<T: VarValue> fmt::Debug for WeakVar<T> {
1498    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1499        f.debug_tuple("WeakVar").field(&self.any.0).finish()
1500    }
1501}
1502impl<T: VarValue> Clone for WeakVar<T> {
1503    fn clone(&self) -> Self {
1504        Self {
1505            any: self.any.clone(),
1506            _t: PhantomData,
1507        }
1508    }
1509}
1510impl<T: VarValue> From<WeakVar<T>> for WeakAnyVar {
1511    fn from(var: WeakVar<T>) -> Self {
1512        var.any
1513    }
1514}
1515impl<T: VarValue> ops::Deref for WeakVar<T> {
1516    type Target = WeakAnyVar;
1517
1518    fn deref(&self) -> &Self::Target {
1519        self.as_any()
1520    }
1521}
1522impl<T: VarValue> WeakVar<T> {
1523    /// Reference the weak variable without the strong value type.
1524    pub fn as_any(&self) -> &WeakAnyVar {
1525        &self.any
1526    }
1527
1528    /// Attempt to create a strong reference to the variable.
1529    pub fn upgrade(&self) -> Option<Var<T>> {
1530        self.any.upgrade().map(Var::new_any)
1531    }
1532}
1533
1534/// New read/write shared reference variable from any type that can convert into it.
1535pub fn var_from<T: VarValue>(initial_value: impl Into<T>) -> Var<T> {
1536    crate::var(initial_value.into())
1537}
1538
1539/// New read/write shared reference variable with default initial value.
1540pub fn var_default<T: VarValue + Default>() -> Var<T> {
1541    crate::var(T::default())
1542}
1543
1544/// New immutable variable that stores the `value` directly.
1545///
1546/// Cloning this variable clones the value.
1547pub fn const_var<T: VarValue>(value: T) -> Var<T> {
1548    Var::new_any(any_const_var(BoxAnyVarValue::new(value)))
1549}
1550
1551/// Type erased [`const_var`].
1552pub fn any_const_var(value: BoxAnyVarValue) -> AnyVar {
1553    AnyVar(crate::DynAnyVar::Const(crate::var_impl::const_var::ConstVar::new(value)))
1554}
1555
1556/// Weak variable that never upgrades.
1557pub fn weak_var<T: VarValue>() -> WeakVar<T> {
1558    WeakVar {
1559        any: weak_var_any(),
1560        _t: PhantomData,
1561    }
1562}
1563
1564/// Weak variable that never upgrades.
1565pub fn weak_var_any() -> WeakAnyVar {
1566    WeakAnyVar(crate::DynWeakAnyVar::Const(crate::var_impl::const_var::WeakConstVar))
1567}
1568
1569/// Arguments for [`Var::hook`].
1570pub struct VarHookArgs<'a, T: VarValue> {
1571    pub(super) any: &'a AnyVarHookArgs<'a>,
1572    pub(super) _t: PhantomData<&'a T>,
1573}
1574impl<'a, T: VarValue> VarHookArgs<'a, T> {
1575    /// Reference the updated value.
1576    pub fn value(&self) -> &'a T {
1577        self.any.value.downcast_ref::<T>().unwrap()
1578    }
1579}
1580impl<'a, T: VarValue> ops::Deref for VarHookArgs<'a, T> {
1581    type Target = AnyVarHookArgs<'a>;
1582
1583    fn deref(&self) -> &Self::Target {
1584        self.any
1585    }
1586}