1use core::fmt;
2use std::{
3 any::{Any, TypeId},
4 borrow::Cow,
5 marker::PhantomData,
6 mem,
7 sync::Arc,
8};
9
10use parking_lot::Mutex;
11use smallbox::{SmallBox, smallbox};
12use zng_clone_move::clmv;
13use zng_txt::{Txt, formatx};
14
15use crate::{
16 AnyVarModify, AnyVarValue, BoxAnyVarValue, VARS, Var, VarCapability, VarHandle, VarHandles, VarImpl, VarIsReadOnlyError, VarModify,
17 VarModifyUpdate, VarUpdateId, VarValue, WeakVarImpl,
18 animation::{Animation, AnimationController, AnimationHandle, AnimationStopFn},
19 any_contextual_var,
20};
21
22pub struct AnyVar(pub(crate) crate::var_impl::DynAnyVar);
24impl Clone for AnyVar {
25 fn clone(&self) -> Self {
26 Self(self.0.clone_dyn())
27 }
28}
29impl fmt::Debug for AnyVar {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 f.debug_tuple("AnyVar").field(&self.0).finish()
32 }
33}
34impl AnyVar {
36 pub fn with<O>(&self, visitor: impl FnOnce(&dyn AnyVarValue) -> O) -> O {
38 let mut once = Some(visitor);
39 let mut output = None;
40 self.0.with(&mut |v| {
41 output = Some(once.take().unwrap()(v));
42 });
43 output.unwrap()
44 }
45
46 pub fn get(&self) -> BoxAnyVarValue {
48 self.0.get()
49 }
50
51 pub fn get_debug(&self, alternate: bool) -> Txt {
53 let mut r = Txt::default();
54 self.0.with(&mut |v| {
55 r = if alternate { formatx!("{v:#?}") } else { formatx!("{v:?}") };
56 });
57 r
58 }
59
60 pub fn is_new(&self) -> bool {
68 self.last_update() == VARS.update_id()
69 }
70
71 pub fn get_new(&self) -> Option<BoxAnyVarValue> {
75 if self.is_new() { Some(self.get()) } else { None }
76 }
77
78 pub fn with_new<O>(&self, visitor: impl FnOnce(&dyn AnyVarValue) -> O) -> Option<O> {
82 if self.is_new() { Some(self.with(visitor)) } else { None }
83 }
84
85 pub fn try_set(&self, new_value: BoxAnyVarValue) -> Result<(), VarIsReadOnlyError> {
89 if new_value.type_id() != self.value_type() {
90 #[cfg(feature = "type_names")]
91 panic!(
92 "cannot set `{}` on variable of type `{}`",
93 new_value.type_name(),
94 self.value_type_name()
95 );
96 #[cfg(not(feature = "type_names"))]
97 panic!("cannot set variable, type mismatch");
98 }
99 self.handle_modify(self.0.set(new_value))
100 }
101
102 pub fn set(&self, new_value: BoxAnyVarValue) {
109 trace_debug_error!(self.try_set(new_value))
110 }
111
112 pub fn try_update(&self) -> Result<(), VarIsReadOnlyError> {
114 self.handle_modify(self.0.update())
115 }
116
117 pub fn update(&self) {
124 trace_debug_error!(self.try_update())
125 }
126
127 pub fn try_modify(&self, modify: impl FnOnce(&mut AnyVarModify) + Send + 'static) -> Result<(), VarIsReadOnlyError> {
131 let mut modify = Some(modify);
134 let modify = move |value: &mut AnyVarModify| {
135 #[cfg(debug_assertions)]
136 let type_id = (&*value.value as &dyn Any).type_id();
137
138 modify.take().unwrap()(value);
139
140 #[cfg(debug_assertions)]
141 if !value.update.is_empty() {
142 assert_eq!((&*value.value as &dyn Any).type_id(), type_id, "AnyVar::modify changed value type");
143 }
144 };
145
146 self.handle_modify(self.0.modify(smallbox!(modify)))
147 }
148
149 pub fn modify(&self, modify: impl FnOnce(&mut AnyVarModify) + Send + 'static) {
158 trace_debug_error!(self.try_modify(modify))
159 }
160
161 pub fn try_set_from(&self, other: &AnyVar) -> Result<(), VarIsReadOnlyError> {
166 let other = other.current_context();
167 if other.capabilities().is_const() {
168 self.try_set(other.get())
169 } else if self.capabilities().is_read_only() {
170 Err(VarIsReadOnlyError {})
171 } else {
172 let weak_other = other.downgrade();
173 self.try_modify(move |v| {
174 if let Some(other) = weak_other.upgrade() {
175 other.with(|ov| {
176 if *ov != **v {
177 let mut new_value = ov.clone_boxed();
179 assert!(v.try_swap(&mut *new_value), "set_from other var not of the same type");
180
181 v.push_tag(other.var_instance_tag());
183 }
184 v.set_modify_importance(other.modify_importance());
186 });
187 }
188 })
189 }
190 }
191
192 pub fn set_from(&self, other: &AnyVar) {
202 trace_debug_error!(self.try_set_from(other))
203 }
204
205 pub fn try_set_from_map(
209 &self,
210 other: &AnyVar,
211 map: impl FnOnce(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
212 ) -> Result<(), VarIsReadOnlyError> {
213 if other.capabilities().is_const() {
214 self.try_set(other.get())
215 } else if self.capabilities().is_read_only() {
216 Err(VarIsReadOnlyError {})
217 } else {
218 let weak_other = other.downgrade();
219 self.try_modify(move |v| {
220 if let Some(other) = weak_other.upgrade() {
221 other.with(|ov| {
222 let new_value = map(ov);
223 if v.set(new_value) {
224 v.push_tag(other.var_instance_tag());
226 }
227 v.set_modify_importance(other.modify_importance());
229 });
230 }
231 })
232 }
233 }
234
235 pub fn set_from_map(&self, other: &AnyVar, map: impl FnOnce(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) {
243 trace_debug_error!(self.try_set_from_map(other, map))
244 }
245
246 pub fn hook(&self, on_update: impl FnMut(&AnyVarHookArgs) -> bool + Send + 'static) -> VarHandle {
255 self.0.hook(smallbox!(on_update))
256 }
257
258 #[allow(clippy::manual_async_fn)] pub fn wait_match(&self, predicate: impl Fn(&dyn AnyVarValue) -> bool + Send + Sync) -> impl Future<Output = ()> + Send + Sync {
261 async move {
262 while !self.with(&predicate) {
263 let future = self.wait_update();
264 if self.with(&predicate) {
265 break;
266 }
267 future.await;
268 }
269 }
270 }
271
272 #[allow(clippy::manual_async_fn)] pub fn wait_next(&self) -> impl Future<Output = BoxAnyVarValue> + Send + Sync {
277 async {
278 self.wait_update().await;
279 self.get()
280 }
281 }
282
283 pub fn last_update(&self) -> VarUpdateId {
290 self.0.last_update()
291 }
292
293 pub fn wait_update(&self) -> impl Future<Output = VarUpdateId> + Send + Sync {
307 crate::future::WaitUpdateFut::new(self)
308 }
309
310 pub fn trace_value<S: Send + 'static>(&self, mut enter_value: impl FnMut(&AnyVarHookArgs) -> S + Send + 'static) -> VarHandle {
316 let span = self.with(|v| {
317 enter_value(&AnyVarHookArgs {
318 var_instance_tag: self.var_instance_tag(),
319 value: v,
320 update: false,
321 tags: &[],
322 })
323 });
324 let mut span = Some(span);
325 self.hook(move |v| {
326 let _ = span.take();
327 span = Some(enter_value(v));
328 true
329 })
330 }
331
332 fn handle_modify(&self, scheduled: bool) -> Result<(), VarIsReadOnlyError> {
333 match scheduled {
334 true => Ok(()),
335 false => Err(VarIsReadOnlyError {}),
336 }
337 }
338}
339impl AnyVar {
341 pub fn map_any(&self, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static, value_type: TypeId) -> AnyVar {
350 let caps = self.capabilities();
351
352 #[cfg(debug_assertions)]
353 let map = {
354 let mut map = map;
355 move |v: &dyn AnyVarValue| {
356 let output = map(v);
357 assert_eq!(value_type, output.type_id(), "map_any value type does not match");
358 output
359 }
360 };
361
362 if caps.is_contextual() {
363 let me = self.clone();
364 let map = Arc::new(Mutex::new(map));
365 return any_contextual_var(
367 move || me.clone().map_any_tail(clmv!(map, |v| map.lock()(v)), me.capabilities()),
368 value_type,
369 );
370 }
371 self.map_any_tail(map, caps)
372 }
373 fn map_any_tail(&self, mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static, caps: VarCapability) -> AnyVar {
375 let me = self.current_context();
376
377 let mut init_value = None;
378 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
379 let init_value = init_value.unwrap();
380
381 if caps.is_const() {
382 return crate::any_const_var(init_value);
383 }
384
385 let output = crate::any_var_derived(init_value, &me);
386 me.bind_impl(&output, map).perm();
387 output.hold(me).perm();
388
389 output.read_only()
390 }
391
392 pub fn map<O: VarValue>(&self, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> Var<O> {
400 let mapping = self.map_any(move |v| BoxAnyVarValue::new(map(v)), TypeId::of::<O>());
401 Var::new_any(mapping)
402 }
403
404 pub fn map_debug(&self, alternate: bool) -> Var<Txt> {
410 if alternate {
411 self.map(|v| formatx!("{v:#?}"))
412 } else {
413 self.map(|v| formatx!("{v:?}"))
414 }
415 }
416
417 pub fn filter_map_any(
427 &self,
428 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
429 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
430 value_type: TypeId,
431 ) -> AnyVar {
432 let caps = self.capabilities();
433
434 if caps.is_contextual() {
435 let me = self.clone();
436 let fns = Arc::new(Mutex::new((map, fallback_init)));
437 return any_contextual_var(
438 move || {
439 me.clone()
440 .filter_map_any_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, || fns.lock().1()), me.capabilities())
441 },
442 value_type,
443 );
444 }
445
446 self.filter_map_any_tail(map, fallback_init, caps)
447 }
448 fn filter_map_any_tail(
450 &self,
451 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
452 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
453 caps: VarCapability,
454 ) -> AnyVar {
455 let me = self.current_context();
456
457 let mut init_value = None;
458 me.with(&mut |v: &dyn AnyVarValue| init_value = map(v));
459 let init_value = match init_value {
460 Some(v) => v,
461 None => fallback_init(),
462 };
463
464 if caps.is_const() {
465 return crate::any_const_var(init_value);
466 }
467
468 let output = crate::any_var_derived(init_value, &me);
469 let weak_output = output.downgrade();
470
471 me.hook(move |args| {
472 match weak_output.upgrade() {
473 Some(o) => {
474 if let Some(new_value) = map(args.value) {
475 o.set(new_value);
476 }
477 true
478 }
479 None => {
480 false
482 }
483 }
484 })
485 .perm();
486 output.hold(me).perm();
487
488 output.read_only()
489 }
490
491 pub fn filter_map<O: VarValue>(
501 &self,
502 mut map: impl FnMut(&dyn AnyVarValue) -> Option<O> + Send + 'static,
503 fallback_init: impl Fn() -> O + Send + 'static,
504 ) -> Var<O> {
505 let mapping = self.filter_map_any(
506 move |v| map(v).map(BoxAnyVarValue::new),
507 move || BoxAnyVarValue::new(fallback_init()),
508 TypeId::of::<O>(),
509 );
510 Var::new_any(mapping)
511 }
512
513 pub fn map_bidi_any(
525 &self,
526 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
527 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
528 value_type: TypeId,
529 ) -> AnyVar {
530 let caps = self.capabilities();
531
532 if caps.is_contextual() {
533 let me = self.clone();
534 let fns = Arc::new(Mutex::new((map, map_back)));
535 return any_contextual_var(
536 move || {
537 me.clone()
538 .map_bidi_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, |v| fns.lock().1(v)), caps)
539 },
540 value_type,
541 );
542 }
543
544 self.map_bidi_tail(map, map_back, caps)
545 }
546 fn map_bidi_tail(
547 &self,
548 mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
549 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
550 caps: VarCapability,
551 ) -> AnyVar {
552 let me = self.current_context();
553
554 let mut init_value = None;
555 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
556 let init_value = init_value.unwrap();
557
558 if caps.is_const() {
559 return crate::any_const_var(init_value);
560 }
561
562 let output = crate::any_var_derived(init_value, &me);
563
564 me.bind_map_bidi_any(&output, map, map_back).perm();
565 output.hold(me).perm();
566
567 output
568 }
569
570 pub fn map_bidi_modify_any(
581 &self,
582 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
583 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
584 value_type: TypeId,
585 ) -> AnyVar {
586 let caps = self.capabilities();
587
588 if caps.is_contextual() {
589 let me = self.clone();
590 let fns = Arc::new(Mutex::new((map, modify_back)));
591 return any_contextual_var(
592 move || {
593 me.clone()
594 .map_bidi_modify_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, |v, m| fns.lock().1(v, m)), caps)
595 },
596 value_type,
597 );
598 }
599 self.map_bidi_modify_tail(map, modify_back, caps)
600 }
601 fn map_bidi_modify_tail(
602 &self,
603 mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
604 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
605 caps: VarCapability,
606 ) -> AnyVar {
607 let me = self.current_context();
608
609 let mut init_value = None;
610 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
611 let init_value = init_value.unwrap();
612
613 if caps.is_const() {
614 return crate::any_const_var(init_value);
615 }
616
617 let output = crate::any_var_derived(init_value, &me);
618 self.bind_map_any(&output, map).perm();
619 output.bind_modify_any(&me, modify_back).perm();
620 output.hold(me).perm();
621 output
622 }
623
624 pub fn filter_map_bidi_any(
636 &self,
637 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
638 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
639 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
640 value_type: TypeId,
641 ) -> AnyVar {
642 let caps = self.capabilities();
643
644 if caps.is_contextual() {
645 let me = self.clone();
646 let fns = Arc::new(Mutex::new((map, map_back, fallback_init)));
647 return any_contextual_var(
648 move || {
649 me.clone().filter_map_bidi_tail(
650 clmv!(fns, |v| fns.lock().0(v)),
651 clmv!(fns, |v| fns.lock().1(v)),
652 clmv!(fns, || fns.lock().2()),
653 caps,
654 )
655 },
656 value_type,
657 );
658 }
659
660 self.filter_map_bidi_tail(map, map_back, fallback_init, caps)
661 }
662 fn filter_map_bidi_tail(
663 &self,
664 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
665 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
666 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
667 caps: VarCapability,
668 ) -> AnyVar {
669 let me = self.current_context();
670
671 let mut init_value = None;
672 me.with(&mut |v: &dyn AnyVarValue| init_value = map(v));
673 let init_value = init_value.unwrap_or_else(&fallback_init);
674
675 if caps.is_const() {
676 return crate::any_const_var(init_value);
677 }
678
679 let output = crate::any_var_derived(init_value, &me);
680
681 me.bind_filter_map_bidi_any(&output, map, map_back).perm();
682 output.hold(me).perm();
683
684 output
685 }
686
687 pub fn flat_map_any(&self, map: impl FnMut(&dyn AnyVarValue) -> AnyVar + Send + 'static, value_type: TypeId) -> AnyVar {
693 let caps = self.capabilities();
694
695 if caps.is_contextual() {
696 let me = self.clone();
697 let map = Arc::new(Mutex::new(map));
698 return any_contextual_var(
699 move || me.clone().flat_map_tail(clmv!(map, |v| map.lock()(v)), me.capabilities()),
700 value_type,
701 );
702 }
703
704 self.flat_map_tail(map, caps)
705 }
706 fn flat_map_tail(&self, map: impl FnMut(&dyn AnyVarValue) -> AnyVar + Send + 'static, caps: VarCapability) -> AnyVar {
707 if caps.is_const() {
708 return self.with(map);
709 }
710 let me = self.current_context();
711 let mapping = crate::var_impl::flat_map_var::FlatMapVar::new(me, smallbox!(map));
712 AnyVar(crate::DynAnyVar::FlatMap(mapping))
713 }
714
715 pub fn flat_map<O: VarValue>(&self, mut map: impl FnMut(&dyn AnyVarValue) -> Var<O> + Send + 'static) -> Var<O> {
721 let mapping = self.flat_map_any(
722 move |v| {
723 let typed = map(v);
724 typed.into()
725 },
726 TypeId::of::<O>(),
727 );
728 Var::new_any(mapping)
729 }
730}
731impl AnyVar {
733 pub fn bind(&self, other: &AnyVar) -> VarHandle {
739 self.bind_map_any(other, |v| v.clone_boxed())
740 }
741
742 pub fn set_bind(&self, other: &AnyVar) -> VarHandle {
749 other.set_from(self);
750 self.bind(other)
751 }
752
753 pub fn bind_map_any(&self, other: &AnyVar, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
759 let other_caps = other.capabilities();
760 if self.capabilities().is_const() || other_caps.is_always_read_only() {
761 return VarHandle::dummy();
762 }
763
764 if other_caps.is_contextual() {
765 self.bind_impl(&other.current_context(), map)
766 } else {
767 self.bind_impl(other, map)
768 }
769 }
770
771 pub fn bind_modify_any(&self, other: &AnyVar, modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static) -> VarHandle {
777 let self_caps = other.capabilities();
778 let other_caps = other.capabilities();
779 if self_caps.is_const() || other_caps.is_always_read_only() {
780 return VarHandle::dummy();
781 }
782
783 let mut source = Cow::Borrowed(self);
784 if self_caps.is_contextual() {
785 source = Cow::Owned(self.current_context());
786 }
787
788 if other_caps.is_contextual() {
789 source.bind_modify_impl(&other.current_context(), modify)
790 } else {
791 source.bind_modify_impl(other, modify)
792 }
793 }
794
795 pub fn set_bind_map_any(&self, other: &AnyVar, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
802 let map = Arc::new(Mutex::new(map));
803 other.set_from_map(self, clmv!(map, |v| map.lock()(v)));
804
805 enum MapFn<F> {
806 Hot(F),
807 Cold(Arc<Mutex<F>>),
808 Taken,
809 }
810 let mut map = MapFn::Cold(map);
811 self.bind_map_any(other, move |v| match mem::replace(&mut map, MapFn::Taken) {
812 MapFn::Hot(mut f) => {
813 let r = f(v);
814 map = MapFn::Hot(f);
815 r
816 }
817 MapFn::Cold(f) => match Arc::try_unwrap(f) {
818 Ok(f) => {
819 let mut f = f.into_inner();
820 let r = f(v);
821 map = MapFn::Hot(f);
822 r
823 }
824 Err(f) => {
825 let r = f.lock()(v);
826 map = MapFn::Cold(f);
827 r
828 }
829 },
830 MapFn::Taken => unreachable!(),
831 })
832 }
833
834 pub fn bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> VarHandle {
840 self.bind_map_any(other, move |v| BoxAnyVarValue::new(map(v)))
841 }
842
843 pub fn bind_modify<O: VarValue>(
849 &self,
850 other: &Var<O>,
851 mut modify: impl FnMut(&dyn AnyVarValue, &mut VarModify<O>) + Send + 'static,
852 ) -> VarHandle {
853 self.bind_modify_any(other, move |v, m| modify(v, &mut m.downcast::<O>().unwrap()))
854 }
855
856 pub fn set_bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> VarHandle {
863 self.set_bind_map_any(other, move |v| BoxAnyVarValue::new(map(v)))
864 }
865
866 pub fn bind_bidi(&self, other: &AnyVar) -> VarHandles {
872 self.bind_map_bidi_any(other, |v| v.clone_boxed(), |v| v.clone_boxed())
873 }
874
875 pub fn bind_map_bidi_any(
881 &self,
882 other: &AnyVar,
883 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
884 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
885 ) -> VarHandles {
886 assert!(!self.var_eq(other), "cannot bind var to itself");
887
888 let self_cap = self.capabilities();
889 let other_cap = other.capabilities();
890 if self_cap.is_const() || other_cap.is_const() {
891 return VarHandles::dummy();
892 }
893 if self_cap.is_always_read_only() {
894 return self.bind_map_any(other, map).into();
895 }
896 if other_cap.is_always_read_only() {
897 return other.bind_map_any(self, map_back).into();
898 }
899
900 let a = if other_cap.is_contextual() {
901 self.bind_impl(&other.current_context(), map)
902 } else {
903 self.bind_impl(other, map)
904 };
905 let b = if self_cap.is_contextual() {
906 other.bind_impl(&self.current_context(), map_back)
907 } else {
908 other.bind_impl(self, map_back)
909 };
910
911 a.chain(b)
912 }
913
914 pub fn bind_modify_bidi_any(
920 &self,
921 other: &AnyVar,
922 modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
923 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
924 ) -> VarHandles {
925 let self_cap = self.capabilities();
926 let other_cap = other.capabilities();
927 if self_cap.is_const() || other_cap.is_const() {
928 return VarHandles::dummy();
929 }
930 if self_cap.is_always_read_only() {
931 return self.bind_modify_any(other, modify).into();
932 }
933 if other_cap.is_always_read_only() {
934 return other.bind_modify_any(self, modify_back).into();
935 }
936
937 let mut self_ = Cow::Borrowed(self);
938 if self_cap.is_contextual() {
939 self_ = Cow::Owned(self.current_context());
940 }
941
942 let a = if other_cap.is_contextual() {
943 self_.bind_modify_impl(&other.current_context(), modify)
944 } else {
945 self_.bind_modify_impl(other, modify)
946 };
947 let b = other.bind_modify_impl(&self_, modify_back);
948
949 a.chain(b)
950 }
951
952 pub fn bind_modify_bidi<O: VarValue>(
958 &self,
959 other: &Var<O>,
960 mut modify: impl FnMut(&dyn AnyVarValue, &mut VarModify<O>) + Send + 'static,
961 mut modify_back: impl FnMut(&O, &mut AnyVarModify) + Send + 'static,
962 ) -> VarHandles {
963 self.bind_modify_bidi_any(
964 other,
965 move |v, m| modify(v, &mut m.downcast::<O>().unwrap()),
966 move |v, m| modify_back(v.downcast_ref::<O>().unwrap(), m),
967 )
968 }
969
970 pub fn bind_filter_map_any(
976 &self,
977 other: &AnyVar,
978 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
979 ) -> VarHandle {
980 if self.capabilities().is_const() || other.capabilities().is_always_read_only() {
981 return VarHandle::dummy();
982 }
983
984 self.bind_filter_map_impl(other, map)
985 }
986
987 pub fn bind_filter_map<O: VarValue>(
993 &self,
994 other: &AnyVar,
995 mut map: impl FnMut(&dyn AnyVarValue) -> Option<O> + Send + 'static,
996 ) -> VarHandle {
997 self.bind_filter_map_any(other, move |v| map(v).map(BoxAnyVarValue::new))
998 }
999
1000 pub fn bind_filter_map_bidi_any(
1007 &self,
1008 other: &AnyVar,
1009 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1010 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1011 ) -> VarHandles {
1012 let self_cap = self.capabilities();
1013 let other_cap = other.capabilities();
1014 if self_cap.is_const() || other_cap.is_const() {
1015 return VarHandles::dummy();
1016 }
1017 if self_cap.is_always_read_only() {
1018 return self.bind_filter_map_any(other, map).into();
1019 }
1020 if other_cap.is_always_read_only() {
1021 return other.bind_filter_map_any(self, map_back).into();
1022 }
1023
1024 let a = self.bind_filter_map_impl(other, map);
1025 let b = other.bind_filter_map_impl(self, map_back);
1026
1027 a.chain(b)
1028 }
1029
1030 fn bind_impl(&self, other: &AnyVar, mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
1032 let weak_other = other.downgrade();
1033 self.hook(move |args| {
1034 if let Some(other) = weak_other.upgrade() {
1035 if args.contains_tag(&other.var_instance_tag()) {
1036 return true;
1038 }
1039 let self_tag = args.var_instance_tag();
1040
1041 let new_value = map(args.value());
1042 let update = args.update();
1043 other.modify(move |v| {
1044 if v.set(new_value) || update {
1045 v.push_tag(self_tag);
1047 }
1048 if update {
1049 v.update();
1051 }
1052 });
1053 true
1054 } else {
1055 false
1056 }
1057 })
1058 }
1059
1060 fn bind_modify_impl(&self, other: &AnyVar, modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static) -> VarHandle {
1062 let weak_other = other.downgrade();
1063 let weak_self = self.downgrade();
1064 let modify = Arc::new(Mutex::new(modify));
1065 self.hook(move |args| {
1066 if let Some(other) = weak_other.upgrade() {
1067 if args.contains_tag(&other.var_instance_tag()) {
1068 return true;
1070 }
1071
1072 let self_ = weak_self.upgrade().unwrap();
1073 let update = args.update();
1074 other.modify(clmv!(modify, |v| {
1075 let prev_update = mem::replace(&mut v.update, VarModifyUpdate::empty());
1076 self_.with(|source| {
1077 modify.lock()(source, v);
1078 });
1079
1080 if !v.update.is_empty() || update {
1081 v.push_tag(self_.var_instance_tag());
1083 }
1084 if update {
1085 v.update();
1087 }
1088 v.update |= prev_update;
1089 }));
1090 true
1091 } else {
1092 false
1093 }
1094 })
1095 }
1096
1097 fn bind_filter_map_impl(
1098 &self,
1099 other: &AnyVar,
1100 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1101 ) -> VarHandle {
1102 let weak_other = other.downgrade();
1103 self.hook(move |args| {
1104 if let Some(other) = weak_other.upgrade() {
1105 if args.contains_tag(&other.var_instance_tag()) {
1106 return true;
1108 }
1109 let self_tag = args.var_instance_tag();
1110 let update = args.update();
1111 if let Some(new_value) = map(args.value()) {
1112 other.modify(move |v| {
1113 if v.set(new_value) || update {
1114 v.push_tag(self_tag);
1116 }
1117 if update {
1118 v.update();
1120 }
1121 });
1122 } else if update {
1123 other.modify(move |v| {
1124 v.update();
1125 v.push_tag(self_tag);
1126 });
1127 }
1128
1129 true
1130 } else {
1131 false
1132 }
1133 })
1134 }
1135}
1136impl AnyVar {
1138 pub fn animate(&self, animate: impl FnMut(&Animation, &mut AnyVarModify) + Send + 'static) -> AnimationHandle {
1144 if !self.capabilities().is_always_read_only() {
1145 let target = self.current_context();
1146 if !target.capabilities().is_always_read_only() {
1147 let wk_target = target.downgrade();
1150 let animate = Arc::new(Mutex::new(animate));
1151
1152 return VARS.animate(move |args| {
1153 if let Some(target) = wk_target.upgrade() {
1156 if target.modify_importance() > VARS.current_modify().importance {
1159 args.stop();
1162 return;
1163 }
1164
1165 let r = target.try_modify(clmv!(animate, args, |value| {
1167 (animate.lock())(&args, value);
1168 }));
1169
1170 if let Err(VarIsReadOnlyError { .. }) = r {
1171 args.stop();
1173 }
1174 } else {
1175 args.stop();
1177 }
1178 });
1179 }
1180 }
1181 AnimationHandle::dummy()
1182 }
1183
1184 pub fn sequence(&self, animate: impl FnMut(AnyVar) -> AnimationHandle + Send + 'static) -> VarHandle {
1191 if !self.capabilities().is_always_read_only() {
1192 let target = self.current_context();
1193 if !target.capabilities().is_always_read_only() {
1194 let (handle_hook, handle) = VarHandle::new();
1197
1198 let wk_target = target.downgrade();
1199
1200 #[derive(Clone)]
1201 struct SequenceController(Arc<dyn Fn() + Send + Sync + 'static>);
1202 impl AnimationController for SequenceController {
1203 fn on_stop(&self, _: &Animation) {
1204 let ctrl = self.clone();
1205 VARS.with_animation_controller(ctrl, || (self.0)());
1206 }
1207 }
1208 let animate = Mutex::new(animate);
1209 let animate = Arc::new(move || {
1210 if let Some(target) = wk_target.upgrade()
1211 && target.modify_importance() <= VARS.current_modify().importance()
1212 && handle_hook.is_alive()
1213 && VARS.animations_enabled().get()
1214 {
1215 (animate.lock())(target).perm();
1216 }
1217 });
1218 VARS.with_animation_controller(SequenceController(animate.clone()), || {
1219 animate();
1220 });
1221
1222 return handle;
1223 }
1224 }
1225 VarHandle::dummy()
1226 }
1227
1228 pub fn is_animating(&self) -> bool {
1240 self.0.is_animating()
1241 }
1242
1243 pub fn modify_importance(&self) -> usize {
1253 self.0.modify_importance()
1254 }
1255
1256 pub fn hook_animation_stop(&self, handler: impl FnOnce() + Send + 'static) -> VarHandle {
1268 let mut once = Some(handler);
1269 let handler: AnimationStopFn = smallbox!(move || { once.take().unwrap()() });
1270 self.0.hook_animation_stop(handler)
1271 }
1272
1273 pub fn wait_animation(&self) -> impl Future<Output = ()> + Send + Sync {
1279 crate::future::WaitIsNotAnimatingFut::new(self)
1280 }
1281}
1282impl AnyVar {
1284 pub fn downcast<T: VarValue>(self) -> Result<Var<T>, AnyVar> {
1286 if self.value_is::<T>() { Ok(Var::new_any(self)) } else { Err(self) }
1287 }
1288
1289 pub fn downcast_or<T: VarValue, F: Into<Var<T>>>(self, fallback_var: impl FnOnce(AnyVar) -> F) -> Var<T> {
1293 match self.downcast() {
1294 Ok(tv) => tv,
1295 Err(av) => fallback_var(av).into(),
1296 }
1297 }
1298
1299 pub fn value_type(&self) -> TypeId {
1301 self.0.value_type()
1302 }
1303
1304 #[cfg(feature = "type_names")]
1308 pub fn value_type_name(&self) -> &'static str {
1309 self.0.value_type_name()
1310 }
1311
1312 pub fn value_is<T: VarValue>(&self) -> bool {
1314 self.value_type() == TypeId::of::<T>()
1315 }
1316}
1317impl AnyVar {
1319 pub fn capabilities(&self) -> VarCapability {
1321 self.0.capabilities()
1322 }
1323
1324 pub fn strong_count(&self) -> usize {
1331 self.0.strong_count()
1332 }
1333
1334 pub fn downgrade(&self) -> WeakAnyVar {
1341 WeakAnyVar(self.0.downgrade())
1342 }
1343
1344 pub fn var_eq(&self, other: &AnyVar) -> bool {
1350 self.0.var_eq(&other.0)
1351 }
1352
1353 pub fn var_instance_tag(&self) -> VarInstanceTag {
1361 self.0.var_instance_tag()
1362 }
1363
1364 pub fn read_only(&self) -> AnyVar {
1370 AnyVar(self.0.clone_dyn().into_read_only())
1371 }
1372
1373 pub fn cow(&self) -> AnyVar {
1379 AnyVar(crate::DynAnyVar::Cow(crate::cow_var::CowVar::new(self.clone())))
1380 }
1381
1382 pub fn perm(&self) {
1387 VARS.perm(self.clone());
1388 }
1389
1390 pub fn hold(&self, thing: impl Any + Send) -> VarHandle {
1392 self.hold_impl(smallbox!(thing))
1393 }
1394 fn hold_impl(&self, thing: SmallBox<dyn Any + Send, smallbox::space::S2>) -> VarHandle {
1395 self.hook(move |_| {
1396 let _hold = &thing;
1397 true
1398 })
1399 }
1400
1401 pub fn hook_drop(&self, on_drop: impl FnOnce() + Send + 'static) -> VarHandle {
1405 self.hook_drop_impl(Box::new(on_drop))
1406 }
1407 fn hook_drop_impl(&self, on_drop: Box<dyn FnOnce() + Send + 'static>) -> VarHandle {
1408 let (handler_owner, handle) = VarHandle::new();
1409
1410 struct CallOnDrop(Option<Box<dyn FnOnce() + Send + 'static>>, crate::VarHandlerOwner);
1411 impl Drop for CallOnDrop {
1412 fn drop(&mut self) {
1413 if let Some(f) = self.0.take()
1414 && self.1.is_alive()
1415 {
1416 f();
1417 }
1418 }
1419 }
1420 let hold = CallOnDrop(Some(on_drop), handler_owner);
1421
1422 self.hook(move |_| hold.1.is_alive()).perm();
1423
1424 handle
1425 }
1426
1427 pub fn current_context(&self) -> AnyVar {
1434 if self.capabilities().is_contextual() {
1435 AnyVar(self.0.current_context())
1436 } else {
1437 self.clone()
1438 }
1439 }
1440}
1441
1442pub struct WeakAnyVar(pub(crate) crate::var_impl::DynWeakAnyVar);
1444impl fmt::Debug for WeakAnyVar {
1445 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1446 f.debug_tuple("WeakAnyVar").field(&self.0).finish()
1447 }
1448}
1449impl Clone for WeakAnyVar {
1450 fn clone(&self) -> Self {
1451 Self(self.0.clone_dyn())
1452 }
1453}
1454impl WeakAnyVar {
1455 pub fn strong_count(&self) -> usize {
1457 self.0.strong_count()
1458 }
1459
1460 pub fn upgrade(&self) -> Option<AnyVar> {
1462 self.0.upgrade().map(AnyVar)
1463 }
1464
1465 pub const fn new() -> Self {
1467 Self(crate::var_impl::DynWeakAnyVar::Const(crate::var_impl::const_var::WeakConstVar))
1468 }
1469
1470 pub fn var_eq(&self, other: &Self) -> bool {
1472 self.0.var_eq(&other.0)
1473 }
1474}
1475impl Default for WeakAnyVar {
1476 fn default() -> Self {
1477 Self::new()
1478 }
1479}
1480
1481pub struct AnyVarHookArgs<'a> {
1483 pub(super) var_instance_tag: VarInstanceTag,
1484 pub(super) value: &'a dyn AnyVarValue,
1485 pub(super) update: bool,
1486 pub(super) tags: &'a [BoxAnyVarValue],
1487}
1488impl<'a> AnyVarHookArgs<'a> {
1489 pub fn new(var_instance_tag: VarInstanceTag, value: &'a dyn AnyVarValue, update: bool, tags: &'a [BoxAnyVarValue]) -> Self {
1491 Self {
1492 var_instance_tag,
1493 value,
1494 update,
1495 tags,
1496 }
1497 }
1498
1499 pub fn var_instance_tag(&self) -> VarInstanceTag {
1501 self.var_instance_tag
1502 }
1503
1504 pub fn value(&self) -> &'a dyn AnyVarValue {
1506 self.value
1507 }
1508
1509 pub fn update(&self) -> bool {
1513 self.update
1514 }
1515
1516 pub fn value_type(&self) -> TypeId {
1518 self.value.type_id()
1519 }
1520
1521 pub fn tags(&self) -> &[BoxAnyVarValue] {
1523 self.tags
1524 }
1525
1526 pub fn tags_vec(&self) -> Vec<BoxAnyVarValue> {
1528 self.tags.iter().map(|t| (*t).clone_boxed()).collect()
1529 }
1530
1531 pub fn downcast_value<T: VarValue>(&self) -> Option<&T> {
1533 self.value.downcast_ref()
1534 }
1535
1536 pub fn downcast_tags<T: VarValue>(&self) -> impl Iterator<Item = &T> + '_ {
1538 self.tags.iter().filter_map(|t| (*t).downcast_ref::<T>())
1539 }
1540
1541 pub fn contains_tag<T: VarValue>(&self, tag: &T) -> bool {
1545 self.downcast_tags::<T>().any(|t| t == tag)
1546 }
1547
1548 pub fn downcast<T: VarValue>(&self) -> Option<crate::VarHookArgs<'_, T>> {
1550 if TypeId::of::<T>() == self.value_type() {
1551 Some(crate::VarHookArgs {
1552 any: self,
1553 _t: PhantomData,
1554 })
1555 } else {
1556 None
1557 }
1558 }
1559}
1560
1561#[derive(Clone, Copy, PartialEq, Eq)]
1565pub struct VarInstanceTag(pub(crate) usize);
1566impl fmt::Debug for VarInstanceTag {
1567 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1568 if *self == Self::NOT_SHARED {
1569 write!(f, "NOT_SHARED")
1570 } else {
1571 write!(f, "0x{:X})", self.0)
1572 }
1573 }
1574}
1575impl VarInstanceTag {
1576 pub const NOT_SHARED: VarInstanceTag = VarInstanceTag(0);
1580}