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#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
9#![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
73pub 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 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
104 pub struct SourceVarTag(usize);
105 impl SourceVarTag {
106 pub fn new(source: &impl AnyVar) -> Self {
108 SourceVarTag(source.var_ptr().raw_pointer() as _)
109 }
110 }
111
112 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 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 pub trait Sealed {}
142}
143
144#[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
162pub trait AnyVarValue: fmt::Debug + Any + Send + Sync {
164 fn as_any(&self) -> &dyn Any;
166
167 fn as_any_mut(&mut self) -> &mut dyn Any;
169
170 fn into_any(self: Box<Self>) -> Box<dyn Any>;
172
173 fn clone_boxed(&self) -> Box<dyn AnyVarValue>;
175
176 fn clone_boxed_var(&self) -> BoxedAnyVar;
178
179 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#[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 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
233 pub struct VarCapability: u8 {
234 const NEW = 0b0000_0010;
239
240 const MODIFY = 0b0000_0011;
246
247 const CAPS_CHANGE = 0b1000_0000;
252 }
253}
254impl VarCapability {
255 pub fn as_read_only(self) -> Self {
257 Self::from_bits_truncate(self.bits() & 0b1111_1110)
258 }
259
260 pub fn is_always_read_only(self) -> bool {
262 !self.contains(Self::MODIFY) && !self.contains(Self::CAPS_CHANGE)
263 }
264
265 pub fn is_always_static(self) -> bool {
267 self.is_empty()
268 }
269
270 pub fn can_modify(self) -> bool {
272 self.contains(Self::MODIFY)
273 }
274}
275
276#[derive(Debug, Clone, Copy)]
280#[non_exhaustive]
281pub struct VarIsReadOnlyError {
282 pub capabilities: VarCapability,
284}
285impl fmt::Display for VarIsReadOnlyError {
286 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
287 write!(f, "cannot modify variable")
288 }
289}
290impl std::error::Error for VarIsReadOnlyError {}
291
292struct VarHandleData {
293 perm: AtomicBool,
294 action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>,
295}
296
297struct VarHook(Arc<VarHandleData>);
299impl VarHook {
300 pub fn call(&self, args: &AnyVarHookArgs) -> bool {
302 self.is_alive() && (self.0.action)(args)
303 }
304
305 pub fn is_alive(&self) -> bool {
307 Arc::strong_count(&self.0) > 1 || self.0.perm.load(Relaxed)
308 }
309}
310
311#[derive(Clone)]
316#[must_use = "var handle stops the behavior it represents on drop"]
317pub struct VarHandle(Option<Arc<VarHandleData>>);
318impl VarHandle {
319 fn new(action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> (VarHandle, VarHook) {
321 let c = Arc::new(VarHandleData {
322 perm: AtomicBool::new(false),
323 action,
324 });
325 (VarHandle(Some(c.clone())), VarHook(c))
326 }
327
328 pub fn dummy() -> Self {
330 VarHandle(None)
331 }
332
333 pub fn is_dummy(&self) -> bool {
337 self.0.is_none()
338 }
339
340 pub fn perm(self) {
344 if let Some(s) = &self.0 {
345 s.perm.store(true, Relaxed);
346 }
347 }
348
349 pub fn with(self, other: Self) -> VarHandles {
351 [self, other].into()
352 }
353}
354impl PartialEq for VarHandle {
355 fn eq(&self, other: &Self) -> bool {
356 match (&self.0, &other.0) {
357 (None, None) => true,
358 (None, Some(_)) | (Some(_), None) => false,
359 (Some(a), Some(b)) => Arc::ptr_eq(a, b),
360 }
361 }
362}
363impl Eq for VarHandle {}
364impl std::hash::Hash for VarHandle {
365 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
366 let i = match &self.0 {
367 Some(rc) => Arc::as_ptr(rc) as usize,
368 None => 0,
369 };
370 state.write_usize(i);
371 }
372}
373impl fmt::Debug for VarHandle {
374 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
375 let i = match &self.0 {
376 Some(rc) => Arc::as_ptr(rc) as usize,
377 None => 0,
378 };
379 f.debug_tuple("VarHandle").field(&i).finish()
380 }
381}
382impl Default for VarHandle {
383 fn default() -> Self {
384 Self::dummy()
385 }
386}
387
388#[must_use = "var handles stops the behavior they represents on drop"]
390#[derive(Clone, Default)]
391pub struct VarHandles(pub Vec<VarHandle>);
392impl VarHandles {
393 pub const fn dummy() -> Self {
395 VarHandles(vec![])
396 }
397
398 pub fn is_dummy(&self) -> bool {
400 self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
401 }
402
403 pub fn perm(self) {
405 for handle in self.0 {
406 handle.perm()
407 }
408 }
409
410 pub fn push(&mut self, other: VarHandle) -> &mut Self {
412 if !other.is_dummy() {
413 self.0.push(other);
414 }
415 self
416 }
417
418 pub fn clear(&mut self) {
420 self.0.clear()
421 }
422}
423impl FromIterator<VarHandle> for VarHandles {
424 fn from_iter<T: IntoIterator<Item = VarHandle>>(iter: T) -> Self {
425 VarHandles(iter.into_iter().filter(|h| !h.is_dummy()).collect())
426 }
427}
428impl<const N: usize> From<[VarHandle; N]> for VarHandles {
429 fn from(handles: [VarHandle; N]) -> Self {
430 handles.into_iter().collect()
431 }
432}
433impl Extend<VarHandle> for VarHandles {
434 fn extend<T: IntoIterator<Item = VarHandle>>(&mut self, iter: T) {
435 for handle in iter {
436 self.push(handle);
437 }
438 }
439}
440impl IntoIterator for VarHandles {
441 type Item = VarHandle;
442
443 type IntoIter = std::vec::IntoIter<VarHandle>;
444
445 fn into_iter(self) -> Self::IntoIter {
446 self.0.into_iter()
447 }
448}
449
450pub struct ArcEq<T: fmt::Debug + Send + Sync>(pub Arc<T>);
455impl<T: fmt::Debug + Send + Sync> ops::Deref for ArcEq<T> {
456 type Target = Arc<T>;
457
458 fn deref(&self) -> &Self::Target {
459 &self.0
460 }
461}
462impl<T: fmt::Debug + Send + Sync> ArcEq<T> {
463 pub fn new(value: T) -> Self {
465 Self(Arc::new(value))
466 }
467}
468impl<T: fmt::Debug + Send + Sync> PartialEq for ArcEq<T> {
469 fn eq(&self, other: &Self) -> bool {
470 Arc::ptr_eq(&self.0, &other.0)
471 }
472}
473impl<T: fmt::Debug + Send + Sync> Eq for ArcEq<T> {}
474impl<T: fmt::Debug + Send + Sync> Clone for ArcEq<T> {
475 fn clone(&self) -> Self {
476 Self(Arc::clone(&self.0))
477 }
478}
479impl<T: fmt::Debug + Send + Sync> fmt::Debug for ArcEq<T> {
480 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481 fmt::Debug::fmt(&*self.0, f)
482 }
483}
484
485pub trait AnyVar: Any + Send + Sync + crate::private::Sealed {
491 fn clone_any(&self) -> BoxedAnyVar;
495
496 fn as_any(&self) -> &dyn Any;
498
499 fn as_unboxed_any(&self) -> &dyn Any;
501
502 fn double_boxed_any(self: Box<Self>) -> Box<dyn Any>;
506
507 fn var_type_id(&self) -> TypeId;
509
510 fn get_any(&self) -> Box<dyn AnyVarValue>;
512
513 fn with_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue));
515
516 fn with_new_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) -> bool;
520
521 fn set_any(&self, value: Box<dyn AnyVarValue>) -> Result<(), VarIsReadOnlyError>;
529
530 fn last_update(&self) -> VarUpdateId;
534
535 fn is_contextual(&self) -> bool;
537
538 fn capabilities(&self) -> VarCapability;
540
541 fn is_new(&self) -> bool {
548 VARS.update_id() == self.last_update()
549 }
550
551 fn is_animating(&self) -> bool;
563
564 fn modify_importance(&self) -> usize;
582
583 fn hook_any(&self, pos_modify_action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> VarHandle;
590
591 fn hook_animation_stop(&self, handler: Box<dyn FnOnce() + Send>) -> Result<(), Box<dyn FnOnce() + Send>>;
603
604 fn strong_count(&self) -> usize;
609
610 fn weak_count(&self) -> usize;
615
616 fn actual_var_any(&self) -> BoxedAnyVar;
618
619 fn downgrade_any(&self) -> BoxedAnyWeakVar;
626
627 fn var_ptr(&self) -> VarPtr;
632
633 fn get_debug(&self) -> Txt;
637
638 fn update(&self) -> Result<(), VarIsReadOnlyError>;
643
644 fn map_debug(&self) -> BoxedVar<Txt>;
649
650 fn perm(&self) {
652 VARS.perm(self.clone_any());
653 }
654
655 fn hold_any(&self, value: Box<dyn Any + Send + Sync>) -> VarHandle {
657 self.hook_any(hold_any_impl(value))
658 }
659}
660fn hold_any_impl(value: Box<dyn Any + Send + Sync>) -> Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync> {
662 Box::new(move |_| {
663 let _hold = &value;
664 true
665 })
666}
667
668#[derive(Debug)]
669enum VarPtrData {
670 Static(AppLocalId),
671 Arc(*const ()),
672 NeverEq,
673}
674impl PartialEq for VarPtrData {
675 fn eq(&self, other: &Self) -> bool {
676 match (self, other) {
677 (Self::Static(l0), Self::Static(r0)) => l0 == r0,
678 (Self::Arc(l0), Self::Arc(r0)) => l0 == r0,
679 _ => false,
680 }
681 }
682}
683
684pub struct VarPtr<'a> {
688 _lt: std::marker::PhantomData<&'a ()>,
689 eq: VarPtrData,
690}
691impl<'a> VarPtr<'a> {
692 pub fn raw_pointer(&self) -> *const () {
701 match self.eq {
702 VarPtrData::Arc(p) => p,
703 VarPtrData::Static(p) => p.get() as *const (),
704 VarPtrData::NeverEq => std::ptr::null(),
705 }
706 }
707
708 fn new_arc<T: ?Sized>(rc: &'a Arc<T>) -> Self {
709 Self {
710 _lt: std::marker::PhantomData,
711 eq: VarPtrData::Arc(Arc::as_ptr(rc) as _),
712 }
713 }
714
715 fn new_ctx_local<T: Send + Sync>(tl: &'static ContextLocal<T>) -> Self {
716 Self {
717 _lt: std::marker::PhantomData,
718 eq: VarPtrData::Static(tl.id()),
719 }
720 }
721
722 fn new_never_eq(_: &'a impl Any) -> Self {
723 Self {
724 _lt: std::marker::PhantomData,
725 eq: VarPtrData::NeverEq,
726 }
727 }
728}
729impl PartialEq for VarPtr<'_> {
730 fn eq(&self, other: &Self) -> bool {
731 self.eq == other.eq
732 }
733}
734impl fmt::Debug for VarPtr<'_> {
735 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
736 if f.alternate() {
737 f.debug_tuple("VarPtr").field(&self.eq).finish()
738 } else {
739 fmt::Debug::fmt(&self.eq, f)
740 }
741 }
742}
743
744pub trait AnyWeakVar: Any + Send + Sync + crate::private::Sealed {
746 fn clone_any(&self) -> BoxedAnyWeakVar;
748
749 fn as_any(&self) -> &dyn Any;
751
752 fn strong_count(&self) -> usize;
756
757 fn weak_count(&self) -> usize;
761
762 fn upgrade_any(&self) -> Option<BoxedAnyVar>;
768}
769
770pub trait WeakVar<T: VarValue>: AnyWeakVar + Clone {
772 type Upgrade: Var<T>;
774
775 fn upgrade(&self) -> Option<Self::Upgrade>;
781
782 fn boxed(self) -> BoxedWeakVar<T>
784 where
785 Self: Sized,
786 {
787 Box::new(self)
788 }
789}
790
791#[diagnostic::on_unimplemented(
805 note = "`IntoVar<T>` is implemented for all `T: VarValue`",
806 note = "`IntoVar<T>` is implemented for all `V: Var<T>`"
807)]
808pub trait IntoVar<T: VarValue> {
809 type Var: Var<T>;
813
814 fn into_var(self) -> Self::Var;
816
817 fn into_boxed_var(self) -> BoxedVar<T>
838 where
839 Self: Sized,
840 {
841 self.into_var().boxed()
842 }
843}
844
845pub struct VarModify<'a, T: VarValue> {
847 current_value: &'a T,
848 value: Cow<'a, T>,
849 update: bool,
850 tags: Vec<Box<dyn AnyVarValue>>,
851 custom_importance: Option<usize>,
852}
853impl<'a, T: VarValue> VarModify<'a, T> {
854 pub fn set(&mut self, new_value: T) {
858 self.value = Cow::Owned(new_value);
859 }
860
861 pub fn update(&mut self) {
863 self.update = true;
864 }
865
866 pub fn to_mut(&mut self) -> &mut T {
872 self.value.to_mut()
873 }
874
875 pub fn tags(&self) -> &[Box<dyn AnyVarValue>] {
880 &self.tags
881 }
882
883 pub fn push_tag(&mut self, tag: impl AnyVarValue) {
885 self.tags.push(Box::new(tag));
886 }
887
888 pub fn push_tags(&mut self, tags: Vec<Box<dyn AnyVarValue>>) {
890 if self.tags.is_empty() {
891 self.tags = tags;
892 } else {
893 self.tags.extend(tags);
894 }
895 }
896
897 pub fn set_modify_importance(&mut self, importance: usize) {
903 self.custom_importance = Some(importance);
904 }
905
906 pub fn new(current_value: &'a T) -> Self {
908 Self {
909 current_value,
910 value: Cow::Borrowed(current_value),
911 update: false,
912 tags: vec![],
913 custom_importance: None,
914 }
915 }
916
917 pub fn finish(self) -> (bool, Option<T>, bool, Vec<Box<dyn AnyVarValue>>, Option<usize>) {
919 match self.value {
920 Cow::Borrowed(_) => {
921 if self.update {
922 return (true, None, true, self.tags, self.custom_importance);
923 }
924 }
925 Cow::Owned(v) => {
926 if self.update || self.current_value != &v {
927 return (true, Some(v), self.update, self.tags, self.custom_importance);
928 }
929 }
930 }
931 (false, None, false, vec![], self.custom_importance)
932 }
933}
934impl<T: VarValue> ops::Deref for VarModify<'_, T> {
935 type Target = T;
936
937 fn deref(&self) -> &Self::Target {
938 self.as_ref()
939 }
940}
941impl<T: VarValue> std::convert::AsRef<T> for VarModify<'_, T> {
942 fn as_ref(&self) -> &T {
943 &self.value
944 }
945}
946
947pub struct AnyVarHookArgs<'a> {
949 value: &'a dyn AnyVarValue,
950 update: bool,
951 tags: &'a [Box<dyn AnyVarValue>],
952}
953impl<'a> AnyVarHookArgs<'a> {
954 pub fn new(value: &'a dyn AnyVarValue, update: bool, tags: &'a [Box<dyn AnyVarValue>]) -> Self {
956 Self { value, update, tags }
957 }
958
959 pub fn value(&self) -> &'a dyn AnyVarValue {
961 self.value
962 }
963
964 pub fn update(&self) -> bool {
968 self.update
969 }
970
971 pub fn value_type(&self) -> TypeId {
973 self.value.as_any().type_id()
974 }
975
976 pub fn tags(&self) -> &[Box<dyn AnyVarValue>] {
978 self.tags
979 }
980
981 pub fn tags_vec(&self) -> Vec<Box<dyn AnyVarValue>> {
983 self.tags.iter().map(|t| (*t).clone_boxed()).collect()
984 }
985
986 pub fn downcast_value<T: VarValue>(&self) -> Option<&T> {
988 self.value.as_any().downcast_ref()
989 }
990
991 pub fn downcast_tags<T: VarValue>(&self) -> impl Iterator<Item = &T> + '_ {
993 self.tags.iter().filter_map(|t| (*t).as_any().downcast_ref::<T>())
994 }
995
996 pub fn as_strong<T: VarValue>(&self) -> Option<VarHookArgs<T>> {
998 if TypeId::of::<T>() == self.value_type() {
999 Some(VarHookArgs {
1000 any: self,
1001 _t: PhantomData,
1002 })
1003 } else {
1004 None
1005 }
1006 }
1007}
1008
1009pub struct VarHookArgs<'a, T: VarValue> {
1011 any: &'a AnyVarHookArgs<'a>,
1012 _t: PhantomData<&'a T>,
1013}
1014impl<'a, T: VarValue> VarHookArgs<'a, T> {
1015 pub fn value(&self) -> &'a T {
1017 self.any.value.as_any().downcast_ref::<T>().unwrap()
1018 }
1019}
1020impl<'a, T: VarValue> ops::Deref for VarHookArgs<'a, T> {
1021 type Target = AnyVarHookArgs<'a>;
1022
1023 fn deref(&self) -> &Self::Target {
1024 self.any
1025 }
1026}
1027
1028pub struct TraceValueArgs<'a, T: VarValue> {
1030 args: &'a AnyVarHookArgs<'a>,
1031 _type: PhantomData<&'a T>,
1032}
1033impl<'a, T: VarValue> ops::Deref for TraceValueArgs<'a, T> {
1034 type Target = AnyVarHookArgs<'a>;
1035
1036 fn deref(&self) -> &Self::Target {
1037 self.args
1038 }
1039}
1040impl<'a, T: VarValue> TraceValueArgs<'a, T> {
1041 pub fn value(&self) -> &'a T {
1043 self.args.downcast_value::<T>().unwrap()
1044 }
1045}
1046
1047pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
1060 type ReadOnly: Var<T>;
1062
1063 type ActualVar: Var<T>;
1065
1066 type Downgrade: WeakVar<T>;
1068
1069 type Map<O: VarValue>: Var<O>;
1071
1072 type MapBidi<O: VarValue>: Var<O>;
1074
1075 type FlatMap<O: VarValue, V: Var<O>>: Var<O>;
1077
1078 type FilterMap<O: VarValue>: Var<O>;
1080
1081 type FilterMapBidi<O: VarValue>: Var<O>;
1083
1084 type MapRef<O: VarValue>: Var<O>;
1086
1087 type MapRefBidi<O: VarValue>: Var<O>;
1089
1090 type Easing: Var<T>;
1092
1093 fn with<R, F>(&self, read: F) -> R
1095 where
1096 F: FnOnce(&T) -> R;
1097
1098 fn modify<F>(&self, modify: F) -> Result<(), VarIsReadOnlyError>
1100 where
1101 F: FnOnce(&mut VarModify<T>) + Send + 'static;
1102
1103 fn boxed(self) -> BoxedVar<T>
1105 where
1106 Self: Sized,
1107 {
1108 Box::new(self)
1109 }
1110
1111 fn boxed_any(self) -> BoxedAnyVar
1113 where
1114 Self: Sized,
1115 {
1116 Box::new(self)
1117 }
1118
1119 fn actual_var(self) -> Self::ActualVar;
1121
1122 fn downgrade(&self) -> Self::Downgrade;
1124
1125 fn into_value(self) -> T;
1127
1128 fn read_only(&self) -> Self::ReadOnly;
1132
1133 fn hook(&self, pos_modify_action: impl Fn(&VarHookArgs<T>) -> bool + Send + Sync + 'static) -> VarHandle {
1140 self.hook_any(Box::new(move |a| pos_modify_action(&a.as_strong().unwrap())))
1141 }
1142
1143 fn wait_update(&self) -> impl Future<Output = VarUpdateId> + Send + Sync {
1158 crate::future::WaitUpdateFut::new(self)
1159 }
1160
1161 fn wait_animation(&self) -> impl Future<Output = ()> + Send + Sync {
1167 crate::future::WaitIsNotAnimatingFut::new(self)
1168 }
1169
1170 fn wait_value(&self, predicate: impl Fn(&T) -> bool + Send + Sync) -> impl Future<Output = ()> + Send + Sync {
1172 async move {
1173 while !self.with(&predicate) {
1174 let future = self.wait_update();
1175 if self.with(&predicate) {
1176 break;
1177 }
1178 future.await;
1179 }
1180 }
1181 }
1182
1183 fn with_new<R, F>(&self, read: F) -> Option<R>
1187 where
1188 F: FnOnce(&T) -> R,
1189 {
1190 if self.is_new() { Some(self.with(read)) } else { None }
1191 }
1192
1193 fn get(&self) -> T {
1195 self.with(Clone::clone)
1196 }
1197
1198 fn get_txt(&self) -> Txt
1202 where
1203 T: fmt::Display,
1204 {
1205 self.with(ToTxt::to_txt)
1206 }
1207
1208 fn get_string(&self) -> String
1210 where
1211 T: fmt::Display,
1212 {
1213 self.with(ToString::to_string)
1214 }
1215
1216 fn get_into(&self, value: &mut T) {
1218 self.with(var_get_into(value))
1219 }
1220
1221 fn get_ne(&self, value: &mut T) -> bool {
1223 self.with(var_get_ne(value))
1224 }
1225
1226 fn get_new(&self) -> Option<T> {
1230 if self.is_new() { Some(self.with(Clone::clone)) } else { None }
1231 }
1232
1233 fn get_new_into(&self, value: &mut T) -> bool {
1237 let is_new = self.is_new();
1238 if is_new {
1239 self.with(var_get_into(value));
1240 }
1241 is_new
1242 }
1243
1244 fn get_new_ne(&self, value: &mut T) -> bool {
1248 self.is_new() && self.get_ne(value)
1249 }
1250
1251 fn set<I>(&self, value: I) -> Result<(), VarIsReadOnlyError>
1253 where
1254 I: Into<T>,
1255 {
1256 self.modify(var_set(value.into()))
1257 }
1258
1259 fn set_from<I>(&self, other: &I) -> Result<(), VarIsReadOnlyError>
1264 where
1265 I: Var<T>,
1266 {
1267 if other.capabilities().is_always_static() {
1268 self.set(other.get())
1269 } else {
1270 self.modify(var_set_from(other.clone().actual_var()))
1271 }
1272 }
1273
1274 fn set_from_map<Iv, I, M>(&self, other: &I, map: M) -> Result<(), VarIsReadOnlyError>
1276 where
1277 Iv: VarValue,
1278 I: Var<Iv>,
1279 M: FnOnce(&Iv) -> T + Send + 'static,
1280 {
1281 if other.capabilities().is_always_static() {
1282 self.set(other.with(map))
1283 } else {
1284 self.modify(var_set_from_map(other.clone().actual_var(), map))
1285 }
1286 }
1287
1288 fn cow(&self) -> types::ArcCowVar<T, Self> {
1295 types::ArcCowVar::new(self.clone())
1296 }
1297
1298 fn map<O, M>(&self, map: M) -> Self::Map<O>
1317 where
1318 O: VarValue,
1319 M: FnMut(&T) -> O + Send + 'static;
1320
1321 fn map_into<O>(&self) -> Self::Map<O>
1325 where
1326 O: VarValue,
1327 T: Into<O>,
1328 {
1329 self.map(|v| v.clone().into())
1330 }
1331
1332 fn map_to_txt(&self) -> Self::Map<Txt>
1338 where
1339 T: ToTxt,
1340 {
1341 self.map(ToTxt::to_txt)
1342 }
1343
1344 fn map_to_string(&self) -> Self::Map<String>
1348 where
1349 T: ToString,
1350 {
1351 self.map(ToString::to_string)
1352 }
1353
1354 fn map_bidi<O, M, B>(&self, map: M, map_back: B) -> Self::MapBidi<O>
1365 where
1366 O: VarValue,
1367 M: FnMut(&T) -> O + Send + 'static,
1368 B: FnMut(&O) -> T + Send + 'static;
1369
1370 fn flat_map<O, V, M>(&self, map: M) -> Self::FlatMap<O, V>
1381 where
1382 O: VarValue,
1383 V: Var<O>,
1384 M: FnMut(&T) -> V + Send + 'static;
1385
1386 fn filter_map<O, M, I>(&self, map: M, fallback: I) -> Self::FilterMap<O>
1403 where
1404 O: VarValue,
1405 M: FnMut(&T) -> Option<O> + Send + 'static,
1406 I: Fn() -> O + Send + Sync + 'static;
1407
1408 fn filter_try_into<O, I>(&self, fallback: I) -> Self::FilterMap<O>
1412 where
1413 O: VarValue,
1414 T: TryInto<O>,
1415 I: Fn() -> O + Send + Sync + 'static,
1416 {
1417 self.filter_map(|v| v.clone().try_into().ok(), fallback)
1418 }
1419
1420 fn filter_parse<O, I>(&self, fallback: I) -> Self::FilterMap<O>
1425 where
1426 O: VarValue + std::str::FromStr,
1427 T: AsRef<str>,
1428 I: Fn() -> O + Send + Sync + 'static,
1429 {
1430 self.filter_map(|v| v.as_ref().parse().ok(), fallback)
1431 }
1432
1433 fn filter_map_bidi<O, M, B, I>(&self, map: M, map_back: B, fallback: I) -> Self::FilterMapBidi<O>
1448 where
1449 O: VarValue,
1450 M: FnMut(&T) -> Option<O> + Send + 'static,
1451 B: FnMut(&O) -> Option<T> + Send + 'static,
1452 I: Fn() -> O + Send + Sync + 'static;
1453
1454 fn map_ref<O, M>(&self, map: M) -> Self::MapRef<O>
1457 where
1458 O: VarValue,
1459 M: Fn(&T) -> &O + Send + Sync + 'static;
1460
1461 fn map_ref_bidi<O, M, B>(&self, map: M, map_mut: B) -> Self::MapRefBidi<O>
1465 where
1466 O: VarValue,
1467 M: Fn(&T) -> &O + Send + Sync + 'static,
1468 B: Fn(&mut T) -> &mut O + Send + Sync + 'static;
1469 fn bind_map<T2, V2, M>(&self, other: &V2, map: M) -> VarHandle
1478 where
1479 T2: VarValue,
1480 V2: Var<T2>,
1481 M: FnMut(&T) -> T2 + Send + 'static,
1482 {
1483 var_bind_map(self, other, map)
1484 }
1485
1486 fn bind_filter_map<T2, V2, F>(&self, other: &V2, map: F) -> VarHandle
1493 where
1494 T2: VarValue,
1495 V2: Var<T2>,
1496 F: FnMut(&T) -> Option<T2> + Send + 'static,
1497 {
1498 var_bind_filter_map(self, other, map)
1499 }
1500
1501 fn bind_map_bidi<T2, V2, M, B>(&self, other: &V2, map: M, map_back: B) -> VarHandles
1510 where
1511 T2: VarValue,
1512 V2: Var<T2>,
1513 M: FnMut(&T) -> T2 + Send + 'static,
1514 B: FnMut(&T2) -> T + Send + 'static,
1515 {
1516 var_bind_map_bidi(self, other, map, map_back)
1517 }
1518
1519 fn bind_filter_map_bidi<T2, V2, M, B>(&self, other: &V2, map: M, map_back: B) -> VarHandles
1527 where
1528 T2: VarValue,
1529 V2: Var<T2>,
1530 M: FnMut(&T) -> Option<T2> + Send + 'static,
1531 B: FnMut(&T2) -> Option<T> + Send + 'static,
1532 {
1533 var_bind_filter_map_bidi(self, other, map, map_back)
1534 }
1535
1536 fn bind<V2>(&self, other: &V2) -> VarHandle
1545 where
1546 V2: Var<T>,
1547 {
1548 self.bind_map(other, Clone::clone)
1549 }
1550
1551 fn set_bind<V2>(&self, other: &V2) -> VarHandle
1553 where
1554 V2: Var<T>,
1555 {
1556 let _ = other.set_from(self);
1557 self.bind(other)
1558 }
1559
1560 fn bind_bidi<V2>(&self, other: &V2) -> VarHandles
1569 where
1570 V2: Var<T>,
1571 {
1572 self.bind_map_bidi(other, Clone::clone, Clone::clone)
1573 }
1574
1575 fn trace_value<E, S>(&self, mut enter_value: E) -> VarHandle
1590 where
1591 E: FnMut(&TraceValueArgs<T>) -> S + Send + 'static,
1592 S: Send + 'static,
1593 {
1594 let span = self.with(|v| {
1595 enter_value(&TraceValueArgs {
1596 args: &AnyVarHookArgs::new(v, false, &[]),
1597 _type: PhantomData,
1598 })
1599 });
1600 let data = Mutex::new((Some(span), enter_value));
1601 self.hook_any(Box::new(move |args| {
1602 let mut data = data.lock();
1603 let (span, enter_value) = &mut *data;
1604 let _ = span.take();
1605 *span = Some(enter_value(&TraceValueArgs { args, _type: PhantomData }));
1606 true
1607 }))
1608 }
1609
1610 fn animate<A>(&self, animate: A) -> animation::AnimationHandle
1622 where
1623 A: FnMut(&animation::Animation, &mut VarModify<T>) + Send + 'static,
1624 {
1625 animation::var_animate(self, animate)
1626 }
1627
1628 fn sequence<A>(&self, animate: A) -> VarHandle
1634 where
1635 A: FnMut(&<<Self::ActualVar as Var<T>>::Downgrade as WeakVar<T>>::Upgrade) -> animation::AnimationHandle + Send + 'static,
1636 {
1637 animation::var_sequence(self, animate)
1638 }
1639
1640 fn set_ease<S, E, F>(&self, start_value: S, end_value: E, duration: Duration, easing: F) -> animation::AnimationHandle
1646 where
1647 T: Transitionable,
1648 S: Into<T>,
1649 E: Into<T>,
1650 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1651 {
1652 self.set_ease_with(start_value, end_value, duration, easing, animation::Transition::sample)
1653 }
1654
1655 fn set_ease_oci<S, E, F>(&self, start_value: S, end_value: E, duration: Duration, easing: F) -> animation::AnimationHandle
1661 where
1662 T: Transitionable,
1663 S: Into<T>,
1664 E: Into<T>,
1665 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1666 {
1667 self.set_ease_oci_with(start_value, end_value, duration, easing, animation::Transition::sample)
1668 }
1669
1670 fn set_ease_with<S, E, F, Sa>(
1676 &self,
1677 start_value: S,
1678 end_value: E,
1679 duration: Duration,
1680 easing: F,
1681 sampler: Sa,
1682 ) -> animation::AnimationHandle
1683 where
1684 T: Transitionable,
1685 S: Into<T>,
1686 E: Into<T>,
1687 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1688 Sa: Fn(&animation::Transition<T>, EasingStep) -> T + Send + 'static,
1689 {
1690 self.animate(animation::var_set_ease_with(
1691 start_value.into(),
1692 end_value.into(),
1693 duration,
1694 easing,
1695 999.fct(),
1696 sampler,
1697 ))
1698 }
1699
1700 fn set_ease_oci_with<S, E, F, Sa>(
1706 &self,
1707 start_value: S,
1708 end_value: E,
1709 duration: Duration,
1710 easing: F,
1711 sampler: Sa,
1712 ) -> animation::AnimationHandle
1713 where
1714 T: Transitionable,
1715 S: Into<T>,
1716 E: Into<T>,
1717 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1718 Sa: Fn(&animation::Transition<T>, EasingStep) -> T + Send + 'static,
1719 {
1720 self.animate(animation::var_set_ease_oci_with(
1721 start_value.into(),
1722 end_value.into(),
1723 duration,
1724 easing,
1725 999.fct(),
1726 sampler,
1727 ))
1728 }
1729
1730 fn ease<E, F>(&self, new_value: E, duration: Duration, easing: F) -> animation::AnimationHandle
1736 where
1737 T: Transitionable,
1738 E: Into<T>,
1739 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1740 {
1741 self.ease_with(new_value, duration, easing, animation::Transition::sample)
1742 }
1743
1744 fn ease_oci<E, F>(&self, new_value: E, duration: Duration, easing: F) -> animation::AnimationHandle
1750 where
1751 T: Transitionable,
1752 E: Into<T>,
1753 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1754 {
1755 self.ease_oci_with(new_value, duration, easing, animation::Transition::sample)
1756 }
1757
1758 fn ease_with<E, F, S>(&self, new_value: E, duration: Duration, easing: F, sampler: S) -> animation::AnimationHandle
1764 where
1765 T: Transitionable,
1766 E: Into<T>,
1767 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1768 S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + 'static,
1769 {
1770 self.animate(animation::var_set_ease_with(
1771 self.get(),
1772 new_value.into(),
1773 duration,
1774 easing,
1775 0.fct(),
1776 sampler,
1777 ))
1778 }
1779
1780 fn ease_oci_with<E, F, S>(&self, new_value: E, duration: Duration, easing: F, sampler: S) -> animation::AnimationHandle
1786 where
1787 T: Transitionable,
1788 E: Into<T>,
1789 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1790 S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + 'static,
1791 {
1792 self.animate(animation::var_set_ease_oci_with(
1793 self.get(),
1794 new_value.into(),
1795 duration,
1796 easing,
1797 0.fct(),
1798 sampler,
1799 ))
1800 }
1801
1802 fn set_ease_keyed<F>(&self, keys: Vec<(Factor, T)>, duration: Duration, easing: F) -> animation::AnimationHandle
1808 where
1809 T: Transitionable,
1810 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1811 {
1812 self.set_ease_keyed_with(keys, duration, easing, animation::TransitionKeyed::sample)
1813 }
1814
1815 fn set_ease_keyed_with<F, S>(&self, keys: Vec<(Factor, T)>, duration: Duration, easing: F, sampler: S) -> animation::AnimationHandle
1821 where
1822 T: Transitionable,
1823 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1824 S: Fn(&animation::TransitionKeyed<T>, EasingStep) -> T + Send + 'static,
1825 {
1826 if let Some(transition) = animation::TransitionKeyed::new(keys) {
1827 self.animate(animation::var_set_ease_keyed_with(transition, duration, easing, 999.fct(), sampler))
1828 } else {
1829 animation::AnimationHandle::dummy()
1830 }
1831 }
1832
1833 fn ease_keyed<F>(&self, keys: Vec<(Factor, T)>, duration: Duration, easing: F) -> animation::AnimationHandle
1839 where
1840 T: Transitionable,
1841 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1842 {
1843 self.ease_keyed_with(keys, duration, easing, animation::TransitionKeyed::sample)
1844 }
1845
1846 fn ease_keyed_with<F, S>(&self, mut keys: Vec<(Factor, T)>, duration: Duration, easing: F, sampler: S) -> animation::AnimationHandle
1852 where
1853 T: Transitionable,
1854 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1855 S: Fn(&animation::TransitionKeyed<T>, EasingStep) -> T + Send + 'static,
1856 {
1857 keys.insert(0, (0.fct(), self.get()));
1858
1859 let transition = animation::TransitionKeyed::new(keys).unwrap();
1860 self.animate(animation::var_set_ease_keyed_with(transition, duration, easing, 0.fct(), sampler))
1861 }
1862
1863 fn step<N>(&self, new_value: N, delay: Duration) -> animation::AnimationHandle
1871 where
1872 N: Into<T>,
1873 {
1874 self.animate(animation::var_step(new_value.into(), delay))
1875 }
1876
1877 fn step_oci<N>(&self, new_value: N, delay: Duration) -> animation::AnimationHandle
1879 where
1880 N: Into<T>,
1881 {
1882 self.animate(animation::var_step_oci([self.get(), new_value.into()], delay, false))
1883 }
1884
1885 fn set_step_oci<V0, V1>(&self, from: V0, to: V1, delay: Duration) -> animation::AnimationHandle
1888 where
1889 V0: Into<T>,
1890 V1: Into<T>,
1891 {
1892 self.animate(animation::var_step_oci([from.into(), to.into()], delay, true))
1893 }
1894
1895 fn steps<F>(&self, steps: Vec<(Factor, T)>, duration: Duration, easing: F) -> animation::AnimationHandle
1925 where
1926 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1927 {
1928 self.animate(animation::var_steps(steps, duration, easing))
1929 }
1930
1931 fn chase<N, F>(&self, first_target: N, duration: Duration, easing: F) -> animation::ChaseAnimation<T>
1935 where
1936 N: Into<T>,
1937 F: Fn(EasingTime) -> EasingStep + Send + 'static,
1938 T: Transitionable,
1939 {
1940 animation::var_chase(self.clone().boxed(), first_target.into(), duration, easing)
1941 }
1942
1943 fn easing<F>(&self, duration: Duration, easing: F) -> Self::Easing
1953 where
1954 T: Transitionable,
1955 F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static;
1956
1957 fn easing_with<F, S>(&self, duration: Duration, easing: F, sampler: S) -> Self::Easing
1966 where
1967 T: Transitionable,
1968 F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
1969 S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static;
1970
1971 fn debug(&self) -> types::VarDebug<T, Self> {
1973 types::VarDebug {
1974 var: self,
1975 _t: PhantomData,
1976 }
1977 }
1978
1979 fn display(&self) -> types::VarDisplay<T, Self>
1981 where
1982 T: fmt::Display,
1983 {
1984 types::VarDisplay {
1985 var: self,
1986 _t: PhantomData,
1987 }
1988 }
1989
1990 fn hold<V>(&self, value: V) -> VarHandle
1992 where
1993 V: Any + Send,
1994 {
1995 let value = Mutex::new(value); self.hook_any(Box::new(move |_| {
1997 let _hold = &value;
1998 true
1999 }))
2000 }
2001}
2002
2003fn var_bind_map<T, T2, V2, M>(source: &impl Var<T>, other: &V2, map: M) -> VarHandle
2004where
2005 T: VarValue,
2006 T2: VarValue,
2007 V2: Var<T2>,
2008 M: FnMut(&T) -> T2 + Send + 'static,
2009{
2010 #[cfg(feature = "dyn_closure")]
2011 let map: Box<dyn FnMut(&T) -> T2 + Send> = Box::new(map);
2012 var_bind_map_impl(source, other, map)
2013}
2014fn var_bind_map_impl<T, T2, V2, M>(source: &impl Var<T>, other: &V2, mut map: M) -> VarHandle
2015where
2016 T: VarValue,
2017 T2: VarValue,
2018 V2: Var<T2>,
2019 M: FnMut(&T) -> T2 + Send + 'static,
2020{
2021 var_bind(source, other, move |value, args, other| {
2022 let value = map(value);
2023 let update = args.update;
2024 let _ = other.modify(move |vm| {
2025 vm.set(value);
2026 if update {
2027 vm.update();
2028 }
2029 });
2030 })
2031}
2032
2033fn var_bind_filter_map<T, T2, V2, F>(source: &impl Var<T>, other: &V2, map: F) -> VarHandle
2034where
2035 T: VarValue,
2036 T2: VarValue,
2037 V2: Var<T2>,
2038 F: FnMut(&T) -> Option<T2> + Send + 'static,
2039{
2040 #[cfg(feature = "dyn_closure")]
2041 let map: Box<dyn FnMut(&T) -> Option<T2> + Send> = Box::new(map);
2042 var_bind_filter_map_impl(source, other, map)
2043}
2044fn var_bind_filter_map_impl<T, T2, V2, F>(source: &impl Var<T>, other: &V2, mut map: F) -> VarHandle
2045where
2046 T: VarValue,
2047 T2: VarValue,
2048 V2: Var<T2>,
2049 F: FnMut(&T) -> Option<T2> + Send + 'static,
2050{
2051 var_bind(source, other, move |value, args, other| {
2052 if let Some(value) = map(value) {
2053 let update = args.update;
2054 let _ = other.modify(move |vm| {
2055 vm.set(value);
2056 if update {
2057 vm.update();
2058 }
2059 });
2060 }
2061 })
2062}
2063
2064fn var_bind_map_bidi<T, T2, V2, M, B>(source: &impl Var<T>, other: &V2, map: M, map_back: B) -> VarHandles
2065where
2066 T: VarValue,
2067 T2: VarValue,
2068 V2: Var<T2>,
2069 M: FnMut(&T) -> T2 + Send + 'static,
2070 B: FnMut(&T2) -> T + Send + 'static,
2071{
2072 #[cfg(feature = "dyn_closure")]
2073 let map: Box<dyn FnMut(&T) -> T2 + Send + 'static> = Box::new(map);
2074 #[cfg(feature = "dyn_closure")]
2075 let map_back: Box<dyn FnMut(&T2) -> T + Send + 'static> = Box::new(map_back);
2076
2077 var_bind_map_bidi_impl(source, other, map, map_back)
2078}
2079
2080fn var_bind_map_bidi_impl<T, T2, V2, M, B>(source: &impl Var<T>, other: &V2, mut map: M, mut map_back: B) -> VarHandles
2081where
2082 T: VarValue,
2083 T2: VarValue,
2084 V2: Var<T2>,
2085 M: FnMut(&T) -> T2 + Send + 'static,
2086 B: FnMut(&T2) -> T + Send + 'static,
2087{
2088 let source_tag = types::SourceVarTag::new(source);
2089 let source_to_other = var_bind(source, other, move |value, args, other| {
2090 let is_from_other = args
2091 .downcast_tags::<types::SourceVarTag>()
2092 .any(|&b| b == types::SourceVarTag::new(&other));
2093 if !is_from_other {
2094 let value = map(value);
2095 let update = args.update;
2096 let _ = other.modify(move |vm| {
2097 vm.set(value);
2098 vm.push_tag(source_tag);
2099 if update {
2100 vm.update();
2101 }
2102 });
2103 }
2104 });
2105
2106 let other_tag = types::SourceVarTag::new(other);
2107 let other_to_source = var_bind(other, source, move |value, args, source| {
2108 let is_from_source = args
2109 .downcast_tags::<types::SourceVarTag>()
2110 .any(|&b| b == types::SourceVarTag::new(&source));
2111 if !is_from_source {
2112 let value = map_back(value);
2113 let update = args.update;
2114 let _ = source.modify(move |vm| {
2115 vm.set(value);
2116 vm.push_tag(other_tag);
2117 if update {
2118 vm.update();
2119 }
2120 });
2121 }
2122 });
2123
2124 [source_to_other, other_to_source].into_iter().collect()
2125}
2126
2127fn var_bind_filter_map_bidi<T, T2, V2, M, B>(source: &impl Var<T>, other: &V2, map: M, map_back: B) -> VarHandles
2128where
2129 T: VarValue,
2130 T2: VarValue,
2131 V2: Var<T2>,
2132 M: FnMut(&T) -> Option<T2> + Send + 'static,
2133 B: FnMut(&T2) -> Option<T> + Send + 'static,
2134{
2135 #[cfg(feature = "dyn_closure")]
2136 let map: Box<dyn FnMut(&T) -> Option<T2> + Send + 'static> = Box::new(map);
2137 #[cfg(feature = "dyn_closure")]
2138 let map_back: Box<dyn FnMut(&T2) -> Option<T> + Send + 'static> = Box::new(map_back);
2139
2140 var_bind_filter_map_bidi_impl(source, other, map, map_back)
2141}
2142
2143fn 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
2144where
2145 T: VarValue,
2146 T2: VarValue,
2147 V2: Var<T2>,
2148 M: FnMut(&T) -> Option<T2> + Send + 'static,
2149 B: FnMut(&T2) -> Option<T> + Send + 'static,
2150{
2151 let source_tag = types::SourceVarTag::new(source);
2152 let source_to_other = var_bind(source, other, move |value, args, other| {
2153 let is_from_other = args
2154 .downcast_tags::<types::SourceVarTag>()
2155 .any(|&b| b == types::SourceVarTag::new(&other));
2156 if !is_from_other {
2157 if let Some(value) = map(value) {
2158 let update = args.update;
2159 let _ = other.modify(move |vm| {
2160 vm.set(value);
2161 vm.push_tag(source_tag);
2162 if update {
2163 vm.update();
2164 }
2165 });
2166 }
2167 }
2168 });
2169
2170 let other_tag = types::SourceVarTag::new(other);
2171 let other_to_source = var_bind(other, source, move |value, args, source| {
2172 let is_from_source = args
2173 .downcast_tags::<types::SourceVarTag>()
2174 .any(|&b| b == types::SourceVarTag::new(&source));
2175 if !is_from_source {
2176 if let Some(value) = map_back(value) {
2177 let update = args.update;
2178 let _ = source.modify(move |vm| {
2179 vm.set(value);
2180 vm.push_tag(other_tag);
2181 if update {
2182 vm.update();
2183 }
2184 });
2185 }
2186 }
2187 });
2188
2189 [source_to_other, other_to_source].into_iter().collect()
2190}
2191
2192fn var_hold_hook(source: &dyn AnyVar) -> Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync> {
2193 let source = source.clone_any();
2194 Box::new(move |_| {
2195 let _hold = &source;
2196 true
2197 })
2198}
2199
2200fn var_map<T: VarValue, O: VarValue>(source: &impl Var<T>, map: impl FnMut(&T) -> O + Send + 'static) -> ReadOnlyArcVar<O> {
2201 #[cfg(feature = "dyn_closure")]
2202 let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2203 var_map_impl(source, map)
2204}
2205fn var_map_impl<T: VarValue, O: VarValue>(source: &impl Var<T>, mut map: impl FnMut(&T) -> O + Send + 'static) -> ReadOnlyArcVar<O> {
2206 let mapped = var(source.with(&mut map));
2207 var_bind_map_impl(source, &mapped, map).perm();
2208 mapped.hook_any(var_hold_hook(source)).perm();
2209 mapped.read_only()
2210}
2211fn var_map_ctx<T: VarValue, O: VarValue>(
2212 source: &impl Var<T>,
2213 map: impl FnMut(&T) -> O + Send + 'static,
2214) -> contextualized::ContextualizedVar<O> {
2215 #[cfg(feature = "dyn_closure")]
2216 let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2217 var_map_ctx_impl(source, map)
2218}
2219fn var_map_ctx_impl<T: VarValue, O: VarValue>(
2220 source: &impl Var<T>,
2221 map: impl FnMut(&T) -> O + Send + 'static,
2222) -> contextualized::ContextualizedVar<O> {
2223 let source = source.clone();
2224 let map = Arc::new(Mutex::new(map));
2225 types::ContextualizedVar::new(move || {
2226 let other = var(source.with(&mut *map.lock()));
2227 let map = map.clone();
2228 source.bind_map(&other, move |t| map.lock()(t)).perm();
2229 other.read_only()
2230 })
2231}
2232fn var_map_mixed<T: VarValue, O: VarValue>(source: &impl Var<T>, map: impl FnMut(&T) -> O + Send + 'static) -> BoxedVar<O> {
2233 #[cfg(feature = "dyn_closure")]
2234 let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2235
2236 if source.is_contextual() {
2237 var_map_ctx_impl(source, map).boxed()
2238 } else if source.capabilities().is_always_static() {
2239 LocalVar(source.with(map)).boxed()
2240 } else {
2241 var_map_impl(source, map).boxed()
2242 }
2243}
2244
2245fn var_map_bidi<T, O, M, B>(source: &impl Var<T>, map: M, map_back: B) -> ArcVar<O>
2246where
2247 T: VarValue,
2248 O: VarValue,
2249 M: FnMut(&T) -> O + Send + 'static,
2250 B: FnMut(&O) -> T + Send + 'static,
2251{
2252 #[cfg(feature = "dyn_closure")]
2253 let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2254 #[cfg(feature = "dyn_closure")]
2255 let map_back: Box<dyn FnMut(&O) -> T + Send> = Box::new(map_back);
2256
2257 var_map_bidi_impl(source, map, map_back)
2258}
2259fn var_map_bidi_impl<T, O, M, B>(source: &impl Var<T>, mut map: M, map_back: B) -> ArcVar<O>
2260where
2261 T: VarValue,
2262 O: VarValue,
2263 M: FnMut(&T) -> O + Send + 'static,
2264 B: FnMut(&O) -> T + Send + 'static,
2265{
2266 let mapped = var(source.with(&mut map));
2267 var_bind_map_bidi_impl(source, &mapped, map, map_back).perm();
2268 mapped.hook_any(var_hold_hook(source)).perm();
2269 mapped
2270}
2271fn var_map_bidi_ctx<T, O, M, B>(source: &impl Var<T>, map: M, map_back: B) -> types::ContextualizedVar<O>
2272where
2273 T: VarValue,
2274 O: VarValue,
2275 M: FnMut(&T) -> O + Send + 'static,
2276 B: FnMut(&O) -> T + Send + 'static,
2277{
2278 #[cfg(feature = "dyn_closure")]
2279 let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2280 #[cfg(feature = "dyn_closure")]
2281 let map_back: Box<dyn FnMut(&O) -> T + Send> = Box::new(map_back);
2282
2283 var_map_bidi_ctx_impl(source, map, map_back)
2284}
2285fn var_map_bidi_ctx_impl<T, O, M, B>(source: &impl Var<T>, map: M, map_back: B) -> types::ContextualizedVar<O>
2286where
2287 T: VarValue,
2288 O: VarValue,
2289 M: FnMut(&T) -> O + Send + 'static,
2290 B: FnMut(&O) -> T + Send + 'static,
2291{
2292 let me = source.clone();
2293 let map = Arc::new(Mutex::new(map));
2294 let map_back = Arc::new(Mutex::new(map_back));
2295 types::ContextualizedVar::new(move || {
2296 let other = var(me.with(&mut *map.lock()));
2297 let map = map.clone();
2298 let map_back = map_back.clone();
2299 me.bind_map_bidi(&other, move |i| map.lock()(i), move |o| map_back.lock()(o)).perm();
2300 other
2301 })
2302}
2303fn var_map_bidi_mixed<T, O, M, B>(source: &impl Var<T>, map: M, map_back: B) -> BoxedVar<O>
2304where
2305 T: VarValue,
2306 O: VarValue,
2307 M: FnMut(&T) -> O + Send + 'static,
2308 B: FnMut(&O) -> T + Send + 'static,
2309{
2310 #[cfg(feature = "dyn_closure")]
2311 let map: Box<dyn FnMut(&T) -> O + Send> = Box::new(map);
2312 #[cfg(feature = "dyn_closure")]
2313 let map_back: Box<dyn FnMut(&O) -> T + Send> = Box::new(map_back);
2314
2315 if source.is_contextual() {
2316 var_map_bidi_ctx_impl(source, map, map_back).boxed()
2317 } else if source.capabilities().is_always_static() {
2318 LocalVar(source.with(map)).boxed()
2319 } else {
2320 var_map_bidi_impl(source, map, map_back).boxed()
2321 }
2322}
2323
2324fn var_flat_map<T, O, V, M>(source: &impl Var<T>, map: M) -> types::ArcFlatMapVar<O, V>
2325where
2326 T: VarValue,
2327 O: VarValue,
2328 V: Var<O>,
2329 M: FnMut(&T) -> V + Send + 'static,
2330{
2331 #[cfg(feature = "dyn_closure")]
2332 let map: Box<dyn FnMut(&T) -> V + Send + 'static> = Box::new(map);
2333
2334 var_flat_map_impl(source, map)
2335}
2336fn var_flat_map_impl<T, O, V, M>(source: &impl Var<T>, map: M) -> types::ArcFlatMapVar<O, V>
2337where
2338 T: VarValue,
2339 O: VarValue,
2340 V: Var<O>,
2341 M: FnMut(&T) -> V + Send + 'static,
2342{
2343 types::ArcFlatMapVar::new(source, map)
2344}
2345fn var_flat_map_ctx<T, O, V, M>(source: &impl Var<T>, map: M) -> types::ContextualizedVar<O>
2346where
2347 T: VarValue,
2348 O: VarValue,
2349 V: Var<O>,
2350 M: FnMut(&T) -> V + Send + 'static,
2351{
2352 #[cfg(feature = "dyn_closure")]
2353 let map: Box<dyn FnMut(&T) -> V + Send + 'static> = Box::new(map);
2354
2355 var_flat_map_ctx_impl(source, map)
2356}
2357fn var_flat_map_ctx_impl<T, O, V, M>(source: &impl Var<T>, map: M) -> types::ContextualizedVar<O>
2358where
2359 T: VarValue,
2360 O: VarValue,
2361 V: Var<O>,
2362 M: FnMut(&T) -> V + Send + 'static,
2363{
2364 let me = source.clone();
2365 let map = Arc::new(Mutex::new(map));
2366 types::ContextualizedVar::new(move || {
2367 let map = map.clone();
2368 types::ArcFlatMapVar::new(&me, move |i| map.lock()(i))
2369 })
2370}
2371fn var_flat_map_mixed<T, O, V, M>(source: &impl Var<T>, map: M) -> BoxedVar<O>
2372where
2373 T: VarValue,
2374 O: VarValue,
2375 V: Var<O>,
2376 M: FnMut(&T) -> V + Send + 'static,
2377{
2378 #[cfg(feature = "dyn_closure")]
2379 let map: Box<dyn FnMut(&T) -> V + Send + 'static> = Box::new(map);
2380
2381 if source.is_contextual() {
2382 var_flat_map_ctx_impl(source, map).boxed()
2383 } else if source.capabilities().is_always_static() {
2384 source.with(map).boxed()
2385 } else {
2386 var_flat_map_impl(source, map).boxed()
2387 }
2388}
2389
2390fn var_filter_map<T, O, M, I>(source: &impl Var<T>, map: M, fallback: I) -> ReadOnlyArcVar<O>
2391where
2392 T: VarValue,
2393 O: VarValue,
2394 M: FnMut(&T) -> Option<O> + Send + 'static,
2395 I: Fn() -> O + Send + Sync + 'static,
2396{
2397 #[cfg(feature = "dyn_closure")]
2398 let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2399 #[cfg(feature = "dyn_closure")]
2400 let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2401
2402 var_filter_map_impl(source, map, fallback)
2403}
2404fn var_filter_map_impl<T, O, M, I>(source: &impl Var<T>, mut map: M, fallback: I) -> ReadOnlyArcVar<O>
2405where
2406 T: VarValue,
2407 O: VarValue,
2408 M: FnMut(&T) -> Option<O> + Send + 'static,
2409 I: Fn() -> O + Send + Sync + 'static,
2410{
2411 let mapped = var(source.with(&mut map).unwrap_or_else(&fallback));
2412 source.bind_filter_map(&mapped, map).perm();
2413 mapped.hook_any(var_hold_hook(source)).perm();
2414 mapped.read_only()
2415}
2416fn var_filter_map_ctx<T, O, M, I>(source: &impl Var<T>, map: M, fallback: I) -> types::ContextualizedVar<O>
2417where
2418 T: VarValue,
2419 O: VarValue,
2420 M: FnMut(&T) -> Option<O> + Send + 'static,
2421 I: Fn() -> O + Send + Sync + 'static,
2422{
2423 #[cfg(feature = "dyn_closure")]
2424 let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2425 #[cfg(feature = "dyn_closure")]
2426 let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2427
2428 var_filter_map_ctx_impl(source, map, fallback)
2429}
2430fn var_filter_map_ctx_impl<T, O, M, I>(source: &impl Var<T>, map: M, fallback: I) -> types::ContextualizedVar<O>
2431where
2432 T: VarValue,
2433 O: VarValue,
2434 M: FnMut(&T) -> Option<O> + Send + 'static,
2435 I: Fn() -> O + Send + Sync + 'static,
2436{
2437 let me = source.clone();
2438 let map = Arc::new(Mutex::new(map));
2439 types::ContextualizedVar::new(move || {
2440 let other = var(me.with(&mut *map.lock()).unwrap_or_else(&fallback));
2441 let map = map.clone();
2442 me.bind_filter_map(&other, move |i| map.lock()(i)).perm();
2443 other.read_only()
2444 })
2445}
2446fn var_filter_map_mixed<T, O, M, I>(source: &impl Var<T>, map: M, fallback: I) -> BoxedVar<O>
2447where
2448 T: VarValue,
2449 O: VarValue,
2450 M: FnMut(&T) -> Option<O> + Send + 'static,
2451 I: Fn() -> O + Send + Sync + 'static,
2452{
2453 #[cfg(feature = "dyn_closure")]
2454 let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2455 #[cfg(feature = "dyn_closure")]
2456 let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2457
2458 if source.is_contextual() {
2459 var_filter_map_ctx_impl(source, map, fallback).boxed()
2460 } else if source.capabilities().is_always_static() {
2461 LocalVar(source.with(map).unwrap_or_else(fallback)).boxed()
2462 } else {
2463 var_filter_map_impl(source, map, fallback).boxed()
2464 }
2465}
2466
2467fn var_filter_map_bidi<T, O, M, B, I>(source: &impl Var<T>, map: M, map_back: B, fallback: I) -> ArcVar<O>
2468where
2469 T: VarValue,
2470 O: VarValue,
2471 M: FnMut(&T) -> Option<O> + Send + 'static,
2472 B: FnMut(&O) -> Option<T> + Send + 'static,
2473 I: Fn() -> O + Send + Sync + 'static,
2474{
2475 #[cfg(feature = "dyn_closure")]
2476 let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2477 #[cfg(feature = "dyn_closure")]
2478 let map_back: Box<dyn FnMut(&O) -> Option<T> + Send + 'static> = Box::new(map_back);
2479 #[cfg(feature = "dyn_closure")]
2480 let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2481
2482 var_filter_map_bidi_impl(source, map, map_back, fallback)
2483}
2484fn var_filter_map_bidi_impl<T, O, M, B, I>(source: &impl Var<T>, mut map: M, map_back: B, fallback: I) -> ArcVar<O>
2485where
2486 T: VarValue,
2487 O: VarValue,
2488 M: FnMut(&T) -> Option<O> + Send + 'static,
2489 B: FnMut(&O) -> Option<T> + Send + 'static,
2490 I: Fn() -> O + Send + Sync + 'static,
2491{
2492 let mapped = var(source.with(&mut map).unwrap_or_else(&fallback));
2493 source.bind_filter_map_bidi(&mapped, map, map_back).perm();
2494 mapped.hook_any(var_hold_hook(source)).perm();
2495 mapped
2496}
2497fn var_filter_map_bidi_ctx<T, O, M, B, I>(source: &impl Var<T>, map: M, map_back: B, fallback: I) -> types::ContextualizedVar<O>
2498where
2499 T: VarValue,
2500 O: VarValue,
2501 M: FnMut(&T) -> Option<O> + Send + 'static,
2502 B: FnMut(&O) -> Option<T> + Send + 'static,
2503 I: Fn() -> O + Send + Sync + 'static,
2504{
2505 #[cfg(feature = "dyn_closure")]
2506 let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2507 #[cfg(feature = "dyn_closure")]
2508 let map_back: Box<dyn FnMut(&O) -> Option<T> + Send + 'static> = Box::new(map_back);
2509 #[cfg(feature = "dyn_closure")]
2510 let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2511
2512 var_filter_map_bidi_ctx_impl(source, map, map_back, fallback)
2513}
2514fn 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>
2515where
2516 T: VarValue,
2517 O: VarValue,
2518 M: FnMut(&T) -> Option<O> + Send + 'static,
2519 B: FnMut(&O) -> Option<T> + Send + 'static,
2520 I: Fn() -> O + Send + Sync + 'static,
2521{
2522 let me = source.clone();
2523 let map = Arc::new(Mutex::new(map));
2524 let map_back = Arc::new(Mutex::new(map_back));
2525 types::ContextualizedVar::new(move || {
2526 let other = var(me.with(&mut *map.lock()).unwrap_or_else(&fallback));
2527 let map = map.clone();
2528 let map_back = map_back.clone();
2529 me.bind_filter_map_bidi(&other, move |i| map.lock()(i), move |o| map_back.lock()(o))
2530 .perm();
2531 other
2532 })
2533}
2534fn var_filter_map_bidi_mixed<T, O, M, B, I>(source: &impl Var<T>, map: M, map_back: B, fallback: I) -> BoxedVar<O>
2535where
2536 T: VarValue,
2537 O: VarValue,
2538 M: FnMut(&T) -> Option<O> + Send + 'static,
2539 B: FnMut(&O) -> Option<T> + Send + 'static,
2540 I: Fn() -> O + Send + Sync + 'static,
2541{
2542 #[cfg(feature = "dyn_closure")]
2543 let map: Box<dyn FnMut(&T) -> Option<O> + Send + 'static> = Box::new(map);
2544 #[cfg(feature = "dyn_closure")]
2545 let map_back: Box<dyn FnMut(&O) -> Option<T> + Send + 'static> = Box::new(map_back);
2546 #[cfg(feature = "dyn_closure")]
2547 let fallback: Box<dyn Fn() -> O + Send + Sync + 'static> = Box::new(fallback);
2548
2549 if source.is_contextual() {
2550 var_filter_map_bidi_ctx_impl(source, map, map_back, fallback).boxed()
2551 } else if source.capabilities().is_always_static() {
2552 LocalVar(source.with(map).unwrap_or_else(fallback)).boxed()
2553 } else {
2554 var_filter_map_bidi_impl(source, map, map_back, fallback).boxed()
2555 }
2556}
2557
2558fn var_map_ref<T, S, O, M>(source: &S, map: M) -> types::MapRef<T, O, S>
2559where
2560 T: VarValue,
2561 S: Var<T>,
2562 O: VarValue,
2563 M: Fn(&T) -> &O + Send + Sync + 'static,
2564{
2565 types::MapRef::new(source.clone(), Arc::new(map))
2566}
2567
2568fn var_map_ref_bidi<T, S, O, M, B>(source: &S, map: M, map_mut: B) -> types::MapRefBidi<T, O, S>
2569where
2570 T: VarValue,
2571 S: Var<T>,
2572 O: VarValue,
2573 M: Fn(&T) -> &O + Send + Sync + 'static,
2574 B: Fn(&mut T) -> &mut O + Send + Sync + 'static,
2575{
2576 types::MapRefBidi::new(source.clone(), Arc::new(map), Arc::new(map_mut))
2577}
2578
2579fn var_easing<T, F>(source: &impl Var<T>, duration: Duration, easing: F) -> ReadOnlyArcVar<T>
2580where
2581 T: VarValue + Transitionable,
2582 F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2583{
2584 let easing_fn = Arc::new(easing);
2585 let easing_var = var(source.get());
2586 let mut _anim_handle = animation::AnimationHandle::dummy();
2587 var_bind(source, &easing_var, move |value, args, easing_var| {
2588 _anim_handle = easing_var.ease(value.clone(), duration, clmv!(easing_fn, |t| easing_fn(t)));
2589 if args.update {
2590 easing_var.update();
2591 }
2592 })
2593 .perm();
2594 easing_var.hook_any(var_hold_hook(source)).perm();
2595 easing_var.read_only()
2596}
2597fn var_easing_ctx<T, F>(source: &impl Var<T>, duration: Duration, easing: F) -> types::ContextualizedVar<T>
2598where
2599 T: VarValue + Transitionable,
2600 F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2601{
2602 let source = source.clone();
2603 let easing_fn = Arc::new(easing);
2604 types::ContextualizedVar::new(move || {
2605 let easing_var = var(source.get());
2606
2607 let easing_fn = easing_fn.clone();
2608 let mut _anim_handle = animation::AnimationHandle::dummy();
2609 var_bind(&source, &easing_var, move |value, args, easing_var| {
2610 let easing_fn = easing_fn.clone();
2611 _anim_handle = easing_var.ease(value.clone(), duration, move |t| easing_fn(t));
2612 if args.update {
2613 easing_var.update();
2614 }
2615 })
2616 .perm();
2617 easing_var.read_only()
2618 })
2619}
2620fn var_easing_mixed<T, F>(source: &impl Var<T>, duration: Duration, easing: F) -> BoxedVar<T>
2621where
2622 T: VarValue + Transitionable,
2623 F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2624{
2625 if source.is_contextual() {
2626 var_easing_ctx(source, duration, easing).boxed()
2627 } else if source.capabilities().is_always_static() {
2628 source.clone().boxed()
2629 } else {
2630 var_easing(source, duration, easing).boxed()
2631 }
2632}
2633
2634fn var_easing_with<T, F, S>(source: &impl Var<T>, duration: Duration, easing: F, sampler: S) -> ReadOnlyArcVar<T>
2635where
2636 T: VarValue + Transitionable,
2637 F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2638 S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static,
2639{
2640 let fns = Arc::new((easing, sampler));
2641 let easing_var = var(source.get());
2642
2643 let mut _anim_handle = animation::AnimationHandle::dummy();
2644 var_bind(source, &easing_var, move |value, args, easing_var| {
2645 _anim_handle = easing_var.ease_with(
2646 value.clone(),
2647 duration,
2648 clmv!(fns, |t| (fns.0)(t)),
2649 clmv!(fns, |t, s| (fns.1)(t, s)),
2650 );
2651 if args.update {
2652 easing_var.update();
2653 }
2654 })
2655 .perm();
2656 easing_var.hook_any(var_hold_hook(source)).perm();
2657 easing_var.read_only()
2658}
2659fn var_easing_with_ctx<T, F, S>(source: &impl Var<T>, duration: Duration, easing: F, sampler: S) -> types::ContextualizedVar<T>
2660where
2661 T: VarValue + Transitionable,
2662 F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2663 S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static,
2664{
2665 let source = source.clone();
2666 let fns = Arc::new((easing, sampler));
2667 types::ContextualizedVar::new(move || {
2668 let easing_var = var(source.get());
2669
2670 let fns = fns.clone();
2671 let mut _anim_handle = animation::AnimationHandle::dummy();
2672 var_bind(&source, &easing_var, move |value, args, easing_var| {
2673 _anim_handle = easing_var.ease_with(
2674 value.clone(),
2675 duration,
2676 clmv!(fns, |t| (fns.0)(t)),
2677 clmv!(fns, |t, s| (fns.1)(t, s)),
2678 );
2679 if args.update {
2680 easing_var.update();
2681 }
2682 })
2683 .perm();
2684 easing_var.read_only()
2685 })
2686}
2687fn var_easing_with_mixed<T, F, S>(source: &impl Var<T>, duration: Duration, easing: F, sampler: S) -> BoxedVar<T>
2688where
2689 T: VarValue + Transitionable,
2690 F: Fn(EasingTime) -> EasingStep + Send + Sync + 'static,
2691 S: Fn(&animation::Transition<T>, EasingStep) -> T + Send + Sync + 'static,
2692{
2693 if source.is_contextual() {
2694 var_easing_with_ctx(source, duration, easing, sampler).boxed()
2695 } else if source.capabilities().is_always_static() {
2696 source.clone().boxed()
2697 } else {
2698 var_easing_with(source, duration, easing, sampler).boxed()
2699 }
2700}
2701
2702fn var_get_into<T>(value: &mut T) -> impl FnOnce(&T) + '_
2705where
2706 T: VarValue,
2707{
2708 move |var_value| value.clone_from(var_value)
2709}
2710fn var_get_ne<T>(value: &mut T) -> impl FnOnce(&T) -> bool + '_
2711where
2712 T: VarValue + PartialEq,
2713{
2714 move |var_value| {
2715 let ne = var_value != value;
2716 if ne {
2717 value.clone_from(var_value);
2718 }
2719 ne
2720 }
2721}
2722fn var_set<T>(value: T) -> impl FnOnce(&mut VarModify<T>)
2723where
2724 T: VarValue,
2725{
2726 move |var_value| {
2727 var_value.set(value);
2728 }
2729}
2730fn var_set_from<T, I>(other: I) -> impl FnOnce(&mut VarModify<T>)
2731where
2732 T: VarValue,
2733 I: Var<T>,
2734{
2735 move |vm| {
2736 let other_tag = types::SourceVarTag::new(&other);
2737 let importance = other.modify_importance();
2738 other.with(|other| {
2739 if vm.as_ref() != other {
2740 vm.set(other.clone());
2741 vm.push_tag(other_tag);
2742 }
2743 vm.set_modify_importance(importance);
2744 })
2745 }
2746}
2747
2748fn var_set_from_map<T, Iv, I, M>(other: I, map: M) -> impl FnOnce(&mut VarModify<T>)
2749where
2750 Iv: VarValue,
2751 I: Var<Iv>,
2752 M: FnOnce(&Iv) -> T + Send + 'static,
2753 T: VarValue,
2754{
2755 move |vm| {
2756 let value = other.with(map);
2757 if vm.as_ref() != &value {
2758 vm.set(value);
2759 vm.push_tag(types::SourceVarTag::new(&other));
2760 }
2761 vm.set_modify_importance(other.modify_importance());
2762 }
2763}
2764
2765fn var_set_any<T>(value: Box<dyn AnyVarValue>) -> impl FnOnce(&mut VarModify<T>)
2766where
2767 T: VarValue,
2768{
2769 match value.into_any().downcast::<T>() {
2770 Ok(value) => var_set(*value),
2771 Err(_) => panic!("cannot `set_any`, incompatible type"),
2772 }
2773}
2774
2775fn var_update<T>(var_value: &mut VarModify<T>)
2776where
2777 T: VarValue,
2778{
2779 var_value.update();
2780}
2781
2782fn var_debug<T>(value: &T) -> Txt
2783where
2784 T: VarValue,
2785{
2786 formatx!("{value:?}")
2787}
2788
2789fn var_bind<I, O, V>(
2790 input: &impl Var<I>,
2791 output: &V,
2792 update_output: impl FnMut(&I, &AnyVarHookArgs, <V::Downgrade as WeakVar<O>>::Upgrade) + Send + 'static,
2793) -> VarHandle
2794where
2795 I: VarValue,
2796 O: VarValue,
2797 V: Var<O>,
2798{
2799 if input.capabilities().is_always_static() || output.capabilities().is_always_read_only() {
2800 VarHandle::dummy()
2801 } else {
2802 #[cfg(feature = "dyn_closure")]
2803 let update_output: Box<dyn FnMut(&I, &AnyVarHookArgs, <V::Downgrade as WeakVar<O>>::Upgrade) + Send + 'static> =
2804 Box::new(update_output);
2805
2806 var_bind_ok(input, output.downgrade(), update_output)
2807 }
2808}
2809
2810fn var_bind_ok<I, O, W>(
2811 input: &impl Var<I>,
2812 wk_output: W,
2813 update_output: impl FnMut(&I, &AnyVarHookArgs, W::Upgrade) + Send + 'static,
2814) -> VarHandle
2815where
2816 I: VarValue,
2817 O: VarValue,
2818 W: WeakVar<O>,
2819{
2820 let update_output = Mutex::new(update_output);
2821 input.hook_any(Box::new(move |args| {
2822 if let Some(output) = wk_output.upgrade() {
2823 if output.capabilities().contains(VarCapability::MODIFY) {
2824 if let Some(value) = args.downcast_value::<I>() {
2825 update_output.lock()(value, args, output);
2826 }
2827 }
2828 true
2829 } else {
2830 false
2831 }
2832 }))
2833}
2834
2835macro_rules! impl_infallible_write {
2836 (for<$T:ident>) => {
2837 pub fn modify(&self, modify: impl FnOnce(&mut $crate::VarModify<$T>) + Send + 'static) {
2839 Var::modify(self, modify).unwrap()
2840 }
2841
2842 pub fn set(&self, value: impl Into<$T>) {
2844 Var::set(self, value).unwrap()
2845 }
2846
2847 pub fn update(&self) {
2849 AnyVar::update(self).unwrap()
2850 }
2851
2852 pub fn set_from<I: Var<$T>>(&self, other: &I) {
2854 Var::set_from(self, other).unwrap()
2855 }
2856
2857 pub fn set_from_map<Iv, I, M>(&self, other: &I, map: M)
2859 where
2860 Iv: VarValue,
2861 I: Var<Iv>,
2862 M: FnOnce(&Iv) -> $T + Send + 'static,
2863 {
2864 Var::set_from_map(self, other, map).unwrap()
2865 }
2866 };
2867}
2868use impl_infallible_write;