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)]
280pub struct VarIsReadOnlyError {
281 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
296struct VarHook(Arc<VarHandleData>);
298impl VarHook {
299 pub fn call(&self, args: &AnyVarHookArgs) -> bool {
301 self.is_alive() && (self.0.action)(args)
302 }
303
304 pub fn is_alive(&self) -> bool {
306 Arc::strong_count(&self.0) > 1 || self.0.perm.load(Relaxed)
307 }
308}
309
310#[derive(Clone)]
315#[must_use = "var handle stops the behavior it represents on drop"]
316pub struct VarHandle(Option<Arc<VarHandleData>>);
317impl VarHandle {
318 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 pub fn dummy() -> Self {
329 VarHandle(None)
330 }
331
332 pub fn is_dummy(&self) -> bool {
336 self.0.is_none()
337 }
338
339 pub fn perm(self) {
343 if let Some(s) = &self.0 {
344 s.perm.store(true, Relaxed);
345 }
346 }
347
348 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#[must_use = "var handles stops the behavior they represents on drop"]
389#[derive(Clone, Default)]
390pub struct VarHandles(pub Vec<VarHandle>);
391impl VarHandles {
392 pub const fn dummy() -> Self {
394 VarHandles(vec![])
395 }
396
397 pub fn is_dummy(&self) -> bool {
399 self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
400 }
401
402 pub fn perm(self) {
404 for handle in self.0 {
405 handle.perm()
406 }
407 }
408
409 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 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
449pub 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 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
484pub trait AnyVar: Any + Send + Sync + crate::private::Sealed {
490 fn clone_any(&self) -> BoxedAnyVar;
494
495 fn as_any(&self) -> &dyn Any;
497
498 fn as_unboxed_any(&self) -> &dyn Any;
500
501 fn double_boxed_any(self: Box<Self>) -> Box<dyn Any>;
505
506 fn var_type_id(&self) -> TypeId;
508
509 fn get_any(&self) -> Box<dyn AnyVarValue>;
511
512 fn with_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue));
514
515 fn with_new_any(&self, read: &mut dyn FnMut(&dyn AnyVarValue)) -> bool;
519
520 fn set_any(&self, value: Box<dyn AnyVarValue>) -> Result<(), VarIsReadOnlyError>;
528
529 fn last_update(&self) -> VarUpdateId;
533
534 fn is_contextual(&self) -> bool;
536
537 fn capabilities(&self) -> VarCapability;
539
540 fn is_new(&self) -> bool {
547 VARS.update_id() == self.last_update()
548 }
549
550 fn is_animating(&self) -> bool;
562
563 fn modify_importance(&self) -> usize;
581
582 fn hook_any(&self, pos_modify_action: Box<dyn Fn(&AnyVarHookArgs) -> bool + Send + Sync>) -> VarHandle;
589
590 fn hook_animation_stop(&self, handler: Box<dyn FnOnce() + Send>) -> Result<(), Box<dyn FnOnce() + Send>>;
602
603 fn strong_count(&self) -> usize;
608
609 fn weak_count(&self) -> usize;
614
615 fn actual_var_any(&self) -> BoxedAnyVar;
617
618 fn downgrade_any(&self) -> BoxedAnyWeakVar;
625
626 fn var_ptr(&self) -> VarPtr;
631
632 fn get_debug(&self) -> Txt;
636
637 fn update(&self) -> Result<(), VarIsReadOnlyError>;
642
643 fn map_debug(&self) -> BoxedVar<Txt>;
648
649 fn perm(&self) {
651 VARS.perm(self.clone_any());
652 }
653
654 fn hold_any(&self, value: Box<dyn Any + Send + Sync>) -> VarHandle {
656 self.hook_any(hold_any_impl(value))
657 }
658}
659fn 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
683pub struct VarPtr<'a> {
687 _lt: std::marker::PhantomData<&'a ()>,
688 eq: VarPtrData,
689}
690impl<'a> VarPtr<'a> {
691 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
743pub trait AnyWeakVar: Any + Send + Sync + crate::private::Sealed {
745 fn clone_any(&self) -> BoxedAnyWeakVar;
747
748 fn as_any(&self) -> &dyn Any;
750
751 fn strong_count(&self) -> usize;
755
756 fn weak_count(&self) -> usize;
760
761 fn upgrade_any(&self) -> Option<BoxedAnyVar>;
767}
768
769pub trait WeakVar<T: VarValue>: AnyWeakVar + Clone {
771 type Upgrade: Var<T>;
773
774 fn upgrade(&self) -> Option<Self::Upgrade>;
780
781 fn boxed(self) -> BoxedWeakVar<T>
783 where
784 Self: Sized,
785 {
786 Box::new(self)
787 }
788}
789
790#[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 type Var: Var<T>;
812
813 fn into_var(self) -> Self::Var;
815
816 fn into_boxed_var(self) -> BoxedVar<T>
837 where
838 Self: Sized,
839 {
840 self.into_var().boxed()
841 }
842}
843
844pub 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 pub fn set(&mut self, new_value: T) {
857 self.value = Cow::Owned(new_value);
858 }
859
860 pub fn update(&mut self) {
862 self.update = true;
863 }
864
865 pub fn to_mut(&mut self) -> &mut T {
871 self.value.to_mut()
872 }
873
874 pub fn tags(&self) -> &[Box<dyn AnyVarValue>] {
879 &self.tags
880 }
881
882 pub fn push_tag(&mut self, tag: impl AnyVarValue) {
884 self.tags.push(Box::new(tag));
885 }
886
887 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 pub fn set_modify_importance(&mut self, importance: usize) {
902 self.custom_importance = Some(importance);
903 }
904
905 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 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
946pub struct AnyVarHookArgs<'a> {
948 value: &'a dyn AnyVarValue,
949 update: bool,
950 tags: &'a [Box<dyn AnyVarValue>],
951}
952impl<'a> AnyVarHookArgs<'a> {
953 pub fn new(value: &'a dyn AnyVarValue, update: bool, tags: &'a [Box<dyn AnyVarValue>]) -> Self {
955 Self { value, update, tags }
956 }
957
958 pub fn value(&self) -> &'a dyn AnyVarValue {
960 self.value
961 }
962
963 pub fn update(&self) -> bool {
967 self.update
968 }
969
970 pub fn value_type(&self) -> TypeId {
972 self.value.as_any().type_id()
973 }
974
975 pub fn tags(&self) -> &[Box<dyn AnyVarValue>] {
977 self.tags
978 }
979
980 pub fn tags_vec(&self) -> Vec<Box<dyn AnyVarValue>> {
982 self.tags.iter().map(|t| (*t).clone_boxed()).collect()
983 }
984
985 pub fn downcast_value<T: VarValue>(&self) -> Option<&T> {
987 self.value.as_any().downcast_ref()
988 }
989
990 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 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
1008pub struct VarHookArgs<'a, T: VarValue> {
1010 any: &'a AnyVarHookArgs<'a>,
1011 _t: PhantomData<&'a T>,
1012}
1013impl<'a, T: VarValue> VarHookArgs<'a, T> {
1014 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
1027pub 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 pub fn value(&self) -> &'a T {
1042 self.args.downcast_value::<T>().unwrap()
1043 }
1044}
1045
1046pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
1059 type ReadOnly: Var<T>;
1061
1062 type ActualVar: Var<T>;
1064
1065 type Downgrade: WeakVar<T>;
1067
1068 type Map<O: VarValue>: Var<O>;
1070
1071 type MapBidi<O: VarValue>: Var<O>;
1073
1074 type FlatMap<O: VarValue, V: Var<O>>: Var<O>;
1076
1077 type FilterMap<O: VarValue>: Var<O>;
1079
1080 type FilterMapBidi<O: VarValue>: Var<O>;
1082
1083 type MapRef<O: VarValue>: Var<O>;
1085
1086 type MapRefBidi<O: VarValue>: Var<O>;
1088
1089 type Easing: Var<T>;
1091
1092 fn with<R, F>(&self, read: F) -> R
1094 where
1095 F: FnOnce(&T) -> R;
1096
1097 fn modify<F>(&self, modify: F) -> Result<(), VarIsReadOnlyError>
1099 where
1100 F: FnOnce(&mut VarModify<T>) + Send + 'static;
1101
1102 fn boxed(self) -> BoxedVar<T>
1104 where
1105 Self: Sized,
1106 {
1107 Box::new(self)
1108 }
1109
1110 fn boxed_any(self) -> BoxedAnyVar
1112 where
1113 Self: Sized,
1114 {
1115 Box::new(self)
1116 }
1117
1118 fn actual_var(self) -> Self::ActualVar;
1120
1121 fn downgrade(&self) -> Self::Downgrade;
1123
1124 fn into_value(self) -> T;
1126
1127 fn read_only(&self) -> Self::ReadOnly;
1131
1132 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 fn wait_update(&self) -> impl Future<Output = VarUpdateId> + Send + Sync {
1157 crate::future::WaitUpdateFut::new(self)
1158 }
1159
1160 fn wait_animation(&self) -> impl Future<Output = ()> + Send + Sync {
1166 crate::future::WaitIsNotAnimatingFut::new(self)
1167 }
1168
1169 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 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 fn get(&self) -> T {
1194 self.with(Clone::clone)
1195 }
1196
1197 fn get_txt(&self) -> Txt
1201 where
1202 T: fmt::Display,
1203 {
1204 self.with(ToTxt::to_txt)
1205 }
1206
1207 fn get_string(&self) -> String
1209 where
1210 T: fmt::Display,
1211 {
1212 self.with(ToString::to_string)
1213 }
1214
1215 fn get_into(&self, value: &mut T) {
1217 self.with(var_get_into(value))
1218 }
1219
1220 fn get_ne(&self, value: &mut T) -> bool {
1222 self.with(var_get_ne(value))
1223 }
1224
1225 fn get_new(&self) -> Option<T> {
1229 if self.is_new() { Some(self.with(Clone::clone)) } else { None }
1230 }
1231
1232 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 fn get_new_ne(&self, value: &mut T) -> bool {
1247 self.is_new() && self.get_ne(value)
1248 }
1249
1250 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 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 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 fn cow(&self) -> types::ArcCowVar<T, Self> {
1294 types::ArcCowVar::new(self.clone())
1295 }
1296
1297 fn map<O, M>(&self, map: M) -> Self::Map<O>
1316 where
1317 O: VarValue,
1318 M: FnMut(&T) -> O + Send + 'static;
1319
1320 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 fn map_to_txt(&self) -> Self::Map<Txt>
1337 where
1338 T: ToTxt,
1339 {
1340 self.map(ToTxt::to_txt)
1341 }
1342
1343 fn map_to_string(&self) -> Self::Map<String>
1347 where
1348 T: ToString,
1349 {
1350 self.map(ToString::to_string)
1351 }
1352
1353 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 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 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 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 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 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 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 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 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 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 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 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 fn bind<V2>(&self, other: &V2) -> VarHandle
1544 where
1545 V2: Var<T>,
1546 {
1547 self.bind_map(other, Clone::clone)
1548 }
1549
1550 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 fn debug(&self) -> types::VarDebug<T, Self> {
1972 types::VarDebug {
1973 var: self,
1974 _t: PhantomData,
1975 }
1976 }
1977
1978 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 fn hold<V>(&self, value: V) -> VarHandle
1991 where
1992 V: Any + Send,
1993 {
1994 let value = Mutex::new(value); 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
2701fn 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 pub fn modify(&self, modify: impl FnOnce(&mut $crate::VarModify<$T>) + Send + 'static) {
2838 Var::modify(self, modify).unwrap()
2839 }
2840
2841 pub fn set(&self, value: impl Into<$T>) {
2843 Var::set(self, value).unwrap()
2844 }
2845
2846 pub fn update(&self) {
2848 AnyVar::update(self).unwrap()
2849 }
2850
2851 pub fn set_from<I: Var<$T>>(&self, other: &I) {
2853 Var::set_from(self, other).unwrap()
2854 }
2855
2856 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;