zng_var/
lib.rs

1#![doc(html_favicon_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo-icon.png")]
2#![doc(html_logo_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo.png")]
3//!
4//! Batch updated variables in an app context.
5//!
6//! # Crate
7//!
8#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
9// suppress nag about very simple boxed closure signatures.
10#![expect(clippy::type_complexity)]
11#![warn(unused_extern_crates)]
12#![warn(missing_docs)]
13#![deny(clippy::future_not_send)]
14
15use animation::{
16    Transitionable,
17    easing::{EasingStep, EasingTime},
18};
19use bitflags::bitflags;
20use parking_lot::Mutex;
21use std::{
22    any::{Any, TypeId},
23    borrow::Cow,
24    fmt,
25    marker::PhantomData,
26    ops,
27    sync::{
28        Arc,
29        atomic::{AtomicBool, Ordering::Relaxed},
30    },
31    time::Duration,
32};
33use zng_app_context::{AppLocalId, ContextLocal};
34use zng_clone_move::clmv;
35use zng_txt::{ToTxt, Txt, formatx};
36use zng_unit::{Factor, FactorUnits};
37
38pub mod animation;
39mod arc;
40mod boxed;
41mod impls;
42
43mod context;
44mod contextualized;
45mod cow;
46mod expr;
47mod flat_map;
48mod future;
49mod local;
50mod map_ref;
51mod merge;
52mod read_only;
53mod response;
54mod vars;
55mod vec;
56mod when;
57
58#[macro_use]
59mod util;
60
61pub use arc::{ArcVar, getter_var, state_var, var, var_default, var_from};
62pub use boxed::{BoxedAnyVar, BoxedAnyWeakVar, BoxedVar, BoxedWeakVar};
63#[doc(inline)]
64pub use context::{ContextInitHandle, ContextVar, ReadOnlyContextVar};
65pub use local::LocalVar;
66#[doc(inline)]
67pub use merge::MergeVarBuilder;
68pub use read_only::ReadOnlyArcVar;
69pub use response::{ResponderVar, ResponseVar, response_done_var, response_var};
70pub use vars::*;
71pub use vec::ObservableVec;
72
73/// Other variable types.
74pub mod types {
75    use std::marker::PhantomData;
76
77    #[doc(hidden)]
78    pub use zng_app_context::context_local;
79
80    pub use impls::*;
81
82    pub use super::arc::WeakArcVar;
83    pub use super::boxed::{VarBoxed, WeakVarBoxed};
84    pub use super::context::{WeakContextInitHandle, context_var_init};
85    pub use super::contextualized::{ContextualizedVar, WeakContextualizedVar};
86    pub use super::cow::{ArcCowVar, WeakCowVar};
87    pub use super::expr::{__expr_var, expr_var_as, expr_var_into, expr_var_map};
88    pub use super::flat_map::{ArcFlatMapVar, WeakFlatMapVar};
89    pub use super::map_ref::{MapRef, MapRefBidi, WeakMapRef, WeakMapRefBidi};
90    pub use super::merge::{__merge_var, ArcMergeVar, ArcMergeVarInput, MergeVarInputs, WeakMergeVar};
91    pub use super::read_only::{ReadOnlyVar, WeakReadOnlyVar};
92    pub use super::response::Response;
93    pub use super::vec::VecChange;
94    pub use super::when::{__when_var, AnyWhenVarBuilder, ArcWhenVar, ContextualizedArcWhenVar, WeakWhenVar, WhenVarBuilder};
95
96    use super::*;
97
98    /// Identifies the source variable in another variable a value update.
99    ///
100    /// The [`Var::set_from`] and bidirectional map/binding methods use this tag to avoid an extra "map_back" caused by "map" itself.
101    ///
102    /// The tag is only equal to the same variable.
103    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
104    pub struct SourceVarTag(usize);
105    impl SourceVarTag {
106        /// Tag that identifies the `source` variable.
107        pub fn new(source: &impl AnyVar) -> Self {
108            SourceVarTag(source.var_ptr().raw_pointer() as _)
109        }
110    }
111
112    /// Helper type for debug printing [`Var<T>`].
113    ///
114    /// You can use [`Var::debug`] to get an instance.
115    pub struct VarDebug<'a, T: VarValue, V: Var<T>> {
116        pub(super) var: &'a V,
117        pub(super) _t: PhantomData<fn() -> T>,
118    }
119    impl<T: VarValue, V: Var<T>> fmt::Debug for VarDebug<'_, T, V> {
120        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121            self.var.with(|t| fmt::Debug::fmt(t, f))
122        }
123    }
124
125    /// Helper type for display printing [`Var<T>`].
126    ///
127    /// You can use [`Var::display`] to get an instance.
128    pub struct VarDisplay<'a, T: VarValue + fmt::Display, V: Var<T>> {
129        pub(super) var: &'a V,
130        pub(super) _t: PhantomData<fn() -> T>,
131    }
132    impl<T: VarValue + fmt::Display, V: Var<T>> fmt::Display for VarDisplay<'_, T, V> {
133        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134            self.var.with(|t| fmt::Display::fmt(t, f))
135        }
136    }
137}
138
139mod private {
140    // https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
141    pub trait Sealed {}
142}
143
144/// Represents a type that can be a [`Var<T>`] value.
145///
146/// # Trait Alias
147///
148/// This trait is used like a type alias for traits and is
149/// already implemented for all types it applies to.
150///
151/// # Implementing
152///
153/// Types need to be `Debug + Clone + PartialEq + Send + Sync + Any` to auto-implement this trait,
154/// if you want to place an external type in a variable and it does not implement all the traits
155/// you may need to declare a *newtype* wrapper, if the external type is `Debug + Send + Sync + Any` at
156/// least you can use the [`ArcEq<T>`] wrapper to quickly implement `Clone + PartialEq`, this is particularly
157/// useful for error types in [`ResponseVar<Result<_, E>>`].
158#[diagnostic::on_unimplemented(note = "`VarValue` is implemented for all `T: Debug + Clone + PartialEq + Any + Send + Sync`")]
159pub trait VarValue: fmt::Debug + Clone + PartialEq + Any + Send + Sync {}
160impl<T: fmt::Debug + Clone + PartialEq + Any + Send + Sync> VarValue for T {}
161
162/// Trait implemented for all [`VarValue`] types.
163pub trait AnyVarValue: fmt::Debug + Any + Send + Sync {
164    /// Access to `dyn Any` methods.
165    fn as_any(&self) -> &dyn Any;
166
167    /// Access to mut `dyn Any` methods.
168    fn as_any_mut(&mut self) -> &mut dyn Any;
169
170    /// Access to `Box<dyn Any>` methods.
171    fn into_any(self: Box<Self>) -> Box<dyn Any>;
172
173    /// Clone the value.
174    fn clone_boxed(&self) -> Box<dyn AnyVarValue>;
175
176    /// Clone the value into a new boxed [`LocalVar<Self>`].
177    fn clone_boxed_var(&self) -> BoxedAnyVar;
178
179    /// Gets if `self` equals `other`.
180    fn eq_any(&self, other: &dyn AnyVarValue) -> bool;
181}
182
183impl<T: VarValue> AnyVarValue for T {
184    fn as_any(&self) -> &dyn Any {
185        self
186    }
187
188    fn as_any_mut(&mut self) -> &mut dyn Any {
189        self
190    }
191
192    fn clone_boxed(&self) -> Box<dyn AnyVarValue> {
193        Box::new(self.clone())
194    }
195
196    fn clone_boxed_var(&self) -> BoxedAnyVar {
197        Box::new(LocalVar(self.clone()))
198    }
199
200    fn into_any(self: Box<Self>) -> Box<dyn Any> {
201        self
202    }
203
204    fn eq_any(&self, other: &dyn AnyVarValue) -> bool {
205        match other.as_any().downcast_ref::<T>() {
206            Some(v) => self == v,
207            None => false,
208        }
209    }
210}
211
212/// A property value that is not a variable but can be inspected.
213///
214/// # Implementing
215///
216/// The trait is only auto-implemented for `T: Into<T> + VarValue`, unfortunately actual type conversions
217/// must be manually implemented, note that the [`impl_from_and_into_var!`] macro auto-implements this conversion.
218///
219/// [`Debug`]: std::fmt::Debug
220/// [`impl_from_and_into_var`]: impl_from_and_into_var
221#[diagnostic::on_unimplemented(
222    note = "`IntoValue<T>` is implemented for all `T: VarValue`",
223    note = "you can use `impl_from_and_into_var!` to implement conversions"
224)]
225pub trait IntoValue<T: VarValue>: Into<T> {}
226impl<T: VarValue> IntoValue<T> for T {}
227
228bitflags! {
229    /// Kinds of interactions allowed by a [`Var<T>`] in the current update.
230    ///
231    /// You can get the current capabilities of a var by using the [`AnyVar::capabilities`] method.
232    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
233    pub struct VarCapability: u8 {
234        /// Var value can change.
235        ///
236        /// If this is set the [`AnyVar::is_new`] can be `true` in some updates, a variable can `NEW`
237        /// even if it cannot `MODIFY`, in this case the variable is a read-only wrapper on a read-write variable.
238        const NEW = 0b0000_0010;
239
240        /// Var can be modified.
241        ///
242        /// If this is set [`Var::modify`] always returns `Ok`, if this is set `NEW` is also set.
243        ///
244        /// Note that modify requests from inside overridden animations can still be ignored, see [`AnyVar::modify_importance`].
245        const MODIFY = 0b0000_0011;
246
247        /// Var capabilities can change.
248        ///
249        /// Var capabilities can only change in between app updates, just like the var value, but [`AnyVar::last_update`]
250        /// may not change when capability changes.
251        const CAPS_CHANGE = 0b1000_0000;
252    }
253}
254impl VarCapability {
255    /// Remove only the `MODIFY` flag without removing `NEW`.
256    pub fn as_read_only(self) -> Self {
257        Self::from_bits_truncate(self.bits() & 0b1111_1110)
258    }
259
260    /// If cannot `MODIFY` and is not `CAPS_CHANGE`.
261    pub fn is_always_read_only(self) -> bool {
262        !self.contains(Self::MODIFY) && !self.contains(Self::CAPS_CHANGE)
263    }
264
265    /// If cannot `NEW` and is not `CAPS_CHANGE`.
266    pub fn is_always_static(self) -> bool {
267        self.is_empty()
268    }
269
270    /// Has the `MODIFY` capability.
271    pub fn can_modify(self) -> bool {
272        self.contains(Self::MODIFY)
273    }
274}
275
276/// Error when an attempt to modify a variable without the [`MODIFY`] capability is made.
277///
278/// [`MODIFY`]: VarCapability::MODIFY
279#[derive(Debug, Clone, Copy)]
280#[non_exhaustive]
281pub struct VarIsReadOnlyError {
282    /// Variable capabilities when the request was made.
283    pub capabilities: VarCapability,
284}
285impl fmt::Display for VarIsReadOnlyError {
286    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
287        write!(f, "cannot modify variable")
288    }
289}
290impl std::error::Error for VarIsReadOnlyError {}
291
292struct VarHandleData {
293    perm: AtomicBool,
294    action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>,
295}
296
297/// Represents the var side of a [`VarHandle`].
298struct VarHook(Arc<VarHandleData>);
299impl VarHook {
300    /// Calls the handle action, returns `true` if the handle must be retained.
301    pub fn call(&self, args: &AnyVarHookArgs) -> bool {
302        self.is_alive() && (self.0.action)(args)
303    }
304
305    /// If the handle is still held or is permanent.
306    pub fn is_alive(&self) -> bool {
307        Arc::strong_count(&self.0) > 1 || self.0.perm.load(Relaxed)
308    }
309}
310
311/// Handle to a variable hook.
312///
313/// This can represent a widget subscriber, a var binding, var app handler or animation, dropping the handler stops
314/// the behavior it represents.
315#[derive(Clone)]
316#[must_use = "var handle stops the behavior it represents on drop"]
317pub struct VarHandle(Option<Arc<VarHandleData>>);
318impl VarHandle {
319    /// New handle, the `action` depends on the behavior the handle represents.
320    fn new(action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> (VarHandle, VarHook) {
321        let c = Arc::new(VarHandleData {
322            perm: AtomicBool::new(false),
323            action,
324        });
325        (VarHandle(Some(c.clone())), VarHook(c))
326    }
327
328    /// Handle to no variable.
329    pub fn dummy() -> Self {
330        VarHandle(None)
331    }
332
333    /// Returns `true` if the handle is a [`dummy`].
334    ///
335    /// [`dummy`]: VarHandle::dummy
336    pub fn is_dummy(&self) -> bool {
337        self.0.is_none()
338    }
339
340    /// Drop the handle without stopping the behavior it represents.
341    ///
342    /// Note that the behavior can still be stopped by dropping the involved variables.
343    pub fn perm(self) {
344        if let Some(s) = &self.0 {
345            s.perm.store(true, Relaxed);
346        }
347    }
348
349    /// Create a [`VarHandles`] collection with `self` and `other`.
350    pub fn with(self, other: Self) -> VarHandles {
351        [self, other].into()
352    }
353}
354impl PartialEq for VarHandle {
355    fn eq(&self, other: &Self) -> bool {
356        match (&self.0, &other.0) {
357            (None, None) => true,
358            (None, Some(_)) | (Some(_), None) => false,
359            (Some(a), Some(b)) => Arc::ptr_eq(a, b),
360        }
361    }
362}
363impl Eq for VarHandle {}
364impl std::hash::Hash for VarHandle {
365    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
366        let i = match &self.0 {
367            Some(rc) => Arc::as_ptr(rc) as usize,
368            None => 0,
369        };
370        state.write_usize(i);
371    }
372}
373impl fmt::Debug for VarHandle {
374    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
375        let i = match &self.0 {
376            Some(rc) => Arc::as_ptr(rc) as usize,
377            None => 0,
378        };
379        f.debug_tuple("VarHandle").field(&i).finish()
380    }
381}
382impl Default for VarHandle {
383    fn default() -> Self {
384        Self::dummy()
385    }
386}
387
388/// Represents a collection of var handles.
389#[must_use = "var handles stops the behavior they represents on drop"]
390#[derive(Clone, Default)]
391pub struct VarHandles(pub Vec<VarHandle>);
392impl VarHandles {
393    /// Empty collection.
394    pub const fn dummy() -> Self {
395        VarHandles(vec![])
396    }
397
398    /// Returns `true` if empty or all handles are dummy.
399    pub fn is_dummy(&self) -> bool {
400        self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
401    }
402
403    /// Drop all handles without stopping their behavior.
404    pub fn perm(self) {
405        for handle in self.0 {
406            handle.perm()
407        }
408    }
409
410    /// Add the `other` handle to the collection, if it is not dummy.
411    pub fn push(&mut self, other: VarHandle) -> &mut Self {
412        if !other.is_dummy() {
413            self.0.push(other);
414        }
415        self
416    }
417
418    /// Drop all handles.
419    pub fn clear(&mut self) {
420        self.0.clear()
421    }
422}
423impl FromIterator<VarHandle> for VarHandles {
424    fn from_iter<T: IntoIterator<Item = VarHandle>>(iter: T) -> Self {
425        VarHandles(iter.into_iter().filter(|h| !h.is_dummy()).collect())
426    }
427}
428impl<const N: usize> From<[VarHandle; N]> for VarHandles {
429    fn from(handles: [VarHandle; N]) -> Self {
430        handles.into_iter().collect()
431    }
432}
433impl Extend<VarHandle> for VarHandles {
434    fn extend<T: IntoIterator<Item = VarHandle>>(&mut self, iter: T) {
435        for handle in iter {
436            self.push(handle);
437        }
438    }
439}
440impl IntoIterator for VarHandles {
441    type Item = VarHandle;
442
443    type IntoIter = std::vec::IntoIter<VarHandle>;
444
445    fn into_iter(self) -> Self::IntoIter {
446        self.0.into_iter()
447    }
448}
449
450/// Arc value that implements equality by pointer comparison.
451///
452/// This type allows external types that are only `Debug + Send + Sync` to become
453/// a full [`VarValue`] to be allowed as a variable value.
454pub struct ArcEq<T: fmt::Debug + Send + Sync>(pub Arc<T>);
455impl<T: fmt::Debug + Send + Sync> ops::Deref for ArcEq<T> {
456    type Target = Arc<T>;
457
458    fn deref(&self) -> &Self::Target {
459        &self.0
460    }
461}
462impl<T: fmt::Debug + Send + Sync> ArcEq<T> {
463    /// Constructs a new `ArcEq<T>`.
464    pub fn new(value: T) -> Self {
465        Self(Arc::new(value))
466    }
467}
468impl<T: fmt::Debug + Send + Sync> PartialEq for ArcEq<T> {
469    fn eq(&self, other: &Self) -> bool {
470        Arc::ptr_eq(&self.0, &other.0)
471    }
472}
473impl<T: fmt::Debug + Send + Sync> Eq for ArcEq<T> {}
474impl<T: fmt::Debug + Send + Sync> Clone for ArcEq<T> {
475    fn clone(&self) -> Self {
476        Self(Arc::clone(&self.0))
477    }
478}
479impl<T: fmt::Debug + Send + Sync> fmt::Debug for ArcEq<T> {
480    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481        fmt::Debug::fmt(&*self.0, f)
482    }
483}
484
485/// Methods of [`Var<T>`] that are object safe.
486///
487/// This trait is [sealed] and cannot be implemented for types outside of this crate.
488///
489/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
490pub trait AnyVar: Any + Send + Sync + crate::private::Sealed {
491    /// Clone the variable into a type erased box.
492    ///
493    /// This is never [`BoxedVar<T>`], that is not a double box.
494    fn clone_any(&self) -> BoxedAnyVar;
495
496    /// Access to `dyn Any` methods.
497    fn as_any(&self) -> &dyn Any;
498
499    /// Access to `dyn Any` methods, on the underlying variable type if boxed.
500    fn as_unboxed_any(&self) -> &dyn Any;
501
502    /// Access to `Box<dyn Any>` methods, with the [`BoxedVar<T>`] type.
503    ///
504    /// This is a double-boxed to allow downcast to [`BoxedVar<T>`].
505    fn double_boxed_any(self: Box<Self>) -> Box<dyn Any>;
506
507    /// Gets the [`TypeId`] of `T` in `Var<T>`.
508    fn var_type_id(&self) -> TypeId;
509
510    /// Get a clone of the current value, with type erased.
511    fn get_any(&self) -> Box<dyn AnyVarValue>;
512
513    /// Visit the current value of the variable.
514    fn with_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue));
515
516    /// Visit the current value of the variable, if it [`is_new`].
517    ///
518    /// [`is_new`]: AnyVar::is_new
519    fn with_new_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) -> bool;
520
521    /// Schedule a new `value` for the variable, it will be set in the end of the current app update.
522    ///
523    /// # Panics
524    ///
525    /// Panics if the `value` is not of the same [`var_type_id`].
526    ///
527    /// [`var_type_id`]: AnyVar::var_type_id
528    fn set_any(&self, value: Box<dyn AnyVarValue>) -> Result<(), VarIsReadOnlyError>;
529
530    /// Last update ID a variable was modified, if the ID is equal to [`VARS.update_id`] the variable is *new*.
531    ///
532    /// [`VARS.update_id`]: VARS::update_id
533    fn last_update(&self) -> VarUpdateId;
534
535    /// If the variable represents different values depending on the context where they are read.
536    fn is_contextual(&self) -> bool;
537
538    /// Flags that indicate what operations the variable is capable of in this update.
539    fn capabilities(&self) -> VarCapability;
540
541    /// Gets if the [`last_update`] is the current update, meaning the variable value just changed.
542    ///
543    /// Note that this is only reliable in threads synchronized with the UI update, this status can change
544    /// at any time when called from other app threads.
545    ///
546    /// [`last_update`]: AnyVar::last_update
547    fn is_new(&self) -> bool {
548        VARS.update_id() == self.last_update()
549    }
550
551    /// If the variable current value was set by an active animation.
552    ///
553    /// The variable [`is_new`] when this changes to `true`, but it **may not be new** when the value changes to `false`.
554    /// If the variable is not updated at the last frame of the animation that has last set it, it will not update
555    /// just because that animation has ended. You can use [`hook_animation_stop`] to get a notification when the
556    /// last animation stops, or use [`wait_animation`] to get a future that is ready when `is_animating` changes
557    /// from `true` to `false`.
558    ///
559    /// [`is_new`]: AnyVar::is_new
560    /// [`hook_animation_stop`]: AnyVar::hook_animation_stop
561    /// [`wait_animation`]: Var::wait_animation
562    fn is_animating(&self) -> bool;
563
564    /// Gets a value that indicates the *importance* clearance that is needed to modify this variable.
565    ///
566    /// If the variable has the [`MODIFY`] capability, `modify` requests will return `Ok(())`, but they will be ignored
567    /// if the [`VARS.current_modify`] importance is less than the variable's at the moment the request is made.
568    ///
569    /// Note that [`VARS.current_modify`] outside animations always overrides this value, so direct modify requests
570    /// always override running animations.
571    ///
572    /// This is the mechanism that ensures that only the latest animation has *control* of the variable value, most animations
573    /// check this value and automatically cancel if overridden, but event assigns from custom animations made using [`VARS.animate`]
574    /// are ignored if the variable is modified from a newer source then the animation.
575    ///
576    /// If the variable does not have [`MODIFY`] capability the value returned is undefined.
577    ///
578    /// [`MODIFY`]: VarCapability::MODIFY
579    /// [`VARS.current_modify`]: VARS::current_modify
580    /// [`VARS.animate`]: VARS::animate
581    fn modify_importance(&self) -> usize;
582
583    /// Setups a callback for just after the variable value update is applied, the closure runs in the root app context, just like
584    /// the `modify` closure. The closure can return if it is retained after each call. If you modify another variable in a
585    /// hook the modification applies in the same update, variable mapping and binding is implemented using hooks.
586    ///
587    /// The variable store a weak reference to the callback if it has the `MODIFY` or `CAPS_CHANGE` capabilities, otherwise
588    /// the callback is discarded and [`VarHandle::dummy`] returned.
589    fn hook_any(&self, pos_modify_action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> VarHandle;
590
591    /// Register a `handler` to be called when the current animation stops.
592    ///
593    /// Note that the `handler` is owned by the animation, not the variable, it will only be called/dropped when the
594    /// animation stops.
595    ///
596    /// Returns the `handler` as an error if the variable is not animating. Note that if you are interacting
597    /// with the variable from a non-UI thread the variable can stops animating between checking [`is_animating`]
598    /// and registering the hook, in this case the `handler` will be returned as an error as well.
599    ///
600    /// [`modify_importance`]: AnyVar::modify_importance
601    /// [`is_animating`]: AnyVar::is_animating
602    fn hook_animation_stop(&self, handler: Box<dyn FnOnce() + Send>) -> Result<(), Box<dyn FnOnce() + Send>>;
603
604    /// Gets the number of strong references to the variable.
605    ///
606    /// This is the [`Arc::strong_count`] for *Arc* variables, the context var count for [`ContextVar<T>`], the boxed var count
607    /// for [`BoxedVar<T>`] and `0` for [`LocalVar<T>`].
608    fn strong_count(&self) -> usize;
609
610    /// Gets the number of weak references to the variable.
611    ///
612    /// This is the [`Arc::weak_count`] for *Arc* variables, the context var count for [`ContextVar<T>`], the boxed var count
613    /// for [`BoxedVar<T>`] and `0` for [`LocalVar<T>`].
614    fn weak_count(&self) -> usize;
615
616    /// Gets a clone of the represented var from [`ContextVar<T>`], gets a clone of `self` for other var types.
617    fn actual_var_any(&self) -> BoxedAnyVar;
618
619    /// Create a weak reference to this *Arc* variable.
620    ///
621    /// The weak reference is made to the [`actual_var`], if the actual var is a [`LocalVar<T>`]
622    /// a [`types::WeakArcVar<T>`] is returned, for *Arc* vars an actual weak reference is made.
623    ///
624    /// [`actual_var`]: Var::actual_var
625    fn downgrade_any(&self) -> BoxedAnyWeakVar;
626
627    /// Var *pointer*, that can be used to identify if two variables point to the same *rc* or *context*.
628    ///
629    /// If two of these values are equal, both variables point to the same *rc* or *context* at the moment of comparison.
630    /// Note that this is only for comparison, trying to access the variable internals is never safe.
631    fn var_ptr(&self) -> VarPtr<'_>;
632
633    /// Get the value as a debug [`Txt`].
634    ///
635    /// [`Txt`]: Txt
636    fn get_debug(&self) -> Txt;
637
638    /// Schedule a variable update, even if the value does no change.
639    ///
640    /// Usually variables only notify update if the value is changed to a different one, calling
641    /// this method flags the variable to notify.
642    fn update(&self) -> Result<(), VarIsReadOnlyError>;
643
644    /// Create a [`map`] that converts from `T` to a [`Txt`] debug print.
645    ///
646    /// [`map`]: Var::map
647    /// [`Txt`]: Txt
648    fn map_debug(&self) -> BoxedVar<Txt>;
649
650    /// Hold the variable in memory until the app exit.
651    fn perm(&self) {
652        VARS.perm(self.clone_any());
653    }
654
655    /// Keep `other` alive until the handle or `self` are dropped.
656    fn hold_any(&self, value: Box<dyn Any + Send + Sync>) -> VarHandle {
657        self.hook_any(hold_any_impl(value))
658    }
659}
660// separate function to avoid code bloat
661fn hold_any_impl(value: Box<dyn Any + Send + Sync>) -> Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync> {
662    Box::new(move |_| {
663        let _hold = &value;
664        true
665    })
666}
667
668#[derive(Debug)]
669enum VarPtrData {
670    Static(AppLocalId),
671    Arc(*const ()),
672    NeverEq,
673}
674impl PartialEq for VarPtrData {
675    fn eq(&self, other: &Self) -> bool {
676        match (self, other) {
677            (Self::Static(l0), Self::Static(r0)) => l0 == r0,
678            (Self::Arc(l0), Self::Arc(r0)) => l0 == r0,
679            _ => false,
680        }
681    }
682}
683
684/// Represents an [`AnyVar`] *pointer* that can be used for comparison.
685///
686/// If two of these values are equal, both variables point to the same *arc* or *context* at the moment of comparison.
687pub struct VarPtr<'a> {
688    _lt: std::marker::PhantomData<&'a ()>,
689    eq: VarPtrData,
690}
691impl<'a> VarPtr<'a> {
692    /// Gets the pointer.
693    ///
694    /// # Safety
695    ///
696    /// Trying to read or write values using this pointer is **never safe**.
697    ///
698    /// Trying to identify a variable using the raw pointer is only valid if you know the variable is still alive.
699    /// The variable could be dropped and new one allocated at the same address.
700    pub fn raw_pointer(&self) -> *const () {
701        match self.eq {
702            VarPtrData::Arc(p) => p,
703            VarPtrData::Static(p) => p.get() as *const (),
704            VarPtrData::NeverEq => std::ptr::null(),
705        }
706    }
707
708    fn new_arc<T: ?Sized>(rc: &'a Arc<T>) -> Self {
709        Self {
710            _lt: std::marker::PhantomData,
711            eq: VarPtrData::Arc(Arc::as_ptr(rc) as _),
712        }
713    }
714
715    fn new_ctx_local<T: Send + Sync>(tl: &'static ContextLocal<T>) -> Self {
716        Self {
717            _lt: std::marker::PhantomData,
718            eq: VarPtrData::Static(tl.id()),
719        }
720    }
721
722    fn new_never_eq(_: &'a impl Any) -> Self {
723        Self {
724            _lt: std::marker::PhantomData,
725            eq: VarPtrData::NeverEq,
726        }
727    }
728}
729impl PartialEq for VarPtr<'_> {
730    fn eq(&self, other: &Self) -> bool {
731        self.eq == other.eq
732    }
733}
734impl fmt::Debug for VarPtr<'_> {
735    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
736        if f.alternate() {
737            f.debug_tuple("VarPtr").field(&self.eq).finish()
738        } else {
739            fmt::Debug::fmt(&self.eq, f)
740        }
741    }
742}
743
744/// Represents a weak reference to an [`AnyVar`].
745pub trait AnyWeakVar: Any + Send + Sync + crate::private::Sealed {
746    /// Clone the weak reference.
747    fn clone_any(&self) -> BoxedAnyWeakVar;
748
749    /// Access to `dyn Any` methods.
750    fn as_any(&self) -> &dyn Any;
751
752    /// Gets the number of strong references to the variable.
753    ///
754    /// This is the same as [`AnyVar::strong_count`].
755    fn strong_count(&self) -> usize;
756
757    /// Gets the number of weak references to the variable.
758    ///
759    /// This is the same as [`AnyVar::weak_count`].
760    fn weak_count(&self) -> usize;
761
762    /// Upgrade to a strong [`AnyVar`] clone.
763    ///
764    /// Returns `None` if the [`strong_count`] is zero.
765    ///
766    /// [`strong_count`]: AnyWeakVar
767    fn upgrade_any(&self) -> Option<BoxedAnyVar>;
768}
769
770/// Represents a weak reference to a [`Var<T>`].
771pub trait WeakVar<T: VarValue>: AnyWeakVar + Clone {
772    /// Output of [`WeakVar::upgrade`].
773    type Upgrade: Var<T>;
774
775    /// Upgrade to a strong [`BoxedVar<T>`] clone.
776    ///
777    /// Returns `None` if the [`strong_count`] is zero.
778    ///
779    /// [`strong_count`]: AnyWeakVar
780    fn upgrade(&self) -> Option<Self::Upgrade>;
781
782    /// Gets the weak reference a as [`BoxedWeakVar<T>`], does not double box.
783    fn boxed(self) -> BoxedWeakVar<T>
784    where
785        Self: Sized,
786    {
787        Box::new(self)
788    }
789}
790
791/// A value-to-var conversion that consumes the value.
792///
793/// Every [`Var<T>`] implements this to convert to itself, every [`VarValue`] implements this to
794/// convert to a [`LocalVar<T>`].
795///
796/// This trait is used by most properties, it allows then to accept literal values, variables and context variables
797/// all with a single signature. Together with [`Var<T>`] this gives properties great flexibility of usage, at zero-cost. Widget
798/// `when` blocks also use [`IntoVar<T>`] to support *changing* the property value depending on the widget state.
799///
800/// Value types can also manually implement this to support a shorthand literal syntax for when they are used in properties,
801/// this converts the *shorthand value* like a tuple into the actual value type and wraps it into a variable, usually [`LocalVar`]
802/// too. They can implement the trait multiple times to support different shorthand syntaxes or different types in the shorthand
803/// value.
804#[diagnostic::on_unimplemented(
805    note = "`IntoVar<T>` is implemented for all `T: VarValue`",
806    note = "`IntoVar<T>` is implemented for all `V: Var<T>`"
807)]
808pub trait IntoVar<T: VarValue> {
809    /// Variable type that will wrap the `T` value.
810    ///
811    /// This is the [`LocalVar`] for most types or `Self` for variable types.
812    type Var: Var<T>;
813
814    /// Converts the source value into a var.
815    fn into_var(self) -> Self::Var;
816
817    /// Converts into [`BoxedVar<T>`].
818    ///
819    /// This method exists to help the type system infer the type in this scenario:
820    ///
821    /// ```
822    /// # use zng_var::*;
823    /// # let bar = true;
824    /// # let BAR_VAR = var(true);
825    /// #
826    /// fn foo(foo: impl IntoVar<bool>) { }
827    ///
828    /// foo(if bar {
829    ///     BAR_VAR.map(|b| !*b).boxed()
830    /// } else {
831    ///     true.into_boxed_var()
832    /// });
833    /// ```
834    ///
835    /// We need a `BoxedVar<bool>` to unify the input types that can be a `map` var or a `LocalVar<bool>`. Writing `true.into_var().boxed()`
836    /// causes the type inference to fail, requiring us to write `IntoVar::<bool>::into_var(true).boxed()`.
837    fn into_boxed_var(self) -> BoxedVar<T>
838    where
839        Self: Sized,
840    {
841        self.into_var().boxed()
842    }
843}
844
845/// Represents the current value in a [`Var::modify`] handler.
846pub struct VarModify<'a, T: VarValue> {
847    current_value: &'a T,
848    value: Cow<'a, T>,
849    update: bool,
850    tags: Vec<Box<dyn AnyVarValue>>,
851    custom_importance: Option<usize>,
852}
853impl<'a, T: VarValue> VarModify<'a, T> {
854    /// Replace the value.
855    ///
856    /// The variable will update if the new value is not equal to the previous after all modify closures apply.
857    pub fn set(&mut self, new_value: T) {
858        self.value = Cow::Owned(new_value);
859    }
860
861    /// Notify an update, even if the value does not actually change.
862    pub fn update(&mut self) {
863        self.update = true;
864    }
865
866    /// Returns a mutable reference for modification.
867    ///
868    /// Note that this clones the current value if this is the first modify closure requesting it.
869    ///
870    /// The variable will update if the new value is not equal to the previous after all modify closures apply.
871    pub fn to_mut(&mut self) -> &mut T {
872        self.value.to_mut()
873    }
874
875    /// Custom tags that will be shared with the var hooks if the value updates.
876    ///
877    /// The tags where set by previous modify closures or this one during this update cycle, so
878    /// tags can also be used to communicate between modify closures.
879    pub fn tags(&self) -> &[Box<dyn AnyVarValue>] {
880        &self.tags
881    }
882
883    /// Add a custom tag object that will be shared with the var hooks if the value updates.
884    pub fn push_tag(&mut self, tag: impl AnyVarValue) {
885        self.tags.push(Box::new(tag));
886    }
887
888    /// Add all custom tags.
889    pub fn push_tags(&mut self, tags: Vec<Box<dyn AnyVarValue>>) {
890        if self.tags.is_empty() {
891            self.tags = tags;
892        } else {
893            self.tags.extend(tags);
894        }
895    }
896
897    /// Sets a custom [`AnyVar::modify_importance`] value.
898    ///
899    /// Note that the modify info is already automatically set, using a custom value here
900    /// can easily break all future modify requests for this variable. The importance is set even if the
901    /// variable does not update (no actual value change or update request).
902    pub fn set_modify_importance(&mut self, importance: usize) {
903        self.custom_importance = Some(importance);
904    }
905
906    /// New from current value.
907    pub fn new(current_value: &'a T) -> Self {
908        Self {
909            current_value,
910            value: Cow::Borrowed(current_value),
911            update: false,
912            tags: vec![],
913            custom_importance: None,
914        }
915    }
916
917    /// Returns `(notify, new_value, update, tags, custom_importance)`.
918    pub fn finish(self) -> (bool, Option<T>, bool, Vec<Box<dyn AnyVarValue>>, Option<usize>) {
919        match self.value {
920            Cow::Borrowed(_) => {
921                if self.update {
922                    return (true, None, true, self.tags, self.custom_importance);
923                }
924            }
925            Cow::Owned(v) => {
926                if self.update || self.current_value != &v {
927                    return (true, Some(v), self.update, self.tags, self.custom_importance);
928                }
929            }
930        }
931        (false, None, false, vec![], self.custom_importance)
932    }
933}
934impl<T: VarValue> ops::Deref for VarModify<'_, T> {
935    type Target = T;
936
937    fn deref(&self) -> &Self::Target {
938        self.as_ref()
939    }
940}
941impl<T: VarValue> std::convert::AsRef<T> for VarModify<'_, T> {
942    fn as_ref(&self) -> &T {
943        &self.value
944    }
945}
946
947/// Arguments for [`AnyVar::hook_any`].
948pub struct AnyVarHookArgs<'a> {
949    value: &'a dyn AnyVarValue,
950    update: bool,
951    tags: &'a [Box<dyn AnyVarValue>],
952}
953impl<'a> AnyVarHookArgs<'a> {
954    /// New from updated value and custom tag.
955    pub fn new(value: &'a dyn AnyVarValue, update: bool, tags: &'a [Box<dyn AnyVarValue>]) -> Self {
956        Self { value, update, tags }
957    }
958
959    /// Reference the updated value.
960    pub fn value(&self) -> &'a dyn AnyVarValue {
961        self.value
962    }
963
964    /// If update was explicitly requested.
965    ///
966    /// Note that bindings/mappings propagate this update request.
967    pub fn update(&self) -> bool {
968        self.update
969    }
970
971    /// Value type ID.
972    pub fn value_type(&self) -> TypeId {
973        self.value.as_any().type_id()
974    }
975
976    /// Custom tag objects.
977    pub fn tags(&self) -> &[Box<dyn AnyVarValue>] {
978        self.tags
979    }
980
981    /// Clone the custom tag objects set by the code that updated the value.
982    pub fn tags_vec(&self) -> Vec<Box<dyn AnyVarValue>> {
983        self.tags.iter().map(|t| (*t).clone_boxed()).collect()
984    }
985
986    /// Reference the value, if it is of type `T`.
987    pub fn downcast_value<T: VarValue>(&self) -> Option<&T> {
988        self.value.as_any().downcast_ref()
989    }
990
991    /// Reference all custom tag values of type `T`.
992    pub fn downcast_tags<T: VarValue>(&self) -> impl Iterator<Item = &T> + '_ {
993        self.tags.iter().filter_map(|t| (*t).as_any().downcast_ref::<T>())
994    }
995
996    /// Try cast to strongly typed args.
997    pub fn as_strong<T: VarValue>(&self) -> Option<VarHookArgs<'_, T>> {
998        if TypeId::of::<T>() == self.value_type() {
999            Some(VarHookArgs {
1000                any: self,
1001                _t: PhantomData,
1002            })
1003        } else {
1004            None
1005        }
1006    }
1007}
1008
1009/// Arguments for [`Var::hook`].
1010pub struct VarHookArgs<'a, T: VarValue> {
1011    any: &'a AnyVarHookArgs<'a>,
1012    _t: PhantomData<&'a T>,
1013}
1014impl<'a, T: VarValue> VarHookArgs<'a, T> {
1015    /// Reference the updated value.
1016    pub fn value(&self) -> &'a T {
1017        self.any.value.as_any().downcast_ref::<T>().unwrap()
1018    }
1019}
1020impl<'a, T: VarValue> ops::Deref for VarHookArgs<'a, T> {
1021    type Target = AnyVarHookArgs<'a>;
1022
1023    fn deref(&self) -> &Self::Target {
1024        self.any
1025    }
1026}
1027
1028/// Args for [`Var::trace_value`].
1029pub struct TraceValueArgs<'a, T: VarValue> {
1030    args: &'a AnyVarHookArgs<'a>,
1031    _type: PhantomData<&'a T>,
1032}
1033impl<'a, T: VarValue> ops::Deref for TraceValueArgs<'a, T> {
1034    type Target = AnyVarHookArgs<'a>;
1035
1036    fn deref(&self) -> &Self::Target {
1037        self.args
1038    }
1039}
1040impl<'a, T: VarValue> TraceValueArgs<'a, T> {
1041    /// Strongly-typed reference to the new value.
1042    pub fn value(&self) -> &'a T {
1043        self.args.downcast_value::<T>().unwrap()
1044    }
1045}
1046
1047/// Represents an observable value.
1048///
1049/// Variable types can have different capabilities, all can provide a value, in some the value can update, some
1050/// are read-only others allow modifying the value. Variables can also be contextual, meaning they have a different
1051/// value depending on the context where they are used. This trait covers all these capabilities, together with
1052/// [`IntoVar<T>`] it enables properties to be very flexible on what input they accept.
1053///
1054/// See [`AnyVar`] for the object safe part of variables.
1055///
1056/// This trait is [sealed] and cannot be implemented for types outside of this crate.
1057///
1058/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
1059pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
1060    /// Output of [`Var::read_only`].
1061    type ReadOnly: Var<T>;
1062
1063    /// Output of [`Var::actual_var`].
1064    type ActualVar: Var<T>;
1065
1066    /// Output of [`Var::downgrade`].
1067    type Downgrade: WeakVar<T>;
1068
1069    /// Output of [`Var::map`].
1070    type Map<O: VarValue>: Var<O>;
1071
1072    /// Output of [`Var::map_bidi`].
1073    type MapBidi<O: VarValue>: Var<O>;
1074
1075    /// Output of [`Var::flat_map`].
1076    type FlatMap<O: VarValue, V: Var<O>>: Var<O>;
1077
1078    /// Output of [`Var::filter_map`].
1079    type FilterMap<O: VarValue>: Var<O>;
1080
1081    /// Output of [`Var::filter_map_bidi`].
1082    type FilterMapBidi<O: VarValue>: Var<O>;
1083
1084    /// Output of [`Var::map_ref`].
1085    type MapRef<O: VarValue>: Var<O>;
1086
1087    /// Output of [`Var::map_ref_bidi`].
1088    type MapRefBidi<O: VarValue>: Var<O>;
1089
1090    /// Output of [`Var::easing`].
1091    type Easing: Var<T>;
1092
1093    /// Visit the current value of the variable.
1094    fn with<R, F>(&self, read: F) -> R
1095    where
1096        F: FnOnce(&T) -> R;
1097
1098    /// Schedule a variable update, it will be applied on the end of the current app update.
1099    fn modify<F>(&self, modify: F) -> Result<(), VarIsReadOnlyError>
1100    where
1101        F: FnOnce(&mut VarModify<T>) + Send + 'static;
1102
1103    /// Gets the variable as a [`BoxedVar<T>`], does not double box.
1104    fn boxed(self) -> BoxedVar<T>
1105    where
1106        Self: Sized,
1107    {
1108        Box::new(self)
1109    }
1110
1111    /// Gets the variable as a [`BoxedAnyVar`], does not double box.
1112    fn boxed_any(self) -> BoxedAnyVar
1113    where
1114        Self: Sized,
1115    {
1116        Box::new(self)
1117    }
1118
1119    /// Gets the current *inner* var represented by this var. This can be the same var or a context var.
1120    fn actual_var(self) -> Self::ActualVar;
1121
1122    /// Create a weak reference to this *Arc* variable.
1123    fn downgrade(&self) -> Self::Downgrade;
1124
1125    /// Convert this variable to the value, if possible moves the value, if it is shared clones it.
1126    fn into_value(self) -> T;
1127
1128    /// Gets a clone of the var that is always read-only.
1129    ///
1130    /// The returned variable can still update if `self` is modified, but it does not have the `MODIFY` capability.
1131    fn read_only(&self) -> Self::ReadOnly;
1132
1133    /// Setups a callback for just after the variable value update is applied, the closure runs in the root app context, just like
1134    /// the `modify` closure. The closure can return if it is retained after each call. If you modify another variable in a
1135    /// hook the modification applies in the same update, variable mapping and binding is implemented using hooks.
1136    ///
1137    /// The variable store a weak reference to the callback if it has the `MODIFY` or `CAPS_CHANGE` capabilities, otherwise
1138    /// the callback is discarded and [`VarHandle::dummy`] returned.
1139    fn hook(&self, pos_modify_action: impl Fn(&VarHookArgs<T>) -> bool + Send + Sync + 'static) -> VarHandle {
1140        self.hook_any(Box::new(move |a| pos_modify_action(&a.as_strong().unwrap())))
1141    }
1142
1143    /// Awaits for the [`last_update`] to change.
1144    ///
1145    /// Note that [`is_new`] will be `true` when the future elapses only when polled
1146    /// in sync with the UI, but it will elapse in any thread when the variable updates after the future is instantiated.
1147    ///
1148    /// Note that outside of the UI tree there is no variable synchronization across multiple var method calls, so
1149    /// a sequence of `get(); wait_update().await; get();` can miss a value between `get` and `wait_update`. The returned
1150    /// future captures the [`last_update`] at the moment this method is called, this can be leveraged by double-checking to
1151    /// avoid race conditions, see the [`wait_value`] default implementation for more details.
1152    ///
1153    /// [`get`]: Var::get
1154    /// [`wait_value`]: Var::wait_value
1155    /// [`last_update`]: AnyVar::last_update
1156    /// [`is_new`]: AnyVar::is_new
1157    fn wait_update(&self) -> impl Future<Output = VarUpdateId> + Send + Sync {
1158        crate::future::WaitUpdateFut::new(self)
1159    }
1160
1161    /// Awaits for [`is_animating`] to change from `true` to `false`.
1162    ///
1163    /// If the variable is not animating at the moment of this call the future will await until the animation starts and stops.
1164    ///
1165    /// [`is_animating`]: AnyVar::is_animating
1166    fn wait_animation(&self) -> impl Future<Output = ()> + Send + Sync {
1167        crate::future::WaitIsNotAnimatingFut::new(self)
1168    }
1169
1170    ///Awaits for a value that passes the `predicate`.
1171    fn wait_value(&self, predicate: impl Fn(&T) -> bool + Send + Sync) -> impl Future<Output = ()> + Send + Sync {
1172        async move {
1173            while !self.with(&predicate) {
1174                let future = self.wait_update();
1175                if self.with(&predicate) {
1176                    break;
1177                }
1178                future.await;
1179            }
1180        }
1181    }
1182
1183    /// Visit the current value of the variable, if it [`is_new`].
1184    ///
1185    /// [`is_new`]: AnyVar::is_new
1186    fn with_new<R, F>(&self, read: F) -> Option<R>
1187    where
1188        F: FnOnce(&T) -> R,
1189    {
1190        if self.is_new() { Some(self.with(read)) } else { None }
1191    }
1192
1193    /// Get a clone of the current value.
1194    fn get(&self) -> T {
1195        self.with(Clone::clone)
1196    }
1197
1198    /// Gets the value as a display [`Txt`].
1199    ///
1200    /// [`Txt`]: Txt
1201    fn get_txt(&self) -> Txt
1202    where
1203        T: fmt::Display,
1204    {
1205        self.with(ToTxt::to_txt)
1206    }
1207
1208    /// Gets the value as a display [`String`].
1209    fn get_string(&self) -> String
1210    where
1211        T: fmt::Display,
1212    {
1213        self.with(ToString::to_string)
1214    }
1215
1216    /// Get a clone of the current value into `value`.
1217    fn get_into(&self, value: &mut T) {
1218        self.with(var_get_into(value))
1219    }
1220
1221    /// Get a clone of the current value into `value` if the current value is not equal to it.
1222    fn get_ne(&self, value: &mut T) -> bool {
1223        self.with(var_get_ne(value))
1224    }
1225
1226    /// Get a clone of the current value, if it [`is_new`].
1227    ///
1228    /// [`is_new`]: AnyVar::is_new
1229    fn get_new(&self) -> Option<T> {
1230        if self.is_new() { Some(self.with(Clone::clone)) } else { None }
1231    }
1232
1233    /// Get a clone of the current value into `value` if the current value [`is_new`].
1234    ///
1235    /// [`is_new`]: AnyVar::is_new
1236    fn get_new_into(&self, value: &mut T) -> bool {
1237        let is_new = self.is_new();
1238        if is_new {
1239            self.with(var_get_into(value));
1240        }
1241        is_new
1242    }
1243
1244    /// Get a clone of the current value into `value` if the variable value [`is_new`] and not equal to the `value`.
1245    ///
1246    /// [`is_new`]: AnyVar::is_new
1247    fn get_new_ne(&self, value: &mut T) -> bool {
1248        self.is_new() && self.get_ne(value)
1249    }
1250
1251    /// Schedule a new `value` for the variable, it will be set in the end of the current app update.
1252    fn set<I>(&self, value: I) -> Result<(), VarIsReadOnlyError>
1253    where
1254        I: Into<T>,
1255    {
1256        self.modify(var_set(value.into()))
1257    }
1258
1259    /// Schedule a new `value` for the variable, it will be set in the end of the current app update to the updated
1260    /// value of `other`, so if the other var has already scheduled an update, the updated value will be used.
1261    ///  
1262    /// This can be used in combination with binding to create a binding that starts with synchronized values.
1263    fn set_from<I>(&self, other: &I) -> Result<(), VarIsReadOnlyError>
1264    where
1265        I: Var<T>,
1266    {
1267        if other.capabilities().is_always_static() {
1268            self.set(other.get())
1269        } else {
1270            self.modify(var_set_from(other.clone().actual_var()))
1271        }
1272    }
1273
1274    /// Set from `other` value at the time of update, mapped to the type of `self`.
1275    fn set_from_map<Iv, I, M>(&self, other: &I, map: M) -> Result<(), VarIsReadOnlyError>
1276    where
1277        Iv: VarValue,
1278        I: Var<Iv>,
1279        M: FnOnce(&Iv) -> T + Send + 'static,
1280    {
1281        if other.capabilities().is_always_static() {
1282            self.set(other.with(map))
1283        } else {
1284            self.modify(var_set_from_map(other.clone().actual_var(), map))
1285        }
1286    }
1287
1288    /// Create a var that redirects to this variable until the first value update, then it behaves like a [`ArcVar<T>`].
1289    ///
1290    /// The return variable is *clone-on-write* and has the `MODIFY` capability independent of the source capabilities, when
1291    /// a modify request is made the source value is cloned and offered for modification, if modified the source variable is dropped
1292    /// and the cow var behaves like a [`ArcVar<T>`], if the modify closure does not update the cloned value it is dropped and the cow
1293    /// continues to redirect to the source variable.
1294    fn cow(&self) -> types::ArcCowVar<T, Self> {
1295        types::ArcCowVar::new(self.clone())
1296    }
1297
1298    /// Creates a var that maps from this variable.
1299    ///
1300    /// The `map` closure is called once on initialization, and then once every time
1301    /// the source variable updates.
1302    ///
1303    /// The mapping variable is read-only, you can use [`map_bidi`] to map back.
1304    ///
1305    /// Note that the mapping var can be [contextualized] for context vars, meaning the map binding will initialize in
1306    /// the fist usage context, not the creation context, so `property = CONTEXT_VAR.map(|&b|!b);` will bind with
1307    /// the `CONTEXT_VAR` in the `property` context, not the property instantiation. The `map` closure itself runs in
1308    /// the root app context, trying to read other context variables inside it will only read the default value.
1309    ///
1310    /// For other variables types the `map` can run once in the caller context.
1311    ///
1312    /// If `self` can change the output variable will keep it alive, this is to support chaining maps.
1313    ///
1314    /// [`map_bidi`]: Var::map_bidi
1315    /// [contextualized]: types::ContextualizedVar
1316    fn map<O, M>(&self, map: M) -> Self::Map<O>
1317    where
1318        O: VarValue,
1319        M: FnMut(&T) -> O + Send + 'static;
1320
1321    /// Creates a [`map`] that converts from `T` to `O` using [`Into<O>`].
1322    ///
1323    /// [`map`]: Var::map
1324    fn map_into<O>(&self) -> Self::Map<O>
1325    where
1326        O: VarValue,
1327        T: Into<O>,
1328    {
1329        self.map(|v| v.clone().into())
1330    }
1331
1332    /// Creates a [`map`] that converts from `T` to [`Txt`] using [`ToTxt`].
1333    ///
1334    /// [`map`]: Var::map
1335    /// [`Txt`]: Txt
1336    /// [`ToTxt`]: ToTxt
1337    fn map_to_txt(&self) -> Self::Map<Txt>
1338    where
1339        T: ToTxt,
1340    {
1341        self.map(ToTxt::to_txt)
1342    }
1343
1344    /// Create a [`map`] that converts from `T` to [`String`] using [`ToString`].
1345    ///
1346    /// [`map`]: Var::map
1347    fn map_to_string(&self) -> Self::Map<String>
1348    where
1349        T: ToString,
1350    {
1351        self.map(ToString::to_string)
1352    }
1353
1354    /// Create a var that maps from this variable on read and to it on write.
1355    ///
1356    /// The `map` closure is called once on initialization, and then once every time
1357    /// the source variable updates, the `map_back` closure is called every time the output value is modified directly.
1358    ///
1359    /// The mapping var can be [contextualized], see [`Var::map`] for more details.
1360    ///
1361    /// If `self` can change the output variable will keep it alive, this is to support chaining maps.
1362    ///
1363    /// [contextualized]: types::ContextualizedVar
1364    fn map_bidi<O, M, B>(&self, map: M, map_back: B) -> Self::MapBidi<O>
1365    where
1366        O: VarValue,
1367        M: FnMut(&T) -> O + Send + 'static,
1368        B: FnMut(&O) -> T + Send + 'static;
1369
1370    /// Create a var that maps to an inner variable that is found inside the value of this variable.
1371    ///
1372    /// The mapping var can be [contextualized] if self is contextual, otherwise `map` evaluates immediately to start. Note
1373    /// that the "mapped-to" var can be contextual even when the mapping var is not.
1374    ///
1375    /// The mapping var has the same capabilities of the inner var, plus `CAPS_CHANGE`, modifying the mapping var modifies the inner var.
1376    ///
1377    /// If `self` can change the output variable will keep it alive, this is to support chaining maps.
1378    ///
1379    /// [contextualized]: types::ContextualizedVar
1380    fn flat_map<O, V, M>(&self, map: M) -> Self::FlatMap<O, V>
1381    where
1382        O: VarValue,
1383        V: Var<O>,
1384        M: FnMut(&T) -> V + Send + 'static;
1385
1386    /// Creates a ref-counted var that maps from this variable, but can retain a previous mapped value.
1387    ///
1388    /// The `map` closure is called once on initialization, if it returns `None` the `fallback` closure is called to generate
1389    /// a fallback value, after, the `map` closure is called once every time the mapping variable reads and is out of sync
1390    /// with the source variable, if it returns `Some(_)` the mapping variable value changes, otherwise the previous value is retained.
1391    ///
1392    /// The mapping variable is read-only, use [`filter_map_bidi`] to map back.
1393    ///
1394    /// The mapping var can be [contextualized], see [`Var::map`] for more details.
1395    ///
1396    /// If `self` can change the output variable will keep it alive, this is to support chaining maps.
1397    ///
1398    /// [contextualized]: types::ContextualizedVar
1399    /// [`map_bidi`]: Var::map_bidi
1400    /// [`filter_map_bidi`]: Var::filter_map_bidi
1401    fn filter_map<O, M, I>(&self, map: M, fallback: I) -> Self::FilterMap<O>
1402    where
1403        O: VarValue,
1404        M: FnMut(&T) -> Option<O> + Send + 'static,
1405        I: Fn() -> O + Send + Sync + 'static;
1406
1407    /// Create a [`filter_map`] that tries to convert from `T` to `O` using [`TryInto<O>`].
1408    ///
1409    /// [`filter_map`]: Var::filter_map
1410    fn filter_try_into<O, I>(&self, fallback: I) -> Self::FilterMap<O>
1411    where
1412        O: VarValue,
1413        T: TryInto<O>,
1414        I: Fn() -> O + Send + Sync + 'static,
1415    {
1416        self.filter_map(|v| v.clone().try_into().ok(), fallback)
1417    }
1418
1419    /// Create a [`filter_map`] that tries to convert from `T` to `O` using [`FromStr`].
1420    ///
1421    /// [`filter_map`]: Var::filter_map
1422    /// [`FromStr`]: std::str::FromStr
1423    fn filter_parse<O, I>(&self, fallback: I) -> Self::FilterMap<O>
1424    where
1425        O: VarValue + std::str::FromStr,
1426        T: AsRef<str>,
1427        I: Fn() -> O + Send + Sync + 'static,
1428    {
1429        self.filter_map(|v| v.as_ref().parse().ok(), fallback)
1430    }
1431
1432    /// Create a var that maps from this variable on read and to it on write, mapping in both directions can skip
1433    /// updates, retaining the previous mapped value.
1434    ///
1435    /// The `map` closure is called once on initialization, if it returns `None` the `fallback` closure is called
1436    /// to generate a fallback value, after, the `map` closure is called once every time
1437    /// the mapping variable reads and is out of sync with the source variable, if it returns `Some(_)` the mapping variable value changes,
1438    /// otherwise the previous value is retained. The `map_back` closure
1439    /// is called every time the output value is modified directly, if it returns `Some(_)` the source variable is set.
1440    ///
1441    /// The mapping var can be [contextualized], see [`Var::map`] for more details.
1442    ///
1443    /// If `self` can change the output variable will keep it alive, this is to support chaining maps.
1444    ///
1445    /// [contextualized]: types::ContextualizedVar
1446    fn filter_map_bidi<O, M, B, I>(&self, map: M, map_back: B, fallback: I) -> Self::FilterMapBidi<O>
1447    where
1448        O: VarValue,
1449        M: FnMut(&T) -> Option<O> + Send + 'static,
1450        B: FnMut(&O) -> Option<T> + Send + 'static,
1451        I: Fn() -> O + Send + Sync + 'static;
1452
1453    /// Create a mapping wrapper around `self`. The `map` closure is called for each value access, it must reference the
1454    /// value `O` that already exists in `T`.
1455    fn map_ref<O, M>(&self, map: M) -> Self::MapRef<O>
1456    where
1457        O: VarValue,
1458        M: Fn(&T) -> &O + Send + Sync + 'static;
1459
1460    /// Create a mapping wrapper around `self`. The `map` closure is called for each value access, it must reference the
1461    /// value `O` that already exists in `T`, the `map_mut` closure is called for every modify request, it must do the same
1462    /// as `map` but with mutable access.
1463    fn map_ref_bidi<O, M, B>(&self, map: M, map_mut: B) -> Self::MapRefBidi<O>
1464    where
1465        O: VarValue,
1466        M: Fn(&T) -> &O + Send + Sync + 'static,
1467        B: Fn(&mut T) -> &mut O + Send + Sync + 'static;
1468    /// Setup a hook that assigns `other` with the new values of `self` transformed by `map`.
1469    ///
1470    /// Only a weak reference to the `other` variable is held, both variables update in the same app update cycle.
1471    ///
1472    /// Note that the current value is not assigned, only the subsequent updates, you can use [`set_from_map`]
1473    /// to sync the initial value.
1474    ///
1475    /// [`set_from_map`]: Self::set_from_map
1476    fn bind_map<T2, V2, M>(&self, other: &V2, map: M) -> VarHandle
1477    where
1478        T2: VarValue,
1479        V2: Var<T2>,
1480        M: FnMut(&T) -> T2 + Send + 'static,
1481    {
1482        var_bind_map(self, other, map)
1483    }
1484
1485    /// Setup a hook that assigns `other` with the new values of `self` transformed by `map`, if the closure returns a value.
1486    ///
1487    /// Only a weak reference to the `other` variable is held, both variables update in the same app update cycle.
1488    ///
1489    /// Note that the current value is not assigned, only the subsequent updates, you can assign
1490    /// `other` and then bind to fully sync the variables.
1491    fn bind_filter_map<T2, V2, F>(&self, other: &V2, map: F) -> VarHandle
1492    where
1493        T2: VarValue,
1494        V2: Var<T2>,
1495        F: FnMut(&T) -> Option<T2> + Send + 'static,
1496    {
1497        var_bind_filter_map(self, other, map)
1498    }
1499
1500    /// Bind `self` to `other` and back without causing an infinite loop.
1501    ///
1502    /// Only a weak reference to each variable is held by the other, if both variables are scheduled to update in the same cycle
1503    /// both get assigned, but only one bind transfer per app cycle is allowed for each variable. Returns two handles on the
1504    /// the *map* hook and one for the *map-back* hook.
1505    ///
1506    /// Note that the current value is not assigned, only the subsequent updates, you can assign
1507    /// `other` and `self` and then bind to fully sync the variables.
1508    fn bind_map_bidi<T2, V2, M, B>(&self, other: &V2, map: M, map_back: B) -> VarHandles
1509    where
1510        T2: VarValue,
1511        V2: Var<T2>,
1512        M: FnMut(&T) -> T2 + Send + 'static,
1513        B: FnMut(&T2) -> T + Send + 'static,
1514    {
1515        var_bind_map_bidi(self, other, map, map_back)
1516    }
1517
1518    /// Bind `self` to `other` and back with the new values of `self` transformed by `map` and the new values of `other` transformed
1519    /// by `map_back`, the value is assigned in a update only if the closures returns a value.
1520    ///
1521    /// Only a weak reference to each variable is held by the other, both variables update in the same app update cycle.
1522    ///
1523    /// Note that the current value is not assigned, only the subsequent updates, you can assign
1524    /// `other` and then bind to fully sync the variables.
1525    fn bind_filter_map_bidi<T2, V2, M, B>(&self, other: &V2, map: M, map_back: B) -> VarHandles
1526    where
1527        T2: VarValue,
1528        V2: Var<T2>,
1529        M: FnMut(&T) -> Option<T2> + Send + 'static,
1530        B: FnMut(&T2) -> Option<T> + Send + 'static,
1531    {
1532        var_bind_filter_map_bidi(self, other, map, map_back)
1533    }
1534
1535    /// Setup a hook that assigns `other` with the new values of `self`.
1536    ///
1537    /// Only a weak reference to the `other` variable is held.
1538    ///
1539    /// Note that the current value is not assigned, only the subsequent updates, you can use
1540    /// [`set_from`] to sync the initial value.
1541    ///
1542    /// [`set_from`]: Self::set_from
1543    fn bind<V2>(&self, other: &V2) -> VarHandle
1544    where
1545        V2: Var<T>,
1546    {
1547        self.bind_map(other, Clone::clone)
1548    }
1549
1550    /// Calls `other.set_from(self)` and `self.bind(other)`.
1551    fn set_bind<V2>(&self, other: &V2) -> VarHandle
1552    where
1553        V2: Var<T>,
1554    {
1555        let _ = other.set_from(self);
1556        self.bind(other)
1557    }
1558
1559    /// Setup two hooks that assigns `other` with the new values of `self` and `self` with the new values of `other`.
1560    ///
1561    /// Only a weak reference to each variable is held by the other.
1562    ///
1563    /// Note that the current value is not assigned, only the subsequent updates, you can assign
1564    /// `other` using [`set_from`] and then bind to fully sync the variables.
1565    ///
1566    /// [`set_from`]: Var::set_from
1567    fn bind_bidi<V2>(&self, other: &V2) -> VarHandles
1568    where
1569        V2: Var<T>,
1570    {
1571        self.bind_map_bidi(other, Clone::clone, Clone::clone)
1572    }
1573
1574    /// Debug helper for tracing the lifetime of a value in this variable.
1575    ///
1576    /// The `enter_value` closure is called every time the variable updates, it can return
1577    /// an implementation agnostic *scope* or *span* `S` that is only dropped when the variable updates again.
1578    ///
1579    /// The `enter_value` is also called immediately when this method is called to start tracking the first value.
1580    ///
1581    /// Returns a [`VarHandle`] that can be used to stop tracing.
1582    ///
1583    /// If this variable can never update the span is immediately dropped and a dummy handle is returned. Note that
1584    /// the trace is set on the [`actual_var`].
1585    ///
1586    /// [`tracing`]: https://docs.rs/tracing
1587    /// [`actual_var`]: Var::actual_var
1588    fn trace_value<E, S>(&self, mut enter_value: E) -> VarHandle
1589    where
1590        E: FnMut(&TraceValueArgs<T>) -> S + Send + 'static,
1591        S: Send + 'static,
1592    {
1593        let span = self.with(|v| {
1594            enter_value(&TraceValueArgs {
1595                args: &AnyVarHookArgs::new(v, false, &[]),
1596                _type: PhantomData,
1597            })
1598        });
1599        let data = Mutex::new((Some(span), enter_value));
1600        self.hook_any(Box::new(move |args| {
1601            let mut data = data.lock();
1602            let (span, enter_value) = &mut *data;
1603            let _ = span.take();
1604            *span = Some(enter_value(&TraceValueArgs { args, _type: PhantomData }));
1605            true
1606        }))
1607    }
1608
1609    /// Schedule an animation that targets this variable.
1610    ///
1611    /// If the variable is always read-only no animation is created and a dummy handle returned. The animation
1612    /// targets the current [`actual_var`] and is stopped if the variable is dropped.
1613    ///
1614    /// The `animate` closure is called every frame, starting after next frame, the closure inputs are
1615    /// the [`Animation`] args and *modify* access to the variable value, the args
1616    /// can be used to calculate the new variable value and to control or stop the animation.
1617    ///
1618    /// [`actual_var`]: Var::actual_var
1619    /// [`Animation`]: animation::Animation
1620    fn animate<A>(&self, animate: A) -> animation::AnimationHandle
1621    where
1622        A: FnMut(&animation::Animation, &mut VarModify<T>) + Send + 'static,
1623    {
1624        animation::var_animate(self, animate)
1625    }
1626
1627    /// Schedule animations started by `animate`, the closure is called once at the start to begin, then again every time
1628    /// the variable stops animating.
1629    ///
1630    /// This can be used to create a sequence of animations or to repeat an animation. The sequence stops when `animate` returns
1631    /// a dummy handle or the variable is modified outside of `animate`, or animations are disabled, or the returned handle is dropped.
1632    fn sequence<A>(&self, animate: A) -> VarHandle
1633    where
1634        A: FnMut(&<<Self::ActualVar as Var<T>>::Downgrade as WeakVar<T>>::Upgrade) -> animation::AnimationHandle + Send + 'static,
1635    {
1636        animation::var_sequence(self, animate)
1637    }
1638
1639    /// Schedule an easing transition from the `start_value` to `end_value`.
1640    ///
1641    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
1642    ///
1643    /// See [`Var::animate`] for details about animations.
1644    fn set_ease<S, E, F>(&self, start_value: S, end_value: E, duration: Duration, easing: F) -> animation::AnimationHandle
1645    where
1646        T: Transitionable,
1647        S: Into<T>,
1648        E: Into<T>,
1649        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1650    {
1651        self.set_ease_with(start_value, end_value, duration, easing, animation::Transition::sample)
1652    }
1653
1654    /// Oscillate between `start_value` to `end_value` with an easing transition.
1655    ///
1656    /// The `duration` defines the easing duration between the two values.
1657    ///
1658    /// Note that you can use [`Var::sequence`] to create more complex looping animations.
1659    fn set_ease_oci<S, E, F>(&self, start_value: S, end_value: E, duration: Duration, easing: F) -> animation::AnimationHandle
1660    where
1661        T: Transitionable,
1662        S: Into<T>,
1663        E: Into<T>,
1664        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1665    {
1666        self.set_ease_oci_with(start_value, end_value, duration, easing, animation::Transition::sample)
1667    }
1668
1669    /// Schedule an easing transition from the `start_value` to `end_value` using a custom value sampler.
1670    ///
1671    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
1672    ///
1673    /// See [`Var::animate`] for details about animations.
1674    fn set_ease_with<S, E, F, Sa>(
1675        &self,
1676        start_value: S,
1677        end_value: E,
1678        duration: Duration,
1679        easing: F,
1680        sampler: Sa,
1681    ) -> animation::AnimationHandle
1682    where
1683        T: Transitionable,
1684        S: Into<T>,
1685        E: Into<T>,
1686        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1687        Sa: Fn(&animation::Transition<T>, EasingStep) -> T + Send + 'static,
1688    {
1689        self.animate(animation::var_set_ease_with(
1690            start_value.into(),
1691            end_value.into(),
1692            duration,
1693            easing,
1694            999.fct(),
1695            sampler,
1696        ))
1697    }
1698
1699    /// Oscillate between `start_value` to `end_value` with an easing transition using a custom value sampler.
1700    ///
1701    /// The `duration` defines the easing duration between the two values.
1702    ///
1703    /// Note that you can use [`Var::sequence`] to create more complex looping animations.
1704    fn set_ease_oci_with<S, E, F, Sa>(
1705        &self,
1706        start_value: S,
1707        end_value: E,
1708        duration: Duration,
1709        easing: F,
1710        sampler: Sa,
1711    ) -> animation::AnimationHandle
1712    where
1713        T: Transitionable,
1714        S: Into<T>,
1715        E: Into<T>,
1716        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1717        Sa: Fn(&animation::Transition<T>, EasingStep) -> T + Send + 'static,
1718    {
1719        self.animate(animation::var_set_ease_oci_with(
1720            start_value.into(),
1721            end_value.into(),
1722            duration,
1723            easing,
1724            999.fct(),
1725            sampler,
1726        ))
1727    }
1728
1729    /// Schedule an easing transition from the current value to `new_value`.
1730    ///
1731    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
1732    ///
1733    /// See [`Var::animate`] for details about animations.
1734    fn ease<E, F>(&self, new_value: E, duration: Duration, easing: F) -> animation::AnimationHandle
1735    where
1736        T: Transitionable,
1737        E: Into<T>,
1738        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1739    {
1740        self.ease_with(new_value, duration, easing, animation::Transition::sample)
1741    }
1742
1743    /// Oscillate between the current value and `new_value` with an easing transition.
1744    ///
1745    /// The `duration` defines the easing duration between the two values.
1746    ///
1747    /// Note that you can use [`Var::sequence`] to create more complex looping animations.
1748    fn ease_oci<E, F>(&self, new_value: E, duration: Duration, easing: F) -> animation::AnimationHandle
1749    where
1750        T: Transitionable,
1751        E: Into<T>,
1752        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1753    {
1754        self.ease_oci_with(new_value, duration, easing, animation::Transition::sample)
1755    }
1756
1757    /// Schedule an easing transition from the current value to `new_value` using a custom value sampler.
1758    ///
1759    /// The variable updates every time the [`EasingStep`] for each frame changes and a different value is sampled.
1760    ///
1761    /// See [`Var::animate`] for details about animations.
1762    fn ease_with<E, F, S>(&self, new_value: E, duration: Duration, easing: F, sampler: S) -> animation::AnimationHandle
1763    where
1764        T: Transitionable,
1765        E: Into<T>,
1766        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1767        S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + 'static,
1768    {
1769        self.animate(animation::var_set_ease_with(
1770            self.get(),
1771            new_value.into(),
1772            duration,
1773            easing,
1774            0.fct(),
1775            sampler,
1776        ))
1777    }
1778
1779    /// Oscillate between the current value and `new_value` with an easing transition and a custom value sampler.
1780    ///
1781    /// The `duration` defines the easing duration between the two values.
1782    ///
1783    /// Note that you can use [`Var::sequence`] to create more complex looping animations.
1784    fn ease_oci_with<E, F, S>(&self, new_value: E, duration: Duration, easing: F, sampler: S) -> animation::AnimationHandle
1785    where
1786        T: Transitionable,
1787        E: Into<T>,
1788        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1789        S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + 'static,
1790    {
1791        self.animate(animation::var_set_ease_oci_with(
1792            self.get(),
1793            new_value.into(),
1794            duration,
1795            easing,
1796            0.fct(),
1797            sampler,
1798        ))
1799    }
1800
1801    /// Schedule a keyframed transition animation for the variable, starting from the first key.
1802    ///
1803    /// The variable will be set to the first keyframe, then animated across all other keys.
1804    ///
1805    /// See [`Var::animate`] for details about animations.
1806    fn set_ease_keyed<F>(&self, keys: Vec<(Factor, T)>, duration: Duration, easing: F) -> animation::AnimationHandle
1807    where
1808        T: Transitionable,
1809        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1810    {
1811        self.set_ease_keyed_with(keys, duration, easing, animation::TransitionKeyed::sample)
1812    }
1813
1814    /// Schedule a keyframed transition animation for the variable, starting from the first key, using a custom value sampler.
1815    ///
1816    /// The variable will be set to the first keyframe, then animated across all other keys.
1817    ///
1818    /// See [`Var::animate`] for details about animations.
1819    fn set_ease_keyed_with<F, S>(&self, keys: Vec<(Factor, T)>, duration: Duration, easing: F, sampler: S) -> animation::AnimationHandle
1820    where
1821        T: Transitionable,
1822        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1823        S: Fn(&animation::TransitionKeyed<T>, EasingStep) -> T + Send + 'static,
1824    {
1825        if let Some(transition) = animation::TransitionKeyed::new(keys) {
1826            self.animate(animation::var_set_ease_keyed_with(transition, duration, easing, 999.fct(), sampler))
1827        } else {
1828            animation::AnimationHandle::dummy()
1829        }
1830    }
1831
1832    /// Schedule a keyframed transition animation for the variable, starting from the current value.
1833    ///
1834    /// The variable will be set to the first keyframe, then animated across all other keys.
1835    ///
1836    /// See [`Var::animate`] for details about animations.
1837    fn ease_keyed<F>(&self, keys: Vec<(Factor, T)>, duration: Duration, easing: F) -> animation::AnimationHandle
1838    where
1839        T: Transitionable,
1840        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1841    {
1842        self.ease_keyed_with(keys, duration, easing, animation::TransitionKeyed::sample)
1843    }
1844
1845    /// Schedule a keyframed transition animation for the variable, starting from the current value, using a custom value sampler.
1846    ///
1847    /// The variable will be set to the first keyframe, then animated across all other keys.
1848    ///
1849    /// See [`Var::animate`] for details about animations.
1850    fn ease_keyed_with<F, S>(&self, mut keys: Vec<(Factor, T)>, duration: Duration, easing: F, sampler: S) -> animation::AnimationHandle
1851    where
1852        T: Transitionable,
1853        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1854        S: Fn(&animation::TransitionKeyed<T>, EasingStep) -> T + Send + 'static,
1855    {
1856        keys.insert(0, (0.fct(), self.get()));
1857
1858        let transition = animation::TransitionKeyed::new(keys).unwrap();
1859        self.animate(animation::var_set_ease_keyed_with(transition, duration, easing, 0.fct(), sampler))
1860    }
1861
1862    /// Set the variable to `new_value` after a `delay`.
1863    ///
1864    /// The variable [`is_animating`] until the delay elapses and the value is set.
1865    ///
1866    /// See [`Var::animate`] for details about animations.
1867    ///
1868    /// [`is_animating`]: AnyVar::is_animating
1869    fn step<N>(&self, new_value: N, delay: Duration) -> animation::AnimationHandle
1870    where
1871        N: Into<T>,
1872    {
1873        self.animate(animation::var_step(new_value.into(), delay))
1874    }
1875
1876    /// Oscillate between the current value and `new_value`, every time the `delay` elapses the variable is set to the next value.
1877    fn step_oci<N>(&self, new_value: N, delay: Duration) -> animation::AnimationHandle
1878    where
1879        N: Into<T>,
1880    {
1881        self.animate(animation::var_step_oci([self.get(), new_value.into()], delay, false))
1882    }
1883
1884    /// Oscillate between `from` and `to`, the variable is set to `from` to start and every time the `delay` elapses
1885    /// the variable is set to the next value.
1886    fn set_step_oci<V0, V1>(&self, from: V0, to: V1, delay: Duration) -> animation::AnimationHandle
1887    where
1888        V0: Into<T>,
1889        V1: Into<T>,
1890    {
1891        self.animate(animation::var_step_oci([from.into(), to.into()], delay, true))
1892    }
1893
1894    /// Set the variable to a sequence of values as a time `duration` elapses.
1895    ///
1896    /// An animation curve is used to find the first factor in `steps` above or at the curve line at the current time,
1897    /// the variable is set to this step value, continuing animating across the next steps until the last or the animation end.
1898    /// The variable [`is_animating`] from the start, even if no step applies and stays *animating* until the last *step* applies
1899    /// or the duration is reached.
1900    ///
1901    /// # Examples
1902    ///
1903    /// Creates a variable that outputs text every 5% of a 5 seconds animation, advanced linearly.
1904    ///
1905    /// ```
1906    /// # use zng_var::{*, animation::easing};
1907    /// # use zng_txt::*;
1908    /// # use zng_unit::*;
1909    /// # fn demo(text_var: impl Var<Txt>) {
1910    /// let steps = (0..=100).step_by(5).map(|i| (i.pct().fct(), formatx!("{i}%"))).collect();
1911    /// # let _ =
1912    /// text_var.steps(steps, 5.secs(), easing::linear)
1913    /// # ;}
1914    /// ```
1915    ///
1916    /// The variable is set to `"0%"`, after 5% of the `duration` elapses it is set to `"5%"` and so on
1917    /// until the value is set to `"100%` at the end of the animation.
1918    ///
1919    /// Returns an [`AnimationHandle`]. See [`Var::animate`] for details about animations.
1920    ///
1921    /// [`is_animating`]: AnyVar::is_animating
1922    /// [`AnimationHandle`]: animation::AnimationHandle
1923    fn steps<F>(&self, steps: Vec<(Factor, T)>, duration: Duration, easing: F) -> animation::AnimationHandle
1924    where
1925        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1926    {
1927        self.animate(animation::var_steps(steps, duration, easing))
1928    }
1929
1930    /// Starts an easing animation that *chases* a target value that can be changed using the [`ChaseAnimation<T>`] handle.
1931    ///
1932    /// [`ChaseAnimation<T>`]: animation::ChaseAnimation
1933    fn chase<N, F>(&self, first_target: N, duration: Duration, easing: F) -> animation::ChaseAnimation<T>
1934    where
1935        N: Into<T>,
1936        F: Fn(EasingTime) -> EasingStep + Send + 'static,
1937        T: Transitionable,
1938    {
1939        animation::var_chase(self.clone().boxed(), first_target.into(), duration, easing)
1940    }
1941
1942    /// Create a vars that [`ease`] to each new value of `self`.
1943    ///
1944    /// Note that the mapping var can be [contextualized], see [`map`] for more details.
1945    ///
1946    /// If `self` can change the output variable will keep it alive.
1947    ///
1948    /// [contextualized]: types::ContextualizedVar
1949    /// [`ease`]: Var::ease
1950    /// [`map`]: Var::map
1951    fn easing<F>(&self, duration: Duration, easing: F) -> Self::Easing
1952    where
1953        T: Transitionable,
1954        F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static;
1955
1956    /// Create a vars that [`ease_with`] to each new value of `self`.
1957    ///
1958    /// Note that the mapping var can be [contextualized], see [`map`] for more details.
1959    /// If `self` can change the output variable will keep it alive.
1960    ///
1961    /// [contextualized]: types::ContextualizedVar
1962    /// [`ease_with`]: Var::ease_with
1963    /// [`map`]: Var::map
1964    fn easing_with<F, S>(&self, duration: Duration, easing: F, sampler: S) -> Self::Easing
1965    where
1966        T: Transitionable,
1967        F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
1968        S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static;
1969
1970    /// Returns a wrapper that implements [`fmt::Debug`] to write the var value.
1971    fn debug(&self) -> types::VarDebug<'_, T, Self> {
1972        types::VarDebug {
1973            var: self,
1974            _t: PhantomData,
1975        }
1976    }
1977
1978    /// Returns a wrapper that implements [`fmt::Display`] to write the var value.
1979    fn display(&self) -> types::VarDisplay<'_, T, Self>
1980    where
1981        T: fmt::Display,
1982    {
1983        types::VarDisplay {
1984            var: self,
1985            _t: PhantomData,
1986        }
1987    }
1988
1989    /// Keep `value` alive until the handle or `self` are dropped.
1990    fn hold<V>(&self, value: V) -> VarHandle
1991    where
1992        V: Any + Send,
1993    {
1994        let value = Mutex::new(value); // + Sync
1995        self.hook_any(Box::new(move |_| {
1996            let _hold = &value;
1997            true
1998        }))
1999    }
2000}
2001
2002fn var_bind_map<T, T2, V2, M>(source: &impl Var<T>, other: &V2, map: M) -> VarHandle
2003where
2004    T: VarValue,
2005    T2: VarValue,
2006    V2: Var<T2>,
2007    M: FnMut(&T) -> T2 + Send + 'static,
2008{
2009    #[cfg(feature = "dyn_closure")]
2010    let map: Box<dyn FnMut(&T) -> T2 + Send> = Box::new(map);
2011    var_bind_map_impl(source, other, map)
2012}
2013fn var_bind_map_impl<T, T2, V2, M>(source: &impl Var<T>, other: &V2, mut map: M) -> VarHandle
2014where
2015    T: VarValue,
2016    T2: VarValue,
2017    V2: Var<T2>,
2018    M: FnMut(&T) -> T2 + Send + 'static,
2019{
2020    var_bind(source, other, move |value, args, other| {
2021        let value = map(value);
2022        let update = args.update;
2023        let _ = other.modify(move |vm| {
2024            vm.set(value);
2025            if update {
2026                vm.update();
2027            }
2028        });
2029    })
2030}
2031
2032fn var_bind_filter_map<T, T2, V2, F>(source: &impl Var<T>, other: &V2, map: F) -> VarHandle
2033where
2034    T: VarValue,
2035    T2: VarValue,
2036    V2: Var<T2>,
2037    F: FnMut(&T) -> Option<T2> + Send + 'static,
2038{
2039    #[cfg(feature = "dyn_closure")]
2040    let map: Box<dyn FnMut(&T) -> Option<T2> + Send> = Box::new(map);
2041    var_bind_filter_map_impl(source, other, map)
2042}
2043fn var_bind_filter_map_impl<T, T2, V2, F>(source: &impl Var<T>, other: &V2, mut map: F) -> VarHandle
2044where
2045    T: VarValue,
2046    T2: VarValue,
2047    V2: Var<T2>,
2048    F: FnMut(&T) -> Option<T2> + Send + 'static,
2049{
2050    var_bind(source, other, move |value, args, other| {
2051        if let Some(value) = map(value) {
2052            let update = args.update;
2053            let _ = other.modify(move |vm| {
2054                vm.set(value);
2055                if update {
2056                    vm.update();
2057                }
2058            });
2059        }
2060    })
2061}
2062
2063fn var_bind_map_bidi<T, T2, V2, M, B>(source: &impl Var<T>, other: &V2, map: M, map_back: B) -> VarHandles
2064where
2065    T: VarValue,
2066    T2: VarValue,
2067    V2: Var<T2>,
2068    M: FnMut(&T) -> T2 + Send + 'static,
2069    B: FnMut(&T2) -> T + Send + 'static,
2070{
2071    #[cfg(feature = "dyn_closure")]
2072    let map: Box<dyn FnMut(&T) -> T2 + Send + 'static> = Box::new(map);
2073    #[cfg(feature = "dyn_closure")]
2074    let map_back: Box<dyn FnMut(&T2) -> T + Send + 'static> = Box::new(map_back);
2075
2076    var_bind_map_bidi_impl(source, other, map, map_back)
2077}
2078
2079fn var_bind_map_bidi_impl<T, T2, V2, M, B>(source: &impl Var<T>, other: &V2, mut map: M, mut map_back: B) -> VarHandles
2080where
2081    T: VarValue,
2082    T2: VarValue,
2083    V2: Var<T2>,
2084    M: FnMut(&T) -> T2 + Send + 'static,
2085    B: FnMut(&T2) -> T + Send + 'static,
2086{
2087    let source_tag = types::SourceVarTag::new(source);
2088    let source_to_other = var_bind(source, other, move |value, args, other| {
2089        let is_from_other = args
2090            .downcast_tags::<types::SourceVarTag>()
2091            .any(|&b| b == types::SourceVarTag::new(&other));
2092        if !is_from_other {
2093            let value = map(value);
2094            let update = args.update;
2095            let _ = other.modify(move |vm| {
2096                vm.set(value);
2097                vm.push_tag(source_tag);
2098                if update {
2099                    vm.update();
2100                }
2101            });
2102        }
2103    });
2104
2105    let other_tag = types::SourceVarTag::new(other);
2106    let other_to_source = var_bind(other, source, move |value, args, source| {
2107        let is_from_source = args
2108            .downcast_tags::<types::SourceVarTag>()
2109            .any(|&b| b == types::SourceVarTag::new(&source));
2110        if !is_from_source {
2111            let value = map_back(value);
2112            let update = args.update;
2113            let _ = source.modify(move |vm| {
2114                vm.set(value);
2115                vm.push_tag(other_tag);
2116                if update {
2117                    vm.update();
2118                }
2119            });
2120        }
2121    });
2122
2123    [source_to_other, other_to_source].into_iter().collect()
2124}
2125
2126fn var_bind_filter_map_bidi<T, T2, V2, M, B>(source: &impl Var<T>, other: &V2, map: M, map_back: B) -> VarHandles
2127where
2128    T: VarValue,
2129    T2: VarValue,
2130    V2: Var<T2>,
2131    M: FnMut(&T) -> Option<T2> + Send + 'static,
2132    B: FnMut(&T2) -> Option<T> + Send + 'static,
2133{
2134    #[cfg(feature = "dyn_closure")]
2135    let map: Box<dyn FnMut(&T) -> Option<T2> + Send + 'static> = Box::new(map);
2136    #[cfg(feature = "dyn_closure")]
2137    let map_back: Box<dyn FnMut(&T2) -> Option<T> + Send + 'static> = Box::new(map_back);
2138
2139    var_bind_filter_map_bidi_impl(source, other, map, map_back)
2140}
2141
2142fn var_bind_filter_map_bidi_impl<T, T2, V2, M, B>(source: &impl Var<T>, other: &V2, mut map: M, mut map_back: B) -> VarHandles
2143where
2144    T: VarValue,
2145    T2: VarValue,
2146    V2: Var<T2>,
2147    M: FnMut(&T) -> Option<T2> + Send + 'static,
2148    B: FnMut(&T2) -> Option<T> + Send + 'static,
2149{
2150    let source_tag = types::SourceVarTag::new(source);
2151    let source_to_other = var_bind(source, other, move |value, args, other| {
2152        let is_from_other = args
2153            .downcast_tags::<types::SourceVarTag>()
2154            .any(|&b| b == types::SourceVarTag::new(&other));
2155        if !is_from_other {
2156            if let Some(value) = map(value) {
2157                let update = args.update;
2158                let _ = other.modify(move |vm| {
2159                    vm.set(value);
2160                    vm.push_tag(source_tag);
2161                    if update {
2162                        vm.update();
2163                    }
2164                });
2165            }
2166        }
2167    });
2168
2169    let other_tag = types::SourceVarTag::new(other);
2170    let other_to_source = var_bind(other, source, move |value, args, source| {
2171        let is_from_source = args
2172            .downcast_tags::<types::SourceVarTag>()
2173            .any(|&b| b == types::SourceVarTag::new(&source));
2174        if !is_from_source {
2175            if let Some(value) = map_back(value) {
2176                let update = args.update;
2177                let _ = source.modify(move |vm| {
2178                    vm.set(value);
2179                    vm.push_tag(other_tag);
2180                    if update {
2181                        vm.update();
2182                    }
2183                });
2184            }
2185        }
2186    });
2187
2188    [source_to_other, other_to_source].into_iter().collect()
2189}
2190
2191fn var_hold_hook(source: &dyn AnyVar) -> Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync> {
2192    let source = source.clone_any();
2193    Box::new(move |_| {
2194        let _hold = &source;
2195        true
2196    })
2197}
2198
2199fn var_map<T: VarValue, O: VarValue>(source: &impl Var<T>, map: impl FnMut(&T) -> O + Send + 'static) -> ReadOnlyArcVar<O> {
2200    #[cfg(feature = "dyn_closure")]
2201    let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2202    var_map_impl(source, map)
2203}
2204fn var_map_impl<T: VarValue, O: VarValue>(source: &impl Var<T>, mut map: impl FnMut(&T) -> O + Send + 'static) -> ReadOnlyArcVar<O> {
2205    let mapped = var(source.with(&mut map));
2206    var_bind_map_impl(source, &mapped, map).perm();
2207    mapped.hook_any(var_hold_hook(source)).perm();
2208    mapped.read_only()
2209}
2210fn var_map_ctx<T: VarValue, O: VarValue>(
2211    source: &impl Var<T>,
2212    map: impl FnMut(&T) -> O + Send + 'static,
2213) -> contextualized::ContextualizedVar<O> {
2214    #[cfg(feature = "dyn_closure")]
2215    let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2216    var_map_ctx_impl(source, map)
2217}
2218fn var_map_ctx_impl<T: VarValue, O: VarValue>(
2219    source: &impl Var<T>,
2220    map: impl FnMut(&T) -> O + Send + 'static,
2221) -> contextualized::ContextualizedVar<O> {
2222    let source = source.clone();
2223    let map = Arc::new(Mutex::new(map));
2224    types::ContextualizedVar::new(move || {
2225        let other = var(source.with(&mut *map.lock()));
2226        let map = map.clone();
2227        source.bind_map(&other, move |t| map.lock()(t)).perm();
2228        other.read_only()
2229    })
2230}
2231fn var_map_mixed<T: VarValue, O: VarValue>(source: &impl Var<T>, map: impl FnMut(&T) -> O + Send + 'static) -> BoxedVar<O> {
2232    #[cfg(feature = "dyn_closure")]
2233    let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2234
2235    if source.is_contextual() {
2236        var_map_ctx_impl(source, map).boxed()
2237    } else if source.capabilities().is_always_static() {
2238        LocalVar(source.with(map)).boxed()
2239    } else {
2240        var_map_impl(source, map).boxed()
2241    }
2242}
2243
2244fn var_map_bidi<T, O, M, B>(source: &impl Var<T>, map: M, map_back: B) -> ArcVar<O>
2245where
2246    T: VarValue,
2247    O: VarValue,
2248    M: FnMut(&T) -> O + Send + 'static,
2249    B: FnMut(&O) -> T + Send + 'static,
2250{
2251    #[cfg(feature = "dyn_closure")]
2252    let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2253    #[cfg(feature = "dyn_closure")]
2254    let map_back: Box<dyn FnMut(&O) -> T + Send> = Box::new(map_back);
2255
2256    var_map_bidi_impl(source, map, map_back)
2257}
2258fn var_map_bidi_impl<T, O, M, B>(source: &impl Var<T>, mut map: M, map_back: B) -> ArcVar<O>
2259where
2260    T: VarValue,
2261    O: VarValue,
2262    M: FnMut(&T) -> O + Send + 'static,
2263    B: FnMut(&O) -> T + Send + 'static,
2264{
2265    let mapped = var(source.with(&mut map));
2266    var_bind_map_bidi_impl(source, &mapped, map, map_back).perm();
2267    mapped.hook_any(var_hold_hook(source)).perm();
2268    mapped
2269}
2270fn var_map_bidi_ctx<T, O, M, B>(source: &impl Var<T>, map: M, map_back: B) -> types::ContextualizedVar<O>
2271where
2272    T: VarValue,
2273    O: VarValue,
2274    M: FnMut(&T) -> O + Send + 'static,
2275    B: FnMut(&O) -> T + Send + 'static,
2276{
2277    #[cfg(feature = "dyn_closure")]
2278    let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2279    #[cfg(feature = "dyn_closure")]
2280    let map_back: Box<dyn FnMut(&O) -> T + Send> = Box::new(map_back);
2281
2282    var_map_bidi_ctx_impl(source, map, map_back)
2283}
2284fn var_map_bidi_ctx_impl<T, O, M, B>(source: &impl Var<T>, map: M, map_back: B) -> types::ContextualizedVar<O>
2285where
2286    T: VarValue,
2287    O: VarValue,
2288    M: FnMut(&T) -> O + Send + 'static,
2289    B: FnMut(&O) -> T + Send + 'static,
2290{
2291    let me = source.clone();
2292    let map = Arc::new(Mutex::new(map));
2293    let map_back = Arc::new(Mutex::new(map_back));
2294    types::ContextualizedVar::new(move || {
2295        let other = var(me.with(&mut *map.lock()));
2296        let map = map.clone();
2297        let map_back = map_back.clone();
2298        me.bind_map_bidi(&other, move |i| map.lock()(i), move |o| map_back.lock()(o)).perm();
2299        other
2300    })
2301}
2302fn var_map_bidi_mixed<T, O, M, B>(source: &impl Var<T>, map: M, map_back: B) -> BoxedVar<O>
2303where
2304    T: VarValue,
2305    O: VarValue,
2306    M: FnMut(&T) -> O + Send + 'static,
2307    B: FnMut(&O) -> T + Send + 'static,
2308{
2309    #[cfg(feature = "dyn_closure")]
2310    let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2311    #[cfg(feature = "dyn_closure")]
2312    let map_back: Box<dyn FnMut(&O) -> T + Send> = Box::new(map_back);
2313
2314    if source.is_contextual() {
2315        var_map_bidi_ctx_impl(source, map, map_back).boxed()
2316    } else if source.capabilities().is_always_static() {
2317        LocalVar(source.with(map)).boxed()
2318    } else {
2319        var_map_bidi_impl(source, map, map_back).boxed()
2320    }
2321}
2322
2323fn var_flat_map<T, O, V, M>(source: &impl Var<T>, map: M) -> types::ArcFlatMapVar<O, V>
2324where
2325    T: VarValue,
2326    O: VarValue,
2327    V: Var<O>,
2328    M: FnMut(&T) -> V + Send + 'static,
2329{
2330    #[cfg(feature = "dyn_closure")]
2331    let map: Box<dyn FnMut(&T) -> V + Send + 'static> = Box::new(map);
2332
2333    var_flat_map_impl(source, map)
2334}
2335fn var_flat_map_impl<T, O, V, M>(source: &impl Var<T>, map: M) -> types::ArcFlatMapVar<O, V>
2336where
2337    T: VarValue,
2338    O: VarValue,
2339    V: Var<O>,
2340    M: FnMut(&T) -> V + Send + 'static,
2341{
2342    types::ArcFlatMapVar::new(source, map)
2343}
2344fn var_flat_map_ctx<T, O, V, M>(source: &impl Var<T>, map: M) -> types::ContextualizedVar<O>
2345where
2346    T: VarValue,
2347    O: VarValue,
2348    V: Var<O>,
2349    M: FnMut(&T) -> V + Send + 'static,
2350{
2351    #[cfg(feature = "dyn_closure")]
2352    let map: Box<dyn FnMut(&T) -> V + Send + 'static> = Box::new(map);
2353
2354    var_flat_map_ctx_impl(source, map)
2355}
2356fn var_flat_map_ctx_impl<T, O, V, M>(source: &impl Var<T>, map: M) -> types::ContextualizedVar<O>
2357where
2358    T: VarValue,
2359    O: VarValue,
2360    V: Var<O>,
2361    M: FnMut(&T) -> V + Send + 'static,
2362{
2363    let me = source.clone();
2364    let map = Arc::new(Mutex::new(map));
2365    types::ContextualizedVar::new(move || {
2366        let map = map.clone();
2367        types::ArcFlatMapVar::new(&me, move |i| map.lock()(i))
2368    })
2369}
2370fn var_flat_map_mixed<T, O, V, M>(source: &impl Var<T>, map: M) -> BoxedVar<O>
2371where
2372    T: VarValue,
2373    O: VarValue,
2374    V: Var<O>,
2375    M: FnMut(&T) -> V + Send + 'static,
2376{
2377    #[cfg(feature = "dyn_closure")]
2378    let map: Box<dyn FnMut(&T) -> V + Send + 'static> = Box::new(map);
2379
2380    if source.is_contextual() {
2381        var_flat_map_ctx_impl(source, map).boxed()
2382    } else if source.capabilities().is_always_static() {
2383        source.with(map).boxed()
2384    } else {
2385        var_flat_map_impl(source, map).boxed()
2386    }
2387}
2388
2389fn var_filter_map<T, O, M, I>(source: &impl Var<T>, map: M, fallback: I) -> ReadOnlyArcVar<O>
2390where
2391    T: VarValue,
2392    O: VarValue,
2393    M: FnMut(&T) -> Option<O> + Send + 'static,
2394    I: Fn() -> O + Send + Sync + 'static,
2395{
2396    #[cfg(feature = "dyn_closure")]
2397    let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2398    #[cfg(feature = "dyn_closure")]
2399    let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2400
2401    var_filter_map_impl(source, map, fallback)
2402}
2403fn var_filter_map_impl<T, O, M, I>(source: &impl Var<T>, mut map: M, fallback: I) -> ReadOnlyArcVar<O>
2404where
2405    T: VarValue,
2406    O: VarValue,
2407    M: FnMut(&T) -> Option<O> + Send + 'static,
2408    I: Fn() -> O + Send + Sync + 'static,
2409{
2410    let mapped = var(source.with(&mut map).unwrap_or_else(&fallback));
2411    source.bind_filter_map(&mapped, map).perm();
2412    mapped.hook_any(var_hold_hook(source)).perm();
2413    mapped.read_only()
2414}
2415fn var_filter_map_ctx<T, O, M, I>(source: &impl Var<T>, map: M, fallback: I) -> types::ContextualizedVar<O>
2416where
2417    T: VarValue,
2418    O: VarValue,
2419    M: FnMut(&T) -> Option<O> + Send + 'static,
2420    I: Fn() -> O + Send + Sync + 'static,
2421{
2422    #[cfg(feature = "dyn_closure")]
2423    let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2424    #[cfg(feature = "dyn_closure")]
2425    let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2426
2427    var_filter_map_ctx_impl(source, map, fallback)
2428}
2429fn var_filter_map_ctx_impl<T, O, M, I>(source: &impl Var<T>, map: M, fallback: I) -> types::ContextualizedVar<O>
2430where
2431    T: VarValue,
2432    O: VarValue,
2433    M: FnMut(&T) -> Option<O> + Send + 'static,
2434    I: Fn() -> O + Send + Sync + 'static,
2435{
2436    let me = source.clone();
2437    let map = Arc::new(Mutex::new(map));
2438    types::ContextualizedVar::new(move || {
2439        let other = var(me.with(&mut *map.lock()).unwrap_or_else(&fallback));
2440        let map = map.clone();
2441        me.bind_filter_map(&other, move |i| map.lock()(i)).perm();
2442        other.read_only()
2443    })
2444}
2445fn var_filter_map_mixed<T, O, M, I>(source: &impl Var<T>, map: M, fallback: I) -> BoxedVar<O>
2446where
2447    T: VarValue,
2448    O: VarValue,
2449    M: FnMut(&T) -> Option<O> + Send + 'static,
2450    I: Fn() -> O + Send + Sync + 'static,
2451{
2452    #[cfg(feature = "dyn_closure")]
2453    let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2454    #[cfg(feature = "dyn_closure")]
2455    let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2456
2457    if source.is_contextual() {
2458        var_filter_map_ctx_impl(source, map, fallback).boxed()
2459    } else if source.capabilities().is_always_static() {
2460        LocalVar(source.with(map).unwrap_or_else(fallback)).boxed()
2461    } else {
2462        var_filter_map_impl(source, map, fallback).boxed()
2463    }
2464}
2465
2466fn var_filter_map_bidi<T, O, M, B, I>(source: &impl Var<T>, map: M, map_back: B, fallback: I) -> ArcVar<O>
2467where
2468    T: VarValue,
2469    O: VarValue,
2470    M: FnMut(&T) -> Option<O> + Send + 'static,
2471    B: FnMut(&O) -> Option<T> + Send + 'static,
2472    I: Fn() -> O + Send + Sync + 'static,
2473{
2474    #[cfg(feature = "dyn_closure")]
2475    let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2476    #[cfg(feature = "dyn_closure")]
2477    let map_back: Box<dyn FnMut(&O) -> Option<T> + Send + 'static> = Box::new(map_back);
2478    #[cfg(feature = "dyn_closure")]
2479    let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2480
2481    var_filter_map_bidi_impl(source, map, map_back, fallback)
2482}
2483fn var_filter_map_bidi_impl<T, O, M, B, I>(source: &impl Var<T>, mut map: M, map_back: B, fallback: I) -> ArcVar<O>
2484where
2485    T: VarValue,
2486    O: VarValue,
2487    M: FnMut(&T) -> Option<O> + Send + 'static,
2488    B: FnMut(&O) -> Option<T> + Send + 'static,
2489    I: Fn() -> O + Send + Sync + 'static,
2490{
2491    let mapped = var(source.with(&mut map).unwrap_or_else(&fallback));
2492    source.bind_filter_map_bidi(&mapped, map, map_back).perm();
2493    mapped.hook_any(var_hold_hook(source)).perm();
2494    mapped
2495}
2496fn var_filter_map_bidi_ctx<T, O, M, B, I>(source: &impl Var<T>, map: M, map_back: B, fallback: I) -> types::ContextualizedVar<O>
2497where
2498    T: VarValue,
2499    O: VarValue,
2500    M: FnMut(&T) -> Option<O> + Send + 'static,
2501    B: FnMut(&O) -> Option<T> + Send + 'static,
2502    I: Fn() -> O + Send + Sync + 'static,
2503{
2504    #[cfg(feature = "dyn_closure")]
2505    let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2506    #[cfg(feature = "dyn_closure")]
2507    let map_back: Box<dyn FnMut(&O) -> Option<T> + Send + 'static> = Box::new(map_back);
2508    #[cfg(feature = "dyn_closure")]
2509    let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2510
2511    var_filter_map_bidi_ctx_impl(source, map, map_back, fallback)
2512}
2513fn var_filter_map_bidi_ctx_impl<T, O, M, B, I>(source: &impl Var<T>, map: M, map_back: B, fallback: I) -> types::ContextualizedVar<O>
2514where
2515    T: VarValue,
2516    O: VarValue,
2517    M: FnMut(&T) -> Option<O> + Send + 'static,
2518    B: FnMut(&O) -> Option<T> + Send + 'static,
2519    I: Fn() -> O + Send + Sync + 'static,
2520{
2521    let me = source.clone();
2522    let map = Arc::new(Mutex::new(map));
2523    let map_back = Arc::new(Mutex::new(map_back));
2524    types::ContextualizedVar::new(move || {
2525        let other = var(me.with(&mut *map.lock()).unwrap_or_else(&fallback));
2526        let map = map.clone();
2527        let map_back = map_back.clone();
2528        me.bind_filter_map_bidi(&other, move |i| map.lock()(i), move |o| map_back.lock()(o))
2529            .perm();
2530        other
2531    })
2532}
2533fn var_filter_map_bidi_mixed<T, O, M, B, I>(source: &impl Var<T>, map: M, map_back: B, fallback: I) -> BoxedVar<O>
2534where
2535    T: VarValue,
2536    O: VarValue,
2537    M: FnMut(&T) -> Option<O> + Send + 'static,
2538    B: FnMut(&O) -> Option<T> + Send + 'static,
2539    I: Fn() -> O + Send + Sync + 'static,
2540{
2541    #[cfg(feature = "dyn_closure")]
2542    let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2543    #[cfg(feature = "dyn_closure")]
2544    let map_back: Box<dyn FnMut(&O) -> Option<T> + Send + 'static> = Box::new(map_back);
2545    #[cfg(feature = "dyn_closure")]
2546    let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2547
2548    if source.is_contextual() {
2549        var_filter_map_bidi_ctx_impl(source, map, map_back, fallback).boxed()
2550    } else if source.capabilities().is_always_static() {
2551        LocalVar(source.with(map).unwrap_or_else(fallback)).boxed()
2552    } else {
2553        var_filter_map_bidi_impl(source, map, map_back, fallback).boxed()
2554    }
2555}
2556
2557fn var_map_ref<T, S, O, M>(source: &S, map: M) -> types::MapRef<T, O, S>
2558where
2559    T: VarValue,
2560    S: Var<T>,
2561    O: VarValue,
2562    M: Fn(&T) -> &O + Send + Sync + 'static,
2563{
2564    types::MapRef::new(source.clone(), Arc::new(map))
2565}
2566
2567fn var_map_ref_bidi<T, S, O, M, B>(source: &S, map: M, map_mut: B) -> types::MapRefBidi<T, O, S>
2568where
2569    T: VarValue,
2570    S: Var<T>,
2571    O: VarValue,
2572    M: Fn(&T) -> &O + Send + Sync + 'static,
2573    B: Fn(&mut T) -> &mut O + Send + Sync + 'static,
2574{
2575    types::MapRefBidi::new(source.clone(), Arc::new(map), Arc::new(map_mut))
2576}
2577
2578fn var_easing<T, F>(source: &impl Var<T>, duration: Duration, easing: F) -> ReadOnlyArcVar<T>
2579where
2580    T: VarValue + Transitionable,
2581    F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2582{
2583    let easing_fn = Arc::new(easing);
2584    let easing_var = var(source.get());
2585    let mut _anim_handle = animation::AnimationHandle::dummy();
2586    var_bind(source, &easing_var, move |value, args, easing_var| {
2587        _anim_handle = easing_var.ease(value.clone(), duration, clmv!(easing_fn, |t| easing_fn(t)));
2588        if args.update {
2589            easing_var.update();
2590        }
2591    })
2592    .perm();
2593    easing_var.hook_any(var_hold_hook(source)).perm();
2594    easing_var.read_only()
2595}
2596fn var_easing_ctx<T, F>(source: &impl Var<T>, duration: Duration, easing: F) -> types::ContextualizedVar<T>
2597where
2598    T: VarValue + Transitionable,
2599    F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2600{
2601    let source = source.clone();
2602    let easing_fn = Arc::new(easing);
2603    types::ContextualizedVar::new(move || {
2604        let easing_var = var(source.get());
2605
2606        let easing_fn = easing_fn.clone();
2607        let mut _anim_handle = animation::AnimationHandle::dummy();
2608        var_bind(&source, &easing_var, move |value, args, easing_var| {
2609            let easing_fn = easing_fn.clone();
2610            _anim_handle = easing_var.ease(value.clone(), duration, move |t| easing_fn(t));
2611            if args.update {
2612                easing_var.update();
2613            }
2614        })
2615        .perm();
2616        easing_var.read_only()
2617    })
2618}
2619fn var_easing_mixed<T, F>(source: &impl Var<T>, duration: Duration, easing: F) -> BoxedVar<T>
2620where
2621    T: VarValue + Transitionable,
2622    F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2623{
2624    if source.is_contextual() {
2625        var_easing_ctx(source, duration, easing).boxed()
2626    } else if source.capabilities().is_always_static() {
2627        source.clone().boxed()
2628    } else {
2629        var_easing(source, duration, easing).boxed()
2630    }
2631}
2632
2633fn var_easing_with<T, F, S>(source: &impl Var<T>, duration: Duration, easing: F, sampler: S) -> ReadOnlyArcVar<T>
2634where
2635    T: VarValue + Transitionable,
2636    F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2637    S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static,
2638{
2639    let fns = Arc::new((easing, sampler));
2640    let easing_var = var(source.get());
2641
2642    let mut _anim_handle = animation::AnimationHandle::dummy();
2643    var_bind(source, &easing_var, move |value, args, easing_var| {
2644        _anim_handle = easing_var.ease_with(
2645            value.clone(),
2646            duration,
2647            clmv!(fns, |t| (fns.0)(t)),
2648            clmv!(fns, |t, s| (fns.1)(t, s)),
2649        );
2650        if args.update {
2651            easing_var.update();
2652        }
2653    })
2654    .perm();
2655    easing_var.hook_any(var_hold_hook(source)).perm();
2656    easing_var.read_only()
2657}
2658fn var_easing_with_ctx<T, F, S>(source: &impl Var<T>, duration: Duration, easing: F, sampler: S) -> types::ContextualizedVar<T>
2659where
2660    T: VarValue + Transitionable,
2661    F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2662    S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static,
2663{
2664    let source = source.clone();
2665    let fns = Arc::new((easing, sampler));
2666    types::ContextualizedVar::new(move || {
2667        let easing_var = var(source.get());
2668
2669        let fns = fns.clone();
2670        let mut _anim_handle = animation::AnimationHandle::dummy();
2671        var_bind(&source, &easing_var, move |value, args, easing_var| {
2672            _anim_handle = easing_var.ease_with(
2673                value.clone(),
2674                duration,
2675                clmv!(fns, |t| (fns.0)(t)),
2676                clmv!(fns, |t, s| (fns.1)(t, s)),
2677            );
2678            if args.update {
2679                easing_var.update();
2680            }
2681        })
2682        .perm();
2683        easing_var.read_only()
2684    })
2685}
2686fn var_easing_with_mixed<T, F, S>(source: &impl Var<T>, duration: Duration, easing: F, sampler: S) -> BoxedVar<T>
2687where
2688    T: VarValue + Transitionable,
2689    F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2690    S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static,
2691{
2692    if source.is_contextual() {
2693        var_easing_with_ctx(source, duration, easing, sampler).boxed()
2694    } else if source.capabilities().is_always_static() {
2695        source.clone().boxed()
2696    } else {
2697        var_easing_with(source, duration, easing, sampler).boxed()
2698    }
2699}
2700
2701// Closure type independent of the variable type, hopefully reduces LLVM lines:
2702
2703fn var_get_into<T>(value: &mut T) -> impl FnOnce(&T) + '_
2704where
2705    T: VarValue,
2706{
2707    move |var_value| value.clone_from(var_value)
2708}
2709fn var_get_ne<T>(value: &mut T) -> impl FnOnce(&T) -> bool + '_
2710where
2711    T: VarValue + PartialEq,
2712{
2713    move |var_value| {
2714        let ne = var_value != value;
2715        if ne {
2716            value.clone_from(var_value);
2717        }
2718        ne
2719    }
2720}
2721fn var_set<T>(value: T) -> impl FnOnce(&mut VarModify<T>)
2722where
2723    T: VarValue,
2724{
2725    move |var_value| {
2726        var_value.set(value);
2727    }
2728}
2729fn var_set_from<T, I>(other: I) -> impl FnOnce(&mut VarModify<T>)
2730where
2731    T: VarValue,
2732    I: Var<T>,
2733{
2734    move |vm| {
2735        let other_tag = types::SourceVarTag::new(&other);
2736        let importance = other.modify_importance();
2737        other.with(|other| {
2738            if vm.as_ref() != other {
2739                vm.set(other.clone());
2740                vm.push_tag(other_tag);
2741            }
2742            vm.set_modify_importance(importance);
2743        })
2744    }
2745}
2746
2747fn var_set_from_map<T, Iv, I, M>(other: I, map: M) -> impl FnOnce(&mut VarModify<T>)
2748where
2749    Iv: VarValue,
2750    I: Var<Iv>,
2751    M: FnOnce(&Iv) -> T + Send + 'static,
2752    T: VarValue,
2753{
2754    move |vm| {
2755        let value = other.with(map);
2756        if vm.as_ref() != &value {
2757            vm.set(value);
2758            vm.push_tag(types::SourceVarTag::new(&other));
2759        }
2760        vm.set_modify_importance(other.modify_importance());
2761    }
2762}
2763
2764fn var_set_any<T>(value: Box<dyn AnyVarValue>) -> impl FnOnce(&mut VarModify<T>)
2765where
2766    T: VarValue,
2767{
2768    match value.into_any().downcast::<T>() {
2769        Ok(value) => var_set(*value),
2770        Err(_) => panic!("cannot `set_any`, incompatible type"),
2771    }
2772}
2773
2774fn var_update<T>(var_value: &mut VarModify<T>)
2775where
2776    T: VarValue,
2777{
2778    var_value.update();
2779}
2780
2781fn var_debug<T>(value: &T) -> Txt
2782where
2783    T: VarValue,
2784{
2785    formatx!("{value:?}")
2786}
2787
2788fn var_bind<I, O, V>(
2789    input: &impl Var<I>,
2790    output: &V,
2791    update_output: impl FnMut(&I, &AnyVarHookArgs, <V::Downgrade as WeakVar<O>>::Upgrade) + Send + 'static,
2792) -> VarHandle
2793where
2794    I: VarValue,
2795    O: VarValue,
2796    V: Var<O>,
2797{
2798    if input.capabilities().is_always_static() || output.capabilities().is_always_read_only() {
2799        VarHandle::dummy()
2800    } else {
2801        #[cfg(feature = "dyn_closure")]
2802        let update_output: Box<dyn FnMut(&I, &AnyVarHookArgs, <V::Downgrade as WeakVar<O>>::Upgrade) + Send + 'static> =
2803            Box::new(update_output);
2804
2805        var_bind_ok(input, output.downgrade(), update_output)
2806    }
2807}
2808
2809fn var_bind_ok<I, O, W>(
2810    input: &impl Var<I>,
2811    wk_output: W,
2812    update_output: impl FnMut(&I, &AnyVarHookArgs, W::Upgrade) + Send + 'static,
2813) -> VarHandle
2814where
2815    I: VarValue,
2816    O: VarValue,
2817    W: WeakVar<O>,
2818{
2819    let update_output = Mutex::new(update_output);
2820    input.hook_any(Box::new(move |args| {
2821        if let Some(output) = wk_output.upgrade() {
2822            if output.capabilities().contains(VarCapability::MODIFY) {
2823                if let Some(value) = args.downcast_value::<I>() {
2824                    update_output.lock()(value, args, output);
2825                }
2826            }
2827            true
2828        } else {
2829            false
2830        }
2831    }))
2832}
2833
2834macro_rules! impl_infallible_write {
2835    (for<$T:ident>) => {
2836        /// Infallible [`Var::modify`].
2837        pub fn modify(&self, modify: impl FnOnce(&mut $crate::VarModify<$T>) + Send + 'static) {
2838            Var::modify(self, modify).unwrap()
2839        }
2840
2841        /// Infallible [`Var::set`].
2842        pub fn set(&self, value: impl Into<$T>) {
2843            Var::set(self, value).unwrap()
2844        }
2845
2846        /// Infallible [`AnyVar::update`].
2847        pub fn update(&self) {
2848            AnyVar::update(self).unwrap()
2849        }
2850
2851        /// Infallible [`Var::set_from`].
2852        pub fn set_from<I: Var<$T>>(&self, other: &I) {
2853            Var::set_from(self, other).unwrap()
2854        }
2855
2856        /// Infallible [`Var::set_from_map`].
2857        pub fn set_from_map<Iv, I, M>(&self, other: &I, map: M)
2858        where
2859            Iv: VarValue,
2860            I: Var<Iv>,
2861            M: FnOnce(&Iv) -> $T + Send + 'static,
2862        {
2863            Var::set_from_map(self, other, map).unwrap()
2864        }
2865    };
2866}
2867use impl_infallible_write;