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}
592impl<T: VarValue> Var<Vec<T>> {
593    /// Create a flat mapping variable that maps each variable entry in `self` to a value entry in the output.
594    ///
595    /// This is similar to [`flat_map`], but operates over many inner variables in a `Vec` value. Note that the `map`
596    /// closure inputs are each item index and the item.
597    ///
598    /// # Capabilities
599    ///
600    /// If this variable is static the `map` closure is called immediately for each item and dropped. The selected inner variables
601    /// are merged into the mapping variable and will continue updating it.
602    ///
603    /// If this variable is a shared reference the `map` closure is called immediately for each item to init the result and will
604    /// be called again for each item for every update of this variable. The mapping variable is another shared reference and it holds
605    /// a strong reference to this variable and the inner variables.
606    ///
607    /// If this variable is contextual the initial `map` calls is deferred until first usage of the mapping variable. The
608    /// mapping variable is also contextual and will init for every context it is used in.
609    ///
610    /// The mapping variable is read-only.
611    ///
612    /// [`flat_map`]: Self::flat_map
613    pub fn flat_map_vec<O: VarValue>(&self, mut map: impl FnMut(usize, &T) -> Var<O> + Send + 'static) -> Var<Vec<O>> {
614        self.flat_map(move |vec| {
615            let mut item_vars: Vec<(Var<O>, VarHandle)> = vec.iter().enumerate().map(|(i, it)| (map(i, it), VarHandle::dummy())).collect();
616            let out_value: Vec<O> = item_vars.iter().map(|v| v.0.get()).collect();
617            let out_var = crate::var(out_value);
618
619            for (i, (item_var, handle)) in item_vars.iter_mut().enumerate() {
620                *handle = item_var.bind_modify(&out_var, move |item_value, out_value| {
621                    if &out_value.value()[i] != item_value {
622                        out_value.value_mut()[i] = item_value.clone();
623                    }
624                });
625            }
626            out_var.hold(item_vars).perm();
627
628            out_var.read_only()
629        })
630    }
631}
632/// Binding
633impl<T: VarValue> Var<T> {
634    /// Bind `other` to receive the new values from this variable.
635    ///
636    /// # Examples
637    ///
638    /// Basic usage:
639    ///
640    /// ```
641    /// # use zng_var::*;
642    /// #
643    /// let a = var(10);
644    /// let b = var(0);
645    ///
646    /// a.bind(&b).perm();
647    /// ```
648    ///
649    /// In the example above the variable `b` will be set every time the variable `a` updates. Note that the current
650    /// value is not propagated, only updates. You can use [`set_bind`] to assign the current value and bind.
651    ///
652    /// # Capabilities
653    ///
654    /// If this variable is const or the other variable is always read-only does nothing and returns a dummy handle.
655    ///
656    /// If any variable is contextual the binding is set on the current context inner variable.
657    ///
658    /// Neither variable holds the other, only a weak reference is used, if either variable or the handle is dropped the binding
659    /// is dropped.
660    ///
661    /// [`set_bind`]: Self::set_bind
662    pub fn bind(&self, other: &Var<T>) -> VarHandle {
663        self.any.bind(other)
664    }
665
666    /// Like [`bind`] but also sets `other` to the current value.
667    ///
668    /// Basic usage:
669    ///
670    /// ```
671    /// # fn demo() {
672    /// # use zng_var::*;
673    /// #
674    /// let a = var(10);
675    /// let b = var(0);
676    ///
677    /// a.set_bind(&b).perm();
678    /// # }
679    /// ```
680    ///
681    /// In the example above the variable `b` will be set to the current value of `a` and every time the variable `a` updates.
682    ///
683    /// # Capabilities
684    ///
685    /// If this variable is const or the other variable is always read-only does nothing and returns a dummy handle.
686    ///
687    /// If any variable is contextual the binding is set on the current context inner variable.
688    ///
689    /// Neither variable holds the other, only a weak reference is used, if either variable or the handle is dropped the binding
690    /// is dropped.
691    ///
692    /// [`bind`]: Self::bind
693    pub fn set_bind(&self, other: &Var<T>) -> VarHandle {
694        self.any.set_bind(other)
695    }
696
697    /// Bind `other` to receive the new values mapped from this variable.
698    ///
699    /// This has the same capabilities as [`bind`], but the `map` closure is called to produce the new value for `other`.
700    ///
701    /// # Examples
702    ///
703    /// Basic usage:
704    ///
705    /// ```
706    /// # use zng_var::*;
707    /// # use zng_txt::*;
708    /// let a = var(10);
709    /// let b = var(Txt::from(""));
710    ///
711    /// a.bind_map(&b, |&a| formatx!("{:?}", a * 2)).perm();
712    /// ```
713    ///
714    /// 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.
715    ///
716    /// [`bind`]: Self::bind
717    pub fn bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&T) -> O + Send + 'static) -> VarHandle {
718        self.any.bind_map(other, move |v| map(v.downcast_ref::<T>().unwrap()))
719    }
720
721    /// Like [`bind_map`] but also sets `other` to the current value.
722    ///
723    /// This has the same capabilities as [`set_bind`], but the `map` closure is called to produce the new value for `other`.
724    ///
725    /// [`bind_map`]: Self::bind_map
726    /// [`set_bind`]: Self::set_bind
727    pub fn set_bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&T) -> O + Send + 'static) -> VarHandle {
728        self.any.set_bind_map(other, move |v| map(v.downcast_ref::<T>().unwrap()))
729    }
730
731    /// Bind `other` to be modified when this variable updates.
732    ///
733    /// This has the same capabilities as [`bind`], but the `modify` closure is called to modify `other` using a reference to the new value.
734    ///
735    /// # Examples
736    ///
737    /// Basic usage:
738    ///
739    /// ```
740    /// # use zng_var::*;
741    /// #
742    /// let a = var(10);
743    /// let b = var(vec![1, 2, 3]);
744    /// a.bind_modify(&b, |&a, b| {
745    ///     if b.is_empty() {
746    ///         b.push(a);
747    ///     } else {
748    ///         b[0] = a;
749    ///     }
750    /// })
751    /// .perm();
752    /// ```
753    ///
754    /// In the example above the variable `b` first element is set to the updated value of `a`.
755    ///
756    /// [`bind`]: Self::bind
757    pub fn bind_modify<O: VarValue>(&self, other: &Var<O>, mut modify: impl FnMut(&T, &mut VarModify<O>) + Send + 'static) -> VarHandle {
758        self.any.bind_modify(other, move |v, m| modify(v.downcast_ref::<T>().unwrap(), m))
759    }
760
761    /// Bind `other` to receive the new values from this variable and this variable to receive new values from `other`.
762    ///
763    /// # Capabilities
764    ///
765    /// This has the same capabilities as [`bind`], it is equivalent of setting two bindings.
766    ///
767    /// The bindings are protected against cyclic updates, like all other mappings and bindings.
768    ///
769    /// [`bind`]: Self::bind
770    pub fn bind_bidi(&self, other: &Var<T>) -> VarHandles {
771        self.any.bind_bidi(other)
772    }
773
774    /// Bind `other` to receive the new mapped values from this variable and this variable to receive new mapped values from `other`.
775    ///
776    /// This has the same capabilities as [`bind_bidi`], but the `map` closure is called to produce the new value for `other`
777    /// and `map_back` is called to produce the new value for this variable.
778    ///
779    /// [`bind_bidi`]: Self::bind_bidi
780    pub fn bind_map_bidi<O: VarValue>(
781        &self,
782        other: &Var<O>,
783        mut map: impl FnMut(&T) -> O + Send + 'static,
784        mut map_back: impl FnMut(&O) -> T + Send + 'static,
785    ) -> VarHandles {
786        self.any.bind_map_bidi_any(
787            other,
788            move |v| BoxAnyVarValue::new(map(v.downcast_ref::<T>().unwrap())),
789            move |v| BoxAnyVarValue::new(map_back(v.downcast_ref::<O>().unwrap())),
790        )
791    }
792
793    /// Bind `other` to be modified when this variable updates and this variable to be modified when `other` updates.
794    ///
795    /// This has the same capabilities as [`bind_bidi`], but the `modify` closure is called to modify `other`
796    /// and `modify_back` is called to modify this variable.
797    ///
798    /// [`bind_bidi`]: Self::bind_bidi
799    pub fn bind_modify_bidi<O: VarValue>(
800        &self,
801        other: &Var<O>,
802        mut modify: impl FnMut(&T, &mut VarModify<O>) + Send + 'static,
803        mut modify_back: impl FnMut(&O, &mut VarModify<T>) + Send + 'static,
804    ) -> VarHandles {
805        self.any.bind_modify_bidi(
806            other,
807            move |v, m| modify(v.downcast_ref::<T>().unwrap(), m),
808            move |v, m| modify_back(v, &mut m.downcast::<T>().unwrap()),
809        )
810    }
811
812    /// Bind `other` to receive the new values filtered mapped from this variable.
813    ///
814    /// This has the same capabilities as [`bind_map`], except that `other` will only receive a new value if `map` returns a value.
815    ///
816    /// [`bind_map`]: Self::bind_map
817    pub fn bind_filter_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&T) -> Option<O> + Send + 'static) -> VarHandle {
818        self.any.bind_filter_map(other, move |v| map(v.downcast_ref::<T>().unwrap()))
819    }
820
821    /// Bind `other` to receive the new filtered mapped values from this variable and this variable to receive
822    /// new filtered mapped values from `other`.
823    pub fn bind_filter_map_bidi<O: VarValue>(
824        &self,
825        other: &Var<O>,
826        mut map: impl FnMut(&T) -> Option<O> + Send + 'static,
827        mut map_back: impl FnMut(&O) -> Option<T> + Send + 'static,
828    ) -> VarHandles {
829        self.any.bind_filter_map_bidi_any(
830            other,
831            move |v| map(v.downcast_ref::<T>().unwrap()).map(BoxAnyVarValue::new),
832            move |v| map_back(v.downcast_ref::<O>().unwrap()).map(BoxAnyVarValue::new),
833        )
834    }
835}
836/// Animation
837impl<T: VarValue> Var<T> {
838    /// Schedule a custom animation that targets this variable.
839    ///
840    /// The `animate` closure is called every frame, starting after next frame, the closure inputs are
841    /// the [`Animation`] args and *modify* access to the variable value, the args
842    /// can be used to calculate the new variable value and to control or stop the animation.
843    ///
844    /// # Examples
845    ///
846    /// Customs animation that displays the animation elapsed time:
847    ///
848    /// ```
849    /// # fn demo() {
850    /// # use zng_var::*;
851    /// # use zng_txt::*;
852    /// # use zng_unit::*;
853    /// let status = var(Txt::from("not animating"));
854    ///
855    /// status
856    ///     .animate(|animation, value| {
857    ///         let elapsed = animation.elapsed_dur();
858    ///         if elapsed < 5.secs() {
859    ///             value.set(formatx!("animating: elapsed {}ms", elapsed.as_millis()));
860    ///         } else {
861    ///             animation.stop();
862    ///             value.set("not animating");
863    ///         }
864    ///     })
865    ///     .perm();
866    /// # }
867    /// ```
868    ///
869    /// # Capabilities
870    ///
871    /// If the variable is always read-only no animation is created and a dummy handle returned.
872    ///
873    /// If this var is contextual the animation targets the current context var.
874    ///
875    /// The animation is stopped if this variable is dropped.
876    ///
877    /// [`Animation`]: Animation
878    pub fn animate(&self, mut animate: impl FnMut(&Animation, &mut VarModify<T>) + Send + 'static) -> AnimationHandle {
879        self.any.animate(move |a, v| animate(a, &mut v.downcast::<T>().unwrap()))
880    }
881
882    /// Schedule animations started by `animate`, the closure is called once at the start to begin, then again every time
883    /// the variable stops animating.
884    ///
885    /// This can be used to create a sequence of animations or to repeat an animation.
886    ///
887    /// # Examples
888    ///
889    /// Running multiple animations in sequence:
890    ///
891    /// ```
892    /// # fn demo() {
893    /// # use zng_var::{*, animation::*};
894    /// # use zng_txt::*;
895    /// # use zng_unit::*;
896    /// let status = var(Txt::from("not animating"));
897    ///
898    /// let mut stage = 0;
899    /// status
900    ///     .sequence(move |status| {
901    ///         stage += 1;
902    ///         if stage < 5 {
903    ///             status.animate(move |animation, value| {
904    ///                 let elapsed = animation.elapsed_stop(5.secs());
905    ///                 value.set(formatx!("animation {stage}: {}", elapsed.pct()));
906    ///             })
907    ///         } else {
908    ///             status.set("not animating");
909    ///             AnimationHandle::dummy()
910    ///         }
911    ///     })
912    ///     .perm();
913    /// # }
914    /// ```
915    ///
916    /// # Capabilities
917    ///
918    /// The sequence stops when `animate` returns a dummy handle, or the variable is modified outside of `animate`,
919    /// or animations are disabled, or the returned handle is dropped.
920    pub fn sequence(&self, mut animate: impl FnMut(Var<T>) -> AnimationHandle + Send + 'static) -> VarHandle {
921        self.any.sequence(move |v| animate(Var::new_any(v)))
922    }
923
924    /// Schedule an easing transition from the `start_value` to `end_value`.
925    ///
926    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
927    ///
928    /// # Examples
929    ///
930    /// Basic usage:
931    ///
932    /// ```
933    /// # fn demo() {
934    /// # use zng_var::{*, animation::easing};
935    /// # use zng_unit::*;
936    /// let progress = var(0.pct());
937    ///
938    /// progress.set_ease(0.pct(), 100.pct(), 5.secs(), easing::linear).perm();
939    /// # }
940    /// ```
941    ///
942    /// Variable is reset to 0% at the start and them transition to 100% in 5 seconds with linear progression.
943    ///
944    /// # Capabilities
945    ///
946    /// See [`animate`] for details about animation capabilities.
947    ///
948    /// [`animate`]: Self::animate
949    pub fn set_ease(
950        &self,
951        start_value: impl Into<T>,
952        end_value: impl Into<T>,
953        duration: Duration,
954        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
955    ) -> AnimationHandle
956    where
957        T: Transitionable,
958    {
959        self.set_ease_with(start_value, end_value, duration, easing, Transition::sample)
960    }
961
962    /// Oscillate between `start_value` to `end_value` with an easing transition.
963    ///
964    /// The `duration` defines the easing duration between the two values. The animation will continue running
965    /// until the handle or the variable is dropped.
966    ///
967    /// Note that you can use [`sequence`] to create more complex looping animations.
968    ///
969    /// [`sequence`]: Var::sequence
970    pub fn set_ease_oci(
971        &self,
972        start_value: impl Into<T>,
973        end_value: impl Into<T>,
974        duration: Duration,
975        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
976    ) -> AnimationHandle
977    where
978        T: Transitionable,
979    {
980        self.set_ease_oci_with(start_value, end_value, duration, easing, Transition::sample)
981    }
982
983    /// Schedule an easing transition from the `start_value` to `end_value` using a custom value sampler.
984    ///
985    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
986    ///
987    /// See [`animate`] for details about animation capabilities.
988    ///
989    /// [`animate`]: Self::animate
990    pub fn set_ease_with(
991        &self,
992        start_value: impl Into<T>,
993        end_value: impl Into<T>,
994        duration: Duration,
995        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
996        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
997    ) -> AnimationHandle
998    where
999        T: Transitionable,
1000    {
1001        self.ease_impl(start_value.into(), end_value.into(), duration, easing, 999.fct(), sampler)
1002    }
1003
1004    /// Oscillate between `start_value` to `end_value` with an easing transition using a custom value sampler.
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`]: Self::sequence
1011    pub fn set_ease_oci_with(
1012        &self,
1013        start_value: impl Into<T>,
1014        end_value: impl Into<T>,
1015        duration: Duration,
1016        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1017        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
1018    ) -> AnimationHandle
1019    where
1020        T: Transitionable,
1021    {
1022        self.ease_oci_impl(start_value.into(), end_value.into(), duration, easing, 999.fct(), sampler)
1023    }
1024
1025    /// Schedule an easing transition from the current value to `new_value`.
1026    ///
1027    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
1028    ///
1029    /// See [`animate`] for details about animation capabilities.
1030    ///
1031    /// [`animate`]: Var::animate
1032    pub fn ease(
1033        &self,
1034        new_value: impl Into<T>,
1035        duration: Duration,
1036        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1037    ) -> AnimationHandle
1038    where
1039        T: Transitionable,
1040    {
1041        self.ease_with(new_value, duration, easing, Transition::sample)
1042    }
1043
1044    /// Oscillate between the current value and `new_value` with an easing transition.
1045    ///
1046    /// The `duration` defines the easing duration between the two values.
1047    ///
1048    /// Note that you can use [`sequence`] to create more complex looping animations.
1049    ///
1050    /// [`sequence`]: Var::sequence
1051    pub fn ease_oci(
1052        &self,
1053        new_value: impl Into<T>,
1054        duration: Duration,
1055        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1056    ) -> AnimationHandle
1057    where
1058        T: Transitionable,
1059    {
1060        self.ease_oci_with(new_value, duration, easing, Transition::sample)
1061    }
1062
1063    /// Schedule an easing transition from the current value to `new_value` using a custom value sampler.
1064    ///
1065    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
1066    ///
1067    /// See [`animate`] for details about animation capabilities.
1068    ///
1069    /// [`animate`]: Var::animate
1070    pub fn ease_with(
1071        &self,
1072        new_value: impl Into<T>,
1073        duration: Duration,
1074        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1075        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
1076    ) -> AnimationHandle
1077    where
1078        T: Transitionable,
1079    {
1080        self.ease_impl(self.get(), new_value.into(), duration, easing, 0.fct(), sampler)
1081    }
1082
1083    /// Oscillate between the current value and `new_value` with an easing transition and a custom value sampler.
1084    ///
1085    /// The `duration` defines the easing duration between the two values.
1086    ///
1087    /// Note that you can use [`sequence`] to create more complex looping animations.
1088    ///
1089    /// [`sequence`]: Self::sequence
1090    pub fn ease_oci_with(
1091        &self,
1092        new_value: impl Into<T>,
1093        duration: Duration,
1094        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1095        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
1096    ) -> AnimationHandle
1097    where
1098        T: Transitionable,
1099    {
1100        self.ease_oci_impl(self.get(), new_value.into(), duration, easing, 0.fct(), sampler)
1101    }
1102
1103    /// Schedule a keyframed transition animation for the variable, starting from the first key.
1104    ///
1105    /// The variable will be set to the first keyframe, then animated across all other keys.
1106    ///
1107    /// See [`animate`] for details about animations.
1108    ///
1109    /// [`animate`]: Self::animate
1110    pub fn set_ease_keyed(
1111        &self,
1112        keys: Vec<(Factor, T)>,
1113        duration: Duration,
1114        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1115    ) -> AnimationHandle
1116    where
1117        T: Transitionable,
1118    {
1119        self.set_ease_keyed_with(keys, duration, easing, TransitionKeyed::sample)
1120    }
1121
1122    /// Schedule a keyframed transition animation for the variable, starting from the first key, using a custom value sampler.
1123    ///
1124    /// The variable will be set to the first keyframe, then animated across all other keys.
1125    ///
1126    /// See [`animate`] for details about animations.
1127    ///
1128    /// [`animate`]: Self::animate
1129    pub fn set_ease_keyed_with(
1130        &self,
1131        keys: Vec<(Factor, T)>,
1132        duration: Duration,
1133        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1134        sampler: impl Fn(&TransitionKeyed<T>, EasingStep) -> T + Send + 'static,
1135    ) -> AnimationHandle
1136    where
1137        T: Transitionable,
1138    {
1139        if let Some(transition) = TransitionKeyed::new(keys) {
1140            self.ease_keyed_impl(transition, duration, easing, 999.fct(), sampler)
1141        } else {
1142            AnimationHandle::dummy()
1143        }
1144    }
1145
1146    /// Schedule a keyframed transition animation for the variable, starting from the current value.
1147    ///
1148    /// The variable will be set to the first keyframe, then animated across all other keys.
1149    ///
1150    /// See [`animate`] for details about animations.
1151    ///
1152    /// [`animate`]: Self::animate
1153    pub fn ease_keyed(
1154        &self,
1155        keys: Vec<(Factor, T)>,
1156        duration: Duration,
1157        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1158    ) -> AnimationHandle
1159    where
1160        T: Transitionable,
1161    {
1162        self.ease_keyed_with(keys, duration, easing, TransitionKeyed::sample)
1163    }
1164
1165    /// Schedule a keyframed transition animation for the variable, starting from the current value, using a custom value sampler.
1166    ///
1167    /// The variable will be set to the first keyframe, then animated across all other keys.
1168    ///
1169    /// See [`animate`] for details about animations.
1170    ///
1171    /// [`animate`]: Self::animate
1172    pub fn ease_keyed_with(
1173        &self,
1174        mut keys: Vec<(Factor, T)>,
1175        duration: Duration,
1176        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1177        sampler: impl Fn(&TransitionKeyed<T>, EasingStep) -> T + Send + 'static,
1178    ) -> AnimationHandle
1179    where
1180        T: Transitionable,
1181    {
1182        keys.insert(0, (0.fct(), self.get()));
1183
1184        let transition = TransitionKeyed::new(keys).unwrap();
1185        self.ease_keyed_impl(transition, duration, easing, 0.fct(), sampler)
1186    }
1187
1188    /// Set the variable to `new_value` after a `delay`.
1189    ///
1190    /// The variable [`is_animating`] until the delay elapses and the value is set.
1191    ///
1192    /// See [`animate`] for details about animations.
1193    ///
1194    /// [`is_animating`]: AnyVar::is_animating
1195    /// [`animate`]: Self::animate
1196    pub fn step(&self, new_value: impl Into<T>, delay: Duration) -> AnimationHandle {
1197        self.step_impl(new_value.into(), delay)
1198    }
1199
1200    /// Oscillate between the current value and `new_value`, every time the `delay` elapses the variable is set to the next value.
1201    pub fn step_oci(&self, new_value: impl Into<T>, delay: Duration) -> AnimationHandle {
1202        self.step_oci_impl([self.get(), new_value.into()], delay, false)
1203    }
1204
1205    /// Oscillate between `from` and `to`, the variable is set to `from` to start and every time the `delay` elapses
1206    /// the variable is set to the next value.
1207    pub fn set_step_oci(&self, from: impl Into<T>, to: impl Into<T>, delay: Duration) -> AnimationHandle {
1208        self.step_oci_impl([from.into(), to.into()], delay, true)
1209    }
1210
1211    /// Set the variable to a sequence of values as a time `duration` elapses.
1212    ///
1213    /// An animation curve is used to find the first factor in `steps` above or at the curve line at the current time,
1214    /// the variable is set to this step value, continuing animating across the next steps until the last or the animation end.
1215    /// The variable [`is_animating`] from the start, even if no step applies and stays *animating* until the last *step* applies
1216    /// or the duration is reached.
1217    ///
1218    /// # Examples
1219    ///
1220    /// Creates a variable that outputs text every 5% of a 5 seconds animation, advanced linearly.
1221    ///
1222    /// ```
1223    /// # use zng_var::{*, animation::easing};
1224    /// # use zng_txt::*;
1225    /// # use zng_unit::*;
1226    /// # fn demo(text_var: Var<Txt>) {
1227    /// let steps = (0..=100).step_by(5).map(|i| (i.pct().fct(), formatx!("{i}%"))).collect();
1228    /// # let _ =
1229    /// text_var.steps(steps, 5.secs(), easing::linear)
1230    /// # ;}
1231    /// ```
1232    ///
1233    /// The variable is set to `"0%"`, after 5% of the `duration` elapses it is set to `"5%"` and so on
1234    /// until the value is set to `"100%` at the end of the animation.
1235    ///
1236    /// Returns an [`AnimationHandle`]. See [`Var::animate`] for details about animations.
1237    ///
1238    /// [`is_animating`]: AnyVar::is_animating
1239    /// [`AnimationHandle`]: crate::animation::AnimationHandle
1240    pub fn steps(
1241        &self,
1242        steps: Vec<(Factor, T)>,
1243        duration: Duration,
1244        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1245    ) -> AnimationHandle {
1246        let mut prev_step = 999.fct();
1247        self.animate(move |a, vm| {
1248            let step = easing(a.elapsed_stop(duration));
1249            if step != prev_step {
1250                prev_step = step;
1251                if let Some(val) = steps.iter().find(|(f, _)| *f >= step).map(|(_, step)| step.clone()) {
1252                    vm.set(val);
1253                }
1254            }
1255        })
1256    }
1257
1258    /// Starts an easing animation that *chases* a target value that can be changed using the [`ChaseAnimation<T>`] handle.
1259    pub fn chase(
1260        &self,
1261        first_target: impl Into<T>,
1262        duration: Duration,
1263        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1264    ) -> ChaseAnimation<T>
1265    where
1266        T: Transitionable,
1267    {
1268        self.chase_impl(first_target.into(), duration, easing)
1269    }
1270    fn chase_impl(
1271        &self,
1272        first_target: T,
1273        duration: Duration,
1274        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1275    ) -> ChaseAnimation<T>
1276    where
1277        T: Transitionable,
1278    {
1279        ChaseAnimation {
1280            handle: self.ease(first_target.clone(), duration, easing),
1281            target: first_target,
1282            var: self.current_context(),
1283        }
1284    }
1285
1286    /// Start a [`chase`] animation without a first target.
1287    ///
1288    /// Use [`ChaseAnimation<T>::set`] to set the first chase target.
1289    ///
1290    /// [`chase`]: Self::chase
1291    pub fn chase_begin(&self) -> ChaseAnimation<T>
1292    where
1293        T: Transitionable,
1294    {
1295        ChaseAnimation {
1296            handle: AnimationHandle::dummy(),
1297            target: self.get(),
1298            var: self.current_context(),
1299        }
1300    }
1301
1302    /// Create a vars that [`ease`] to each new value of `self`.
1303    ///
1304    /// Note that the mapping var can be [contextualized], see [`map`] for more details.
1305    ///
1306    /// If `self` can change the output variable will keep it alive.
1307    ///
1308    /// [contextualized]: crate::contextual_var
1309    /// [`ease`]: Var::ease
1310    /// [`map`]: Var::map
1311    pub fn easing(&self, duration: Duration, easing: impl Fn(EasingTime) -> EasingStep + Send + Sync + 'static) -> Var<T>
1312    where
1313        T: Transitionable,
1314    {
1315        self.easing_with(duration, easing, Transition::sample)
1316    }
1317
1318    /// Create a vars that [`ease_with`] to each new value of `self`.
1319    ///
1320    /// Note that the mapping var can be contextualized, see [`map`] for more details.
1321    /// If `self` is shared the output variable will hold a strong reference to it.
1322    ///
1323    /// [`ease_with`]: Var::ease_with
1324    /// [`map`]: Var::map
1325    pub fn easing_with(
1326        &self,
1327        duration: Duration,
1328        easing: impl Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
1329        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + Sync + 'static,
1330    ) -> Var<T>
1331    where
1332        T: Transitionable,
1333    {
1334        let caps = self.capabilities();
1335        if caps.is_const() {
1336            return self.clone();
1337        }
1338
1339        let fns = Arc::new((easing, sampler));
1340
1341        if caps.is_contextual() {
1342            let me = self.clone();
1343            return contextual_var(move || me.clone().easing_with_tail(duration, fns.clone()));
1344        }
1345
1346        self.easing_with_tail(duration, fns)
1347    }
1348    // to avoid infinite closure type (contextual case)
1349    fn easing_with_tail(
1350        &self,
1351        duration: Duration,
1352        fns: Arc<(
1353            impl Fn(EasingTime) -> Factor + Send + Sync + 'static,
1354            impl Fn(&Transition<T>, Factor) -> T + Send + Sync + 'static,
1355        )>,
1356    ) -> Var<T>
1357    where
1358        T: Transitionable,
1359    {
1360        let me = self.current_context();
1361
1362        let output = crate::var(me.get());
1363
1364        let weak_output = output.downgrade();
1365        let mut _ease_handle = AnimationHandle::dummy();
1366        me.hook(move |args| {
1367            if let Some(output) = weak_output.upgrade() {
1368                _ease_handle = output.ease_with(
1369                    args.value().clone(),
1370                    duration,
1371                    clmv!(fns, |t| fns.0(t)),
1372                    clmv!(fns, |t, s| fns.1(t, s)),
1373                );
1374                true
1375            } else {
1376                false
1377            }
1378        })
1379        .perm();
1380        output.hold(me).perm();
1381
1382        output.read_only()
1383    }
1384
1385    fn ease_impl(
1386        &self,
1387        start_value: T,
1388        end_value: T,
1389        duration: Duration,
1390        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1391        init_step: Factor, // set to 0 skips first frame, set to 999 includes first frame.
1392        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
1393    ) -> AnimationHandle
1394    where
1395        T: Transitionable,
1396    {
1397        let transition = Transition::new(start_value, end_value);
1398        let mut prev_step = init_step;
1399        self.animate(move |a, vm| {
1400            let step = easing(a.elapsed_stop(duration));
1401
1402            if prev_step != step {
1403                vm.set(sampler(&transition, step));
1404                prev_step = step;
1405            }
1406        })
1407    }
1408
1409    fn ease_oci_impl(
1410        &self,
1411        start_value: T,
1412        end_value: T,
1413        duration: Duration,
1414        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1415        init_step: EasingStep, // set to 0 skips first frame, set to 999 includes first frame.
1416        sampler: impl Fn(&Transition<T>, EasingStep) -> T + Send + 'static,
1417    ) -> AnimationHandle
1418    where
1419        T: Transitionable,
1420    {
1421        let transition = Transition::new(start_value, end_value);
1422        let mut prev_step = init_step;
1423        self.animate(move |a, vm| {
1424            let t = a.elapsed(duration);
1425            let mut step = easing(t);
1426            if a.count() % 2 != 0 {
1427                step = step.flip()
1428            }
1429            if t.is_end() {
1430                a.restart();
1431            }
1432
1433            if prev_step != step {
1434                vm.set(sampler(&transition, step));
1435                prev_step = step;
1436            }
1437        })
1438    }
1439
1440    fn ease_keyed_impl(
1441        &self,
1442        transition: TransitionKeyed<T>,
1443        duration: Duration,
1444        easing: impl Fn(EasingTime) -> EasingStep + Send + 'static,
1445        init_step: EasingStep,
1446        sampler: impl Fn(&TransitionKeyed<T>, EasingStep) -> T + Send + 'static,
1447    ) -> AnimationHandle
1448    where
1449        T: Transitionable,
1450    {
1451        let mut prev_step = init_step;
1452        self.animate(move |a, value| {
1453            let step = easing(a.elapsed_stop(duration));
1454
1455            if prev_step != step {
1456                value.set(sampler(&transition, step));
1457                prev_step = step;
1458            }
1459        })
1460    }
1461
1462    fn step_impl(&self, new_value: T, delay: Duration) -> AnimationHandle {
1463        let mut new_value = Some(new_value);
1464        self.animate(move |a, vm| {
1465            if !a.animations_enabled() || a.elapsed_dur() >= delay {
1466                a.stop();
1467                if let Some(nv) = new_value.take() {
1468                    vm.set(nv);
1469                }
1470            } else {
1471                a.sleep(delay, false);
1472            }
1473        })
1474    }
1475
1476    fn step_oci_impl(&self, values: [T; 2], delay: Duration, mut set: bool) -> AnimationHandle {
1477        let mut first = false;
1478        self.animate(move |a, vm| {
1479            if !a.animations_enabled() || std::mem::take(&mut set) {
1480                vm.set(values[0].clone());
1481            } else if a.elapsed_dur() >= delay {
1482                if first {
1483                    vm.set(values[0].clone());
1484                } else {
1485                    vm.set(values[1].clone());
1486                }
1487                first = !first;
1488            }
1489            a.sleep(delay, false);
1490        })
1491    }
1492}
1493/// Transition animations
1494impl<T: VarValue + Transitionable> Var<T> {}
1495/// Value type.
1496impl<T: VarValue> Var<T> {
1497    /// Reference the variable without the strong value type.
1498    pub fn as_any(&self) -> &AnyVar {
1499        &self.any
1500    }
1501}
1502/// Variable type.
1503impl<T: VarValue> Var<T> {
1504    /// Create a weak reference to this variable.
1505    pub fn downgrade(&self) -> WeakVar<T> {
1506        WeakVar {
1507            any: self.any.downgrade(),
1508            _t: PhantomData,
1509        }
1510    }
1511
1512    /// Gets a clone of the var that is always read-only.
1513    ///
1514    /// The returned variable can still update if `self` is modified, but it does not have the `MODIFY` capability.
1515    pub fn read_only(&self) -> Var<T> {
1516        Var::new_any(self.any.read_only())
1517    }
1518
1519    /// Create a var that redirects to this variable until the first value update, then it disconnects as a separate variable.
1520    ///
1521    /// The return variable is *clone-on-write* and has the `MODIFY` capability independent of the source capabilities, when
1522    /// a modify request is made the source value is cloned and offered for modification, if modified the source variable is dropped,
1523    /// if the modify closure does not update the source variable is retained.
1524    pub fn cow(&self) -> Var<T> {
1525        Var::new_any(self.any.cow())
1526    }
1527
1528    /// Gets the underlying var in the current calling context.
1529    ///
1530    /// If this variable is [`CONTEXT`] returns a clone of the inner variable,
1531    /// otherwise returns a clone of this variable.
1532    ///
1533    /// [`CONTEXT`]: crate::VarCapability::CONTEXT
1534    pub fn current_context(&self) -> Var<T> {
1535        Var::new_any(self.any.current_context())
1536    }
1537
1538    /// Gets if this variable is the same as `other`.
1539    ///
1540    /// If this variable is [`SHARE`] compares the *pointer*. If this variable is local this is always `false`.
1541    ///
1542    /// [`SHARE`]: crate::VarCapability::SHARE
1543    pub fn var_eq(&self, other: &Self) -> bool {
1544        self.any.var_eq(&other.any)
1545    }
1546}
1547
1548/// Weak reference to a [`Var<T>`].
1549pub struct WeakVar<T: VarValue> {
1550    any: WeakAnyVar,
1551    _t: PhantomData<T>,
1552}
1553impl<T: VarValue> fmt::Debug for WeakVar<T> {
1554    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1555        f.debug_tuple("WeakVar").field(&self.any.0).finish()
1556    }
1557}
1558impl<T: VarValue> Clone for WeakVar<T> {
1559    fn clone(&self) -> Self {
1560        Self {
1561            any: self.any.clone(),
1562            _t: PhantomData,
1563        }
1564    }
1565}
1566impl<T: VarValue> From<WeakVar<T>> for WeakAnyVar {
1567    fn from(var: WeakVar<T>) -> Self {
1568        var.any
1569    }
1570}
1571impl<T: VarValue> ops::Deref for WeakVar<T> {
1572    type Target = WeakAnyVar;
1573
1574    fn deref(&self) -> &Self::Target {
1575        self.as_any()
1576    }
1577}
1578impl<T: VarValue> WeakVar<T> {
1579    /// Reference the weak variable without the strong value type.
1580    pub fn as_any(&self) -> &WeakAnyVar {
1581        &self.any
1582    }
1583
1584    /// Attempt to create a strong reference to the variable.
1585    pub fn upgrade(&self) -> Option<Var<T>> {
1586        self.any.upgrade().map(Var::new_any)
1587    }
1588
1589    /// New weak var that does not upgrade.
1590    pub const fn new() -> Self {
1591        Self {
1592            any: WeakAnyVar::new(),
1593            _t: PhantomData,
1594        }
1595    }
1596}
1597impl<T: VarValue> Default for WeakVar<T> {
1598    fn default() -> Self {
1599        Self::new()
1600    }
1601}
1602
1603/// New read/write shared reference variable from any type that can convert into it.
1604pub fn var_from<T: VarValue>(initial_value: impl Into<T>) -> Var<T> {
1605    crate::var(initial_value.into())
1606}
1607
1608/// New read/write shared reference variable with default initial value.
1609pub fn var_default<T: VarValue + Default>() -> Var<T> {
1610    crate::var(T::default())
1611}
1612
1613/// New immutable variable that stores the `value` directly.
1614///
1615/// Cloning this variable clones the value.
1616pub fn const_var<T: VarValue>(value: T) -> Var<T> {
1617    Var::new_any(any_const_var(BoxAnyVarValue::new(value)))
1618}
1619
1620/// Type erased [`const_var`].
1621pub fn any_const_var(value: BoxAnyVarValue) -> AnyVar {
1622    AnyVar(crate::DynAnyVar::Const(crate::var_impl::const_var::ConstVar::new(value)))
1623}
1624
1625/// Weak variable that never upgrades.
1626pub fn weak_var<T: VarValue>() -> WeakVar<T> {
1627    WeakVar {
1628        any: weak_var_any(),
1629        _t: PhantomData,
1630    }
1631}
1632
1633/// Weak variable that never upgrades.
1634pub fn weak_var_any() -> WeakAnyVar {
1635    WeakAnyVar(crate::DynWeakAnyVar::Const(crate::var_impl::const_var::WeakConstVar))
1636}
1637
1638/// Arguments for [`Var::hook`].
1639pub struct VarHookArgs<'a, T: VarValue> {
1640    pub(super) any: &'a AnyVarHookArgs<'a>,
1641    pub(super) _t: PhantomData<&'a T>,
1642}
1643impl<'a, T: VarValue> VarHookArgs<'a, T> {
1644    /// Reference the updated value.
1645    pub fn value(&self) -> &'a T {
1646        self.any.value.downcast_ref::<T>().unwrap()
1647    }
1648}
1649impl<'a, T: VarValue> ops::Deref for VarHookArgs<'a, T> {
1650    type Target = AnyVarHookArgs<'a>;
1651
1652    fn deref(&self) -> &Self::Target {
1653        self.any
1654    }
1655}