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