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)]
280pub struct VarIsReadOnlyError {
281    /// Variable capabilities when the request was made.
282    pub capabilities: VarCapability,
283}
284impl fmt::Display for VarIsReadOnlyError {
285    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286        write!(f, "cannot modify variable")
287    }
288}
289impl std::error::Error for VarIsReadOnlyError {}
290
291struct VarHandleData {
292    perm: AtomicBool,
293    action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>,
294}
295
296/// Represents the var side of a [`VarHandle`].
297struct VarHook(Arc<VarHandleData>);
298impl VarHook {
299    /// Calls the handle action, returns `true` if the handle must be retained.
300    pub fn call(&self, args: &AnyVarHookArgs) -> bool {
301        self.is_alive() && (self.0.action)(args)
302    }
303
304    /// If the handle is still held or is permanent.
305    pub fn is_alive(&self) -> bool {
306        Arc::strong_count(&self.0) > 1 || self.0.perm.load(Relaxed)
307    }
308}
309
310/// Handle to a variable hook.
311///
312/// This can represent a widget subscriber, a var binding, var app handler or animation, dropping the handler stops
313/// the behavior it represents.
314#[derive(Clone)]
315#[must_use = "var handle stops the behavior it represents on drop"]
316pub struct VarHandle(Option<Arc<VarHandleData>>);
317impl VarHandle {
318    /// New handle, the `action` depends on the behavior the handle represents.
319    fn new(action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> (VarHandle, VarHook) {
320        let c = Arc::new(VarHandleData {
321            perm: AtomicBool::new(false),
322            action,
323        });
324        (VarHandle(Some(c.clone())), VarHook(c))
325    }
326
327    /// Handle to no variable.
328    pub fn dummy() -> Self {
329        VarHandle(None)
330    }
331
332    /// Returns `true` if the handle is a [`dummy`].
333    ///
334    /// [`dummy`]: VarHandle::dummy
335    pub fn is_dummy(&self) -> bool {
336        self.0.is_none()
337    }
338
339    /// Drop the handle without stopping the behavior it represents.
340    ///
341    /// Note that the behavior can still be stopped by dropping the involved variables.
342    pub fn perm(self) {
343        if let Some(s) = &self.0 {
344            s.perm.store(true, Relaxed);
345        }
346    }
347
348    /// Create a [`VarHandles`] collection with `self` and `other`.
349    pub fn with(self, other: Self) -> VarHandles {
350        [self, other].into()
351    }
352}
353impl PartialEq for VarHandle {
354    fn eq(&self, other: &Self) -> bool {
355        match (&self.0, &other.0) {
356            (None, None) => true,
357            (None, Some(_)) | (Some(_), None) => false,
358            (Some(a), Some(b)) => Arc::ptr_eq(a, b),
359        }
360    }
361}
362impl Eq for VarHandle {}
363impl std::hash::Hash for VarHandle {
364    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
365        let i = match &self.0 {
366            Some(rc) => Arc::as_ptr(rc) as usize,
367            None => 0,
368        };
369        state.write_usize(i);
370    }
371}
372impl fmt::Debug for VarHandle {
373    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
374        let i = match &self.0 {
375            Some(rc) => Arc::as_ptr(rc) as usize,
376            None => 0,
377        };
378        f.debug_tuple("VarHandle").field(&i).finish()
379    }
380}
381impl Default for VarHandle {
382    fn default() -> Self {
383        Self::dummy()
384    }
385}
386
387/// Represents a collection of var handles.
388#[must_use = "var handles stops the behavior they represents on drop"]
389#[derive(Clone, Default)]
390pub struct VarHandles(pub Vec<VarHandle>);
391impl VarHandles {
392    /// Empty collection.
393    pub const fn dummy() -> Self {
394        VarHandles(vec![])
395    }
396
397    /// Returns `true` if empty or all handles are dummy.
398    pub fn is_dummy(&self) -> bool {
399        self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
400    }
401
402    /// Drop all handles without stopping their behavior.
403    pub fn perm(self) {
404        for handle in self.0 {
405            handle.perm()
406        }
407    }
408
409    /// Add the `other` handle to the collection, if it is not dummy.
410    pub fn push(&mut self, other: VarHandle) -> &mut Self {
411        if !other.is_dummy() {
412            self.0.push(other);
413        }
414        self
415    }
416
417    /// Drop all handles.
418    pub fn clear(&mut self) {
419        self.0.clear()
420    }
421}
422impl FromIterator<VarHandle> for VarHandles {
423    fn from_iter<T: IntoIterator<Item = VarHandle>>(iter: T) -> Self {
424        VarHandles(iter.into_iter().filter(|h| !h.is_dummy()).collect())
425    }
426}
427impl<const N: usize> From<[VarHandle; N]> for VarHandles {
428    fn from(handles: [VarHandle; N]) -> Self {
429        handles.into_iter().collect()
430    }
431}
432impl Extend<VarHandle> for VarHandles {
433    fn extend<T: IntoIterator<Item = VarHandle>>(&mut self, iter: T) {
434        for handle in iter {
435            self.push(handle);
436        }
437    }
438}
439impl IntoIterator for VarHandles {
440    type Item = VarHandle;
441
442    type IntoIter = std::vec::IntoIter<VarHandle>;
443
444    fn into_iter(self) -> Self::IntoIter {
445        self.0.into_iter()
446    }
447}
448
449/// Arc value that implements equality by pointer comparison.
450///
451/// This type allows external types that are only `Debug + Send + Sync` to become
452/// a full [`VarValue`] to be allowed as a variable value.
453pub struct ArcEq<T: fmt::Debug + Send + Sync>(pub Arc<T>);
454impl<T: fmt::Debug + Send + Sync> ops::Deref for ArcEq<T> {
455    type Target = Arc<T>;
456
457    fn deref(&self) -> &Self::Target {
458        &self.0
459    }
460}
461impl<T: fmt::Debug + Send + Sync> ArcEq<T> {
462    /// Constructs a new `ArcEq<T>`.
463    pub fn new(value: T) -> Self {
464        Self(Arc::new(value))
465    }
466}
467impl<T: fmt::Debug + Send + Sync> PartialEq for ArcEq<T> {
468    fn eq(&self, other: &Self) -> bool {
469        Arc::ptr_eq(&self.0, &other.0)
470    }
471}
472impl<T: fmt::Debug + Send + Sync> Eq for ArcEq<T> {}
473impl<T: fmt::Debug + Send + Sync> Clone for ArcEq<T> {
474    fn clone(&self) -> Self {
475        Self(Arc::clone(&self.0))
476    }
477}
478impl<T: fmt::Debug + Send + Sync> fmt::Debug for ArcEq<T> {
479    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
480        fmt::Debug::fmt(&*self.0, f)
481    }
482}
483
484/// Methods of [`Var<T>`] that are object safe.
485///
486/// This trait is [sealed] and cannot be implemented for types outside of this crate.
487///
488/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
489pub trait AnyVar: Any + Send + Sync + crate::private::Sealed {
490    /// Clone the variable into a type erased box.
491    ///
492    /// This is never [`BoxedVar<T>`], that is not a double box.
493    fn clone_any(&self) -> BoxedAnyVar;
494
495    /// Access to `dyn Any` methods.
496    fn as_any(&self) -> &dyn Any;
497
498    /// Access to `dyn Any` methods, on the underlying variable type if boxed.
499    fn as_unboxed_any(&self) -> &dyn Any;
500
501    /// Access to `Box<dyn Any>` methods, with the [`BoxedVar<T>`] type.
502    ///
503    /// This is a double-boxed to allow downcast to [`BoxedVar<T>`].
504    fn double_boxed_any(self: Box<Self>) -> Box<dyn Any>;
505
506    /// Gets the [`TypeId`] of `T` in `Var<T>`.
507    fn var_type_id(&self) -> TypeId;
508
509    /// Get a clone of the current value, with type erased.
510    fn get_any(&self) -> Box<dyn AnyVarValue>;
511
512    /// Visit the current value of the variable.
513    fn with_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue));
514
515    /// Visit the current value of the variable, if it [`is_new`].
516    ///
517    /// [`is_new`]: AnyVar::is_new
518    fn with_new_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) -> bool;
519
520    /// Schedule a new `value` for the variable, it will be set in the end of the current app update.
521    ///
522    /// # Panics
523    ///
524    /// Panics if the `value` is not of the same [`var_type_id`].
525    ///
526    /// [`var_type_id`]: AnyVar::var_type_id
527    fn set_any(&self, value: Box<dyn AnyVarValue>) -> Result<(), VarIsReadOnlyError>;
528
529    /// Last update ID a variable was modified, if the ID is equal to [`VARS.update_id`] the variable is *new*.
530    ///
531    /// [`VARS.update_id`]: VARS::update_id
532    fn last_update(&self) -> VarUpdateId;
533
534    /// If the variable represents different values depending on the context where they are read.
535    fn is_contextual(&self) -> bool;
536
537    /// Flags that indicate what operations the variable is capable of in this update.
538    fn capabilities(&self) -> VarCapability;
539
540    /// Gets if the [`last_update`] is the current update, meaning the variable value just changed.
541    ///
542    /// Note that this is only reliable in threads synchronized with the UI update, this status can change
543    /// at any time when called from other app threads.
544    ///
545    /// [`last_update`]: AnyVar::last_update
546    fn is_new(&self) -> bool {
547        VARS.update_id() == self.last_update()
548    }
549
550    /// If the variable current value was set by an active animation.
551    ///
552    /// The variable [`is_new`] when this changes to `true`, but it **may not be new** when the value changes to `false`.
553    /// If the variable is not updated at the last frame of the animation that has last set it, it will not update
554    /// just because that animation has ended. You can use [`hook_animation_stop`] to get a notification when the
555    /// last animation stops, or use [`wait_animation`] to get a future that is ready when `is_animating` changes
556    /// from `true` to `false`.
557    ///
558    /// [`is_new`]: AnyVar::is_new
559    /// [`hook_animation_stop`]: AnyVar::hook_animation_stop
560    /// [`wait_animation`]: Var::wait_animation
561    fn is_animating(&self) -> bool;
562
563    /// Gets a value that indicates the *importance* clearance that is needed to modify this variable.
564    ///
565    /// If the variable has the [`MODIFY`] capability, `modify` requests will return `Ok(())`, but they will be ignored
566    /// if the [`VARS.current_modify`] importance is less than the variable's at the moment the request is made.
567    ///
568    /// Note that [`VARS.current_modify`] outside animations always overrides this value, so direct modify requests
569    /// always override running animations.
570    ///
571    /// This is the mechanism that ensures that only the latest animation has *control* of the variable value, most animations
572    /// check this value and automatically cancel if overridden, but event assigns from custom animations made using [`VARS.animate`]
573    /// are ignored if the variable is modified from a newer source then the animation.
574    ///
575    /// If the variable does not have [`MODIFY`] capability the value returned is undefined.
576    ///
577    /// [`MODIFY`]: VarCapability::MODIFY
578    /// [`VARS.current_modify`]: VARS::current_modify
579    /// [`VARS.animate`]: VARS::animate
580    fn modify_importance(&self) -> usize;
581
582    /// Setups a callback for just after the variable value update is applied, the closure runs in the root app context, just like
583    /// the `modify` closure. The closure can return if it is retained after each call. If you modify another variable in a
584    /// hook the modification applies in the same update, variable mapping and binding is implemented using hooks.
585    ///
586    /// The variable store a weak reference to the callback if it has the `MODIFY` or `CAPS_CHANGE` capabilities, otherwise
587    /// the callback is discarded and [`VarHandle::dummy`] returned.
588    fn hook_any(&self, pos_modify_action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> VarHandle;
589
590    /// Register a `handler` to be called when the current animation stops.
591    ///
592    /// Note that the `handler` is owned by the animation, not the variable, it will only be called/dropped when the
593    /// animation stops.
594    ///
595    /// Returns the `handler` as an error if the variable is not animating. Note that if you are interacting
596    /// with the variable from a non-UI thread the variable can stops animating between checking [`is_animating`]
597    /// and registering the hook, in this case the `handler` will be returned as an error as well.
598    ///
599    /// [`modify_importance`]: AnyVar::modify_importance
600    /// [`is_animating`]: AnyVar::is_animating
601    fn hook_animation_stop(&self, handler: Box<dyn FnOnce() + Send>) -> Result<(), Box<dyn FnOnce() + Send>>;
602
603    /// Gets the number of strong references to the variable.
604    ///
605    /// This is the [`Arc::strong_count`] for *Arc* variables, the context var count for [`ContextVar<T>`], the boxed var count
606    /// for [`BoxedVar<T>`] and `0` for [`LocalVar<T>`].
607    fn strong_count(&self) -> usize;
608
609    /// Gets the number of weak references to the variable.
610    ///
611    /// This is the [`Arc::weak_count`] for *Arc* variables, the context var count for [`ContextVar<T>`], the boxed var count
612    /// for [`BoxedVar<T>`] and `0` for [`LocalVar<T>`].
613    fn weak_count(&self) -> usize;
614
615    /// Gets a clone of the represented var from [`ContextVar<T>`], gets a clone of `self` for other var types.
616    fn actual_var_any(&self) -> BoxedAnyVar;
617
618    /// Create a weak reference to this *Arc* variable.
619    ///
620    /// The weak reference is made to the [`actual_var`], if the actual var is a [`LocalVar<T>`]
621    /// a [`types::WeakArcVar<T>`] is returned, for *Arc* vars an actual weak reference is made.
622    ///
623    /// [`actual_var`]: Var::actual_var
624    fn downgrade_any(&self) -> BoxedAnyWeakVar;
625
626    /// Var *pointer*, that can be used to identify if two variables point to the same *rc* or *context*.
627    ///
628    /// If two of these values are equal, both variables point to the same *rc* or *context* at the moment of comparison.
629    /// Note that this is only for comparison, trying to access the variable internals is never safe.
630    fn var_ptr(&self) -> VarPtr;
631
632    /// Get the value as a debug [`Txt`].
633    ///
634    /// [`Txt`]: Txt
635    fn get_debug(&self) -> Txt;
636
637    /// Schedule a variable update, even if the value does no change.
638    ///
639    /// Usually variables only notify update if the value is changed to a different one, calling
640    /// this method flags the variable to notify.
641    fn update(&self) -> Result<(), VarIsReadOnlyError>;
642
643    /// Create a [`map`] that converts from `T` to a [`Txt`] debug print.
644    ///
645    /// [`map`]: Var::map
646    /// [`Txt`]: Txt
647    fn map_debug(&self) -> BoxedVar<Txt>;
648
649    /// Hold the variable in memory until the app exit.
650    fn perm(&self) {
651        VARS.perm(self.clone_any());
652    }
653
654    /// Keep `other` alive until the handle or `self` are dropped.
655    fn hold_any(&self, value: Box<dyn Any + Send + Sync>) -> VarHandle {
656        self.hook_any(hold_any_impl(value))
657    }
658}
659// separate function to avoid code bloat
660fn hold_any_impl(value: Box<dyn Any + Send + Sync>) -> Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync> {
661    Box::new(move |_| {
662        let _hold = &value;
663        true
664    })
665}
666
667#[derive(Debug)]
668enum VarPtrData {
669    Static(AppLocalId),
670    Arc(*const ()),
671    NeverEq,
672}
673impl PartialEq for VarPtrData {
674    fn eq(&self, other: &Self) -> bool {
675        match (self, other) {
676            (Self::Static(l0), Self::Static(r0)) => l0 == r0,
677            (Self::Arc(l0), Self::Arc(r0)) => l0 == r0,
678            _ => false,
679        }
680    }
681}
682
683/// Represents an [`AnyVar`] *pointer* that can be used for comparison.
684///
685/// If two of these values are equal, both variables point to the same *arc* or *context* at the moment of comparison.
686pub struct VarPtr<'a> {
687    _lt: std::marker::PhantomData<&'a ()>,
688    eq: VarPtrData,
689}
690impl<'a> VarPtr<'a> {
691    /// Gets the pointer.
692    ///
693    /// # Safety
694    ///
695    /// Trying to read or write values using this pointer is **never safe**.
696    ///
697    /// Trying to identify a variable using the raw pointer is only valid if you know the variable is still alive.
698    /// The variable could be dropped and new one allocated at the same address.
699    pub fn raw_pointer(&self) -> *const () {
700        match self.eq {
701            VarPtrData::Arc(p) => p,
702            VarPtrData::Static(p) => p.get() as *const (),
703            VarPtrData::NeverEq => std::ptr::null(),
704        }
705    }
706
707    fn new_arc<T: ?Sized>(rc: &'a Arc<T>) -> Self {
708        Self {
709            _lt: std::marker::PhantomData,
710            eq: VarPtrData::Arc(Arc::as_ptr(rc) as _),
711        }
712    }
713
714    fn new_ctx_local<T: Send + Sync>(tl: &'static ContextLocal<T>) -> Self {
715        Self {
716            _lt: std::marker::PhantomData,
717            eq: VarPtrData::Static(tl.id()),
718        }
719    }
720
721    fn new_never_eq(_: &'a impl Any) -> Self {
722        Self {
723            _lt: std::marker::PhantomData,
724            eq: VarPtrData::NeverEq,
725        }
726    }
727}
728impl PartialEq for VarPtr<'_> {
729    fn eq(&self, other: &Self) -> bool {
730        self.eq == other.eq
731    }
732}
733impl fmt::Debug for VarPtr<'_> {
734    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
735        if f.alternate() {
736            f.debug_tuple("VarPtr").field(&self.eq).finish()
737        } else {
738            fmt::Debug::fmt(&self.eq, f)
739        }
740    }
741}
742
743/// Represents a weak reference to an [`AnyVar`].
744pub trait AnyWeakVar: Any + Send + Sync + crate::private::Sealed {
745    /// Clone the weak reference.
746    fn clone_any(&self) -> BoxedAnyWeakVar;
747
748    /// Access to `dyn Any` methods.
749    fn as_any(&self) -> &dyn Any;
750
751    /// Gets the number of strong references to the variable.
752    ///
753    /// This is the same as [`AnyVar::strong_count`].
754    fn strong_count(&self) -> usize;
755
756    /// Gets the number of weak references to the variable.
757    ///
758    /// This is the same as [`AnyVar::weak_count`].
759    fn weak_count(&self) -> usize;
760
761    /// Upgrade to a strong [`AnyVar`] clone.
762    ///
763    /// Returns `None` if the [`strong_count`] is zero.
764    ///
765    /// [`strong_count`]: AnyWeakVar
766    fn upgrade_any(&self) -> Option<BoxedAnyVar>;
767}
768
769/// Represents a weak reference to a [`Var<T>`].
770pub trait WeakVar<T: VarValue>: AnyWeakVar + Clone {
771    /// Output of [`WeakVar::upgrade`].
772    type Upgrade: Var<T>;
773
774    /// Upgrade to a strong [`BoxedVar<T>`] clone.
775    ///
776    /// Returns `None` if the [`strong_count`] is zero.
777    ///
778    /// [`strong_count`]: AnyWeakVar
779    fn upgrade(&self) -> Option<Self::Upgrade>;
780
781    /// Gets the weak reference a as [`BoxedWeakVar<T>`], does not double box.
782    fn boxed(self) -> BoxedWeakVar<T>
783    where
784        Self: Sized,
785    {
786        Box::new(self)
787    }
788}
789
790/// A value-to-var conversion that consumes the value.
791///
792/// Every [`Var<T>`] implements this to convert to itself, every [`VarValue`] implements this to
793/// convert to a [`LocalVar<T>`].
794///
795/// This trait is used by most properties, it allows then to accept literal values, variables and context variables
796/// all with a single signature. Together with [`Var<T>`] this gives properties great flexibility of usage, at zero-cost. Widget
797/// `when` blocks also use [`IntoVar<T>`] to support *changing* the property value depending on the widget state.
798///
799/// Value types can also manually implement this to support a shorthand literal syntax for when they are used in properties,
800/// this converts the *shorthand value* like a tuple into the actual value type and wraps it into a variable, usually [`LocalVar`]
801/// too. They can implement the trait multiple times to support different shorthand syntaxes or different types in the shorthand
802/// value.
803#[diagnostic::on_unimplemented(
804    note = "`IntoVar<T>` is implemented for all `T: VarValue`",
805    note = "`IntoVar<T>` is implemented for all `V: Var<T>`"
806)]
807pub trait IntoVar<T: VarValue> {
808    /// Variable type that will wrap the `T` value.
809    ///
810    /// This is the [`LocalVar`] for most types or `Self` for variable types.
811    type Var: Var<T>;
812
813    /// Converts the source value into a var.
814    fn into_var(self) -> Self::Var;
815
816    /// Converts into [`BoxedVar<T>`].
817    ///
818    /// This method exists to help the type system infer the type in this scenario:
819    ///
820    /// ```
821    /// # use zng_var::*;
822    /// # let bar = true;
823    /// # let BAR_VAR = var(true);
824    /// #
825    /// fn foo(foo: impl IntoVar<bool>) { }
826    ///
827    /// foo(if bar {
828    ///     BAR_VAR.map(|b| !*b).boxed()
829    /// } else {
830    ///     true.into_boxed_var()
831    /// });
832    /// ```
833    ///
834    /// 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()`
835    /// causes the type inference to fail, requiring us to write `IntoVar::<bool>::into_var(true).boxed()`.
836    fn into_boxed_var(self) -> BoxedVar<T>
837    where
838        Self: Sized,
839    {
840        self.into_var().boxed()
841    }
842}
843
844/// Represents the current value in a [`Var::modify`] handler.
845pub struct VarModify<'a, T: VarValue> {
846    current_value: &'a T,
847    value: Cow<'a, T>,
848    update: bool,
849    tags: Vec<Box<dyn AnyVarValue>>,
850    custom_importance: Option<usize>,
851}
852impl<'a, T: VarValue> VarModify<'a, T> {
853    /// Replace the value.
854    ///
855    /// The variable will update if the new value is not equal to the previous after all modify closures apply.
856    pub fn set(&mut self, new_value: T) {
857        self.value = Cow::Owned(new_value);
858    }
859
860    /// Notify an update, even if the value does not actually change.
861    pub fn update(&mut self) {
862        self.update = true;
863    }
864
865    /// Returns a mutable reference for modification.
866    ///
867    /// Note that this clones the current value if this is the first modify closure requesting it.
868    ///
869    /// The variable will update if the new value is not equal to the previous after all modify closures apply.
870    pub fn to_mut(&mut self) -> &mut T {
871        self.value.to_mut()
872    }
873
874    /// Custom tags that will be shared with the var hooks if the value updates.
875    ///
876    /// The tags where set by previous modify closures or this one during this update cycle, so
877    /// tags can also be used to communicate between modify closures.
878    pub fn tags(&self) -> &[Box<dyn AnyVarValue>] {
879        &self.tags
880    }
881
882    /// Add a custom tag object that will be shared with the var hooks if the value updates.
883    pub fn push_tag(&mut self, tag: impl AnyVarValue) {
884        self.tags.push(Box::new(tag));
885    }
886
887    /// Add all custom tags.
888    pub fn push_tags(&mut self, tags: Vec<Box<dyn AnyVarValue>>) {
889        if self.tags.is_empty() {
890            self.tags = tags;
891        } else {
892            self.tags.extend(tags);
893        }
894    }
895
896    /// Sets a custom [`AnyVar::modify_importance`] value.
897    ///
898    /// Note that the modify info is already automatically set, using a custom value here
899    /// can easily break all future modify requests for this variable. The importance is set even if the
900    /// variable does not update (no actual value change or update request).
901    pub fn set_modify_importance(&mut self, importance: usize) {
902        self.custom_importance = Some(importance);
903    }
904
905    /// New from current value.
906    pub fn new(current_value: &'a T) -> Self {
907        Self {
908            current_value,
909            value: Cow::Borrowed(current_value),
910            update: false,
911            tags: vec![],
912            custom_importance: None,
913        }
914    }
915
916    /// Returns `(notify, new_value, update, tags, custom_importance)`.
917    pub fn finish(self) -> (bool, Option<T>, bool, Vec<Box<dyn AnyVarValue>>, Option<usize>) {
918        match self.value {
919            Cow::Borrowed(_) => {
920                if self.update {
921                    return (true, None, true, self.tags, self.custom_importance);
922                }
923            }
924            Cow::Owned(v) => {
925                if self.update || self.current_value != &v {
926                    return (true, Some(v), self.update, self.tags, self.custom_importance);
927                }
928            }
929        }
930        (false, None, false, vec![], self.custom_importance)
931    }
932}
933impl<T: VarValue> ops::Deref for VarModify<'_, T> {
934    type Target = T;
935
936    fn deref(&self) -> &Self::Target {
937        self.as_ref()
938    }
939}
940impl<T: VarValue> std::convert::AsRef<T> for VarModify<'_, T> {
941    fn as_ref(&self) -> &T {
942        &self.value
943    }
944}
945
946/// Arguments for [`AnyVar::hook_any`].
947pub struct AnyVarHookArgs<'a> {
948    value: &'a dyn AnyVarValue,
949    update: bool,
950    tags: &'a [Box<dyn AnyVarValue>],
951}
952impl<'a> AnyVarHookArgs<'a> {
953    /// New from updated value and custom tag.
954    pub fn new(value: &'a dyn AnyVarValue, update: bool, tags: &'a [Box<dyn AnyVarValue>]) -> Self {
955        Self { value, update, tags }
956    }
957
958    /// Reference the updated value.
959    pub fn value(&self) -> &'a dyn AnyVarValue {
960        self.value
961    }
962
963    /// If update was explicitly requested.
964    ///
965    /// Note that bindings/mappings propagate this update request.
966    pub fn update(&self) -> bool {
967        self.update
968    }
969
970    /// Value type ID.
971    pub fn value_type(&self) -> TypeId {
972        self.value.as_any().type_id()
973    }
974
975    /// Custom tag objects.
976    pub fn tags(&self) -> &[Box<dyn AnyVarValue>] {
977        self.tags
978    }
979
980    /// Clone the custom tag objects set by the code that updated the value.
981    pub fn tags_vec(&self) -> Vec<Box<dyn AnyVarValue>> {
982        self.tags.iter().map(|t| (*t).clone_boxed()).collect()
983    }
984
985    /// Reference the value, if it is of type `T`.
986    pub fn downcast_value<T: VarValue>(&self) -> Option<&T> {
987        self.value.as_any().downcast_ref()
988    }
989
990    /// Reference all custom tag values of type `T`.
991    pub fn downcast_tags<T: VarValue>(&self) -> impl Iterator<Item = &T> + '_ {
992        self.tags.iter().filter_map(|t| (*t).as_any().downcast_ref::<T>())
993    }
994
995    /// Try cast to strongly typed args.
996    pub fn as_strong<T: VarValue>(&self) -> Option<VarHookArgs<T>> {
997        if TypeId::of::<T>() == self.value_type() {
998            Some(VarHookArgs {
999                any: self,
1000                _t: PhantomData,
1001            })
1002        } else {
1003            None
1004        }
1005    }
1006}
1007
1008/// Arguments for [`Var::hook`].
1009pub struct VarHookArgs<'a, T: VarValue> {
1010    any: &'a AnyVarHookArgs<'a>,
1011    _t: PhantomData<&'a T>,
1012}
1013impl<'a, T: VarValue> VarHookArgs<'a, T> {
1014    /// Reference the updated value.
1015    pub fn value(&self) -> &'a T {
1016        self.any.value.as_any().downcast_ref::<T>().unwrap()
1017    }
1018}
1019impl<'a, T: VarValue> ops::Deref for VarHookArgs<'a, T> {
1020    type Target = AnyVarHookArgs<'a>;
1021
1022    fn deref(&self) -> &Self::Target {
1023        self.any
1024    }
1025}
1026
1027/// Args for [`Var::trace_value`].
1028pub struct TraceValueArgs<'a, T: VarValue> {
1029    args: &'a AnyVarHookArgs<'a>,
1030    _type: PhantomData<&'a T>,
1031}
1032impl<'a, T: VarValue> ops::Deref for TraceValueArgs<'a, T> {
1033    type Target = AnyVarHookArgs<'a>;
1034
1035    fn deref(&self) -> &Self::Target {
1036        self.args
1037    }
1038}
1039impl<'a, T: VarValue> TraceValueArgs<'a, T> {
1040    /// Strongly-typed reference to the new value.
1041    pub fn value(&self) -> &'a T {
1042        self.args.downcast_value::<T>().unwrap()
1043    }
1044}
1045
1046/// Represents an observable value.
1047///
1048/// Variable types can have different capabilities, all can provide a value, in some the value can update, some
1049/// are read-only others allow modifying the value. Variables can also be contextual, meaning they have a different
1050/// value depending on the context where they are used. This trait covers all these capabilities, together with
1051/// [`IntoVar<T>`] it enables properties to be very flexible on what input they accept.
1052///
1053/// See [`AnyVar`] for the object safe part of variables.
1054///
1055/// This trait is [sealed] and cannot be implemented for types outside of this crate.
1056///
1057/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
1058pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
1059    /// Output of [`Var::read_only`].
1060    type ReadOnly: Var<T>;
1061
1062    /// Output of [`Var::actual_var`].
1063    type ActualVar: Var<T>;
1064
1065    /// Output of [`Var::downgrade`].
1066    type Downgrade: WeakVar<T>;
1067
1068    /// Output of [`Var::map`].
1069    type Map<O: VarValue>: Var<O>;
1070
1071    /// Output of [`Var::map_bidi`].
1072    type MapBidi<O: VarValue>: Var<O>;
1073
1074    /// Output of [`Var::flat_map`].
1075    type FlatMap<O: VarValue, V: Var<O>>: Var<O>;
1076
1077    /// Output of [`Var::filter_map`].
1078    type FilterMap<O: VarValue>: Var<O>;
1079
1080    /// Output of [`Var::filter_map_bidi`].
1081    type FilterMapBidi<O: VarValue>: Var<O>;
1082
1083    /// Output of [`Var::map_ref`].
1084    type MapRef<O: VarValue>: Var<O>;
1085
1086    /// Output of [`Var::map_ref_bidi`].
1087    type MapRefBidi<O: VarValue>: Var<O>;
1088
1089    /// Output of [`Var::easing`].
1090    type Easing: Var<T>;
1091
1092    /// Visit the current value of the variable.
1093    fn with<R, F>(&self, read: F) -> R
1094    where
1095        F: FnOnce(&T) -> R;
1096
1097    /// Schedule a variable update, it will be applied on the end of the current app update.
1098    fn modify<F>(&self, modify: F) -> Result<(), VarIsReadOnlyError>
1099    where
1100        F: FnOnce(&mut VarModify<T>) + Send + 'static;
1101
1102    /// Gets the variable as a [`BoxedVar<T>`], does not double box.
1103    fn boxed(self) -> BoxedVar<T>
1104    where
1105        Self: Sized,
1106    {
1107        Box::new(self)
1108    }
1109
1110    /// Gets the variable as a [`BoxedAnyVar`], does not double box.
1111    fn boxed_any(self) -> BoxedAnyVar
1112    where
1113        Self: Sized,
1114    {
1115        Box::new(self)
1116    }
1117
1118    /// Gets the current *inner* var represented by this var. This can be the same var or a context var.
1119    fn actual_var(self) -> Self::ActualVar;
1120
1121    /// Create a weak reference to this *Arc* variable.
1122    fn downgrade(&self) -> Self::Downgrade;
1123
1124    /// Convert this variable to the value, if possible moves the value, if it is shared clones it.
1125    fn into_value(self) -> T;
1126
1127    /// Gets a clone of the var that is always read-only.
1128    ///
1129    /// The returned variable can still update if `self` is modified, but it does not have the `MODIFY` capability.
1130    fn read_only(&self) -> Self::ReadOnly;
1131
1132    /// Setups a callback for just after the variable value update is applied, the closure runs in the root app context, just like
1133    /// the `modify` closure. The closure can return if it is retained after each call. If you modify another variable in a
1134    /// hook the modification applies in the same update, variable mapping and binding is implemented using hooks.
1135    ///
1136    /// The variable store a weak reference to the callback if it has the `MODIFY` or `CAPS_CHANGE` capabilities, otherwise
1137    /// the callback is discarded and [`VarHandle::dummy`] returned.
1138    fn hook(&self, pos_modify_action: impl Fn(&VarHookArgs<T>) -> bool + Send + Sync + 'static) -> VarHandle {
1139        self.hook_any(Box::new(move |a| pos_modify_action(&a.as_strong().unwrap())))
1140    }
1141
1142    /// Awaits for the [`last_update`] to change.
1143    ///
1144    /// Note that [`is_new`] will be `true` when the future elapses only when polled
1145    /// in sync with the UI, but it will elapse in any thread when the variable updates after the future is instantiated.
1146    ///
1147    /// Note that outside of the UI tree there is no variable synchronization across multiple var method calls, so
1148    /// a sequence of `get(); wait_update().await; get();` can miss a value between `get` and `wait_update`. The returned
1149    /// future captures the [`last_update`] at the moment this method is called, this can be leveraged by double-checking to
1150    /// avoid race conditions, see the [`wait_value`] default implementation for more details.
1151    ///
1152    /// [`get`]: Var::get
1153    /// [`wait_value`]: Var::wait_value
1154    /// [`last_update`]: AnyVar::last_update
1155    /// [`is_new`]: AnyVar::is_new
1156    fn wait_update(&self) -> impl Future<Output = VarUpdateId> + Send + Sync {
1157        crate::future::WaitUpdateFut::new(self)
1158    }
1159
1160    /// Awaits for [`is_animating`] to change from `true` to `false`.
1161    ///
1162    /// If the variable is not animating at the moment of this call the future will await until the animation starts and stops.
1163    ///
1164    /// [`is_animating`]: AnyVar::is_animating
1165    fn wait_animation(&self) -> impl Future<Output = ()> + Send + Sync {
1166        crate::future::WaitIsNotAnimatingFut::new(self)
1167    }
1168
1169    ///Awaits for a value that passes the `predicate`.
1170    fn wait_value(&self, predicate: impl Fn(&T) -> bool + Send + Sync) -> impl Future<Output = ()> + Send + Sync {
1171        async move {
1172            while !self.with(&predicate) {
1173                let future = self.wait_update();
1174                if self.with(&predicate) {
1175                    break;
1176                }
1177                future.await;
1178            }
1179        }
1180    }
1181
1182    /// Visit the current value of the variable, if it [`is_new`].
1183    ///
1184    /// [`is_new`]: AnyVar::is_new
1185    fn with_new<R, F>(&self, read: F) -> Option<R>
1186    where
1187        F: FnOnce(&T) -> R,
1188    {
1189        if self.is_new() { Some(self.with(read)) } else { None }
1190    }
1191
1192    /// Get a clone of the current value.
1193    fn get(&self) -> T {
1194        self.with(Clone::clone)
1195    }
1196
1197    /// Gets the value as a display [`Txt`].
1198    ///
1199    /// [`Txt`]: Txt
1200    fn get_txt(&self) -> Txt
1201    where
1202        T: fmt::Display,
1203    {
1204        self.with(ToTxt::to_txt)
1205    }
1206
1207    /// Gets the value as a display [`String`].
1208    fn get_string(&self) -> String
1209    where
1210        T: fmt::Display,
1211    {
1212        self.with(ToString::to_string)
1213    }
1214
1215    /// Get a clone of the current value into `value`.
1216    fn get_into(&self, value: &mut T) {
1217        self.with(var_get_into(value))
1218    }
1219
1220    /// Get a clone of the current value into `value` if the current value is not equal to it.
1221    fn get_ne(&self, value: &mut T) -> bool {
1222        self.with(var_get_ne(value))
1223    }
1224
1225    /// Get a clone of the current value, if it [`is_new`].
1226    ///
1227    /// [`is_new`]: AnyVar::is_new
1228    fn get_new(&self) -> Option<T> {
1229        if self.is_new() { Some(self.with(Clone::clone)) } else { None }
1230    }
1231
1232    /// Get a clone of the current value into `value` if the current value [`is_new`].
1233    ///
1234    /// [`is_new`]: AnyVar::is_new
1235    fn get_new_into(&self, value: &mut T) -> bool {
1236        let is_new = self.is_new();
1237        if is_new {
1238            self.with(var_get_into(value));
1239        }
1240        is_new
1241    }
1242
1243    /// Get a clone of the current value into `value` if the variable value [`is_new`] and not equal to the `value`.
1244    ///
1245    /// [`is_new`]: AnyVar::is_new
1246    fn get_new_ne(&self, value: &mut T) -> bool {
1247        self.is_new() && self.get_ne(value)
1248    }
1249
1250    /// Schedule a new `value` for the variable, it will be set in the end of the current app update.
1251    fn set<I>(&self, value: I) -> Result<(), VarIsReadOnlyError>
1252    where
1253        I: Into<T>,
1254    {
1255        self.modify(var_set(value.into()))
1256    }
1257
1258    /// Schedule a new `value` for the variable, it will be set in the end of the current app update to the updated
1259    /// value of `other`, so if the other var has already scheduled an update, the updated value will be used.
1260    ///  
1261    /// This can be used in combination with binding to create a binding that starts with synchronized values.
1262    fn set_from<I>(&self, other: &I) -> Result<(), VarIsReadOnlyError>
1263    where
1264        I: Var<T>,
1265    {
1266        if other.capabilities().is_always_static() {
1267            self.set(other.get())
1268        } else {
1269            self.modify(var_set_from(other.clone().actual_var()))
1270        }
1271    }
1272
1273    /// Set from `other` value at the time of update, mapped to the type of `self`.
1274    fn set_from_map<Iv, I, M>(&self, other: &I, map: M) -> Result<(), VarIsReadOnlyError>
1275    where
1276        Iv: VarValue,
1277        I: Var<Iv>,
1278        M: FnOnce(&Iv) -> T + Send + 'static,
1279    {
1280        if other.capabilities().is_always_static() {
1281            self.set(other.with(map))
1282        } else {
1283            self.modify(var_set_from_map(other.clone().actual_var(), map))
1284        }
1285    }
1286
1287    /// Create a var that redirects to this variable until the first value update, then it behaves like a [`ArcVar<T>`].
1288    ///
1289    /// The return variable is *clone-on-write* and has the `MODIFY` capability independent of the source capabilities, when
1290    /// a modify request is made the source value is cloned and offered for modification, if modified the source variable is dropped
1291    /// 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
1292    /// continues to redirect to the source variable.
1293    fn cow(&self) -> types::ArcCowVar<T, Self> {
1294        types::ArcCowVar::new(self.clone())
1295    }
1296
1297    /// Creates a var that maps from this variable.
1298    ///
1299    /// The `map` closure is called once on initialization, and then once every time
1300    /// the source variable updates.
1301    ///
1302    /// The mapping variable is read-only, you can use [`map_bidi`] to map back.
1303    ///
1304    /// Note that the mapping var can be [contextualized] for context vars, meaning the map binding will initialize in
1305    /// the fist usage context, not the creation context, so `property = CONTEXT_VAR.map(|&b|!b);` will bind with
1306    /// the `CONTEXT_VAR` in the `property` context, not the property instantiation. The `map` closure itself runs in
1307    /// the root app context, trying to read other context variables inside it will only read the default value.
1308    ///
1309    /// For other variables types the `map` can run once in the caller context.
1310    ///
1311    /// If `self` can change the output variable will keep it alive, this is to support chaining maps.
1312    ///
1313    /// [`map_bidi`]: Var::map_bidi
1314    /// [contextualized]: types::ContextualizedVar
1315    fn map<O, M>(&self, map: M) -> Self::Map<O>
1316    where
1317        O: VarValue,
1318        M: FnMut(&T) -> O + Send + 'static;
1319
1320    /// Creates a [`map`] that converts from `T` to `O` using [`Into<O>`].
1321    ///
1322    /// [`map`]: Var::map
1323    fn map_into<O>(&self) -> Self::Map<O>
1324    where
1325        O: VarValue,
1326        T: Into<O>,
1327    {
1328        self.map(|v| v.clone().into())
1329    }
1330
1331    /// Creates a [`map`] that converts from `T` to [`Txt`] using [`ToTxt`].
1332    ///
1333    /// [`map`]: Var::map
1334    /// [`Txt`]: Txt
1335    /// [`ToTxt`]: ToTxt
1336    fn map_to_txt(&self) -> Self::Map<Txt>
1337    where
1338        T: ToTxt,
1339    {
1340        self.map(ToTxt::to_txt)
1341    }
1342
1343    /// Create a [`map`] that converts from `T` to [`String`] using [`ToString`].
1344    ///
1345    /// [`map`]: Var::map
1346    fn map_to_string(&self) -> Self::Map<String>
1347    where
1348        T: ToString,
1349    {
1350        self.map(ToString::to_string)
1351    }
1352
1353    /// Create a var that maps from this variable on read and to it on write.
1354    ///
1355    /// The `map` closure is called once on initialization, and then once every time
1356    /// the source variable updates, the `map_back` closure is called every time the output value is modified directly.
1357    ///
1358    /// The mapping var can be [contextualized], see [`Var::map`] for more details.
1359    ///
1360    /// If `self` can change the output variable will keep it alive, this is to support chaining maps.
1361    ///
1362    /// [contextualized]: types::ContextualizedVar
1363    fn map_bidi<O, M, B>(&self, map: M, map_back: B) -> Self::MapBidi<O>
1364    where
1365        O: VarValue,
1366        M: FnMut(&T) -> O + Send + 'static,
1367        B: FnMut(&O) -> T + Send + 'static;
1368
1369    /// Create a var that maps to an inner variable that is found inside the value of this variable.
1370    ///
1371    /// The mapping var can be [contextualized] if self is contextual, otherwise `map` evaluates immediately to start. Note
1372    /// that the "mapped-to" var can be contextual even when the mapping var is not.
1373    ///
1374    /// The mapping var has the same capabilities of the inner var, plus `CAPS_CHANGE`, modifying the mapping var modifies the inner var.
1375    ///
1376    /// If `self` can change the output variable will keep it alive, this is to support chaining maps.
1377    ///
1378    /// [contextualized]: types::ContextualizedVar
1379    fn flat_map<O, V, M>(&self, map: M) -> Self::FlatMap<O, V>
1380    where
1381        O: VarValue,
1382        V: Var<O>,
1383        M: FnMut(&T) -> V + Send + 'static;
1384
1385    /// Creates a ref-counted var that maps from this variable, but can retain a previous mapped value.
1386    ///
1387    /// The `map` closure is called once on initialization, if it returns `None` the `fallback` closure is called to generate
1388    /// a fallback value, after, the `map` closure is called once every time
1389    /// the mapping variable reads and is out of sync with the source variable, if it returns `Some(_)` the mapping variable value changes,
1390    /// 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;