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);
40 let mut output = None;
41 self.0.with(&mut |v| {
42 output = Some(once.take().unwrap()(v));
43 });
44 output.unwrap()
45 }
46
47 pub fn get(&self) -> BoxAnyVarValue {
49 self.0.get()
50 }
51
52 pub fn get_debug(&self, alternate: bool) -> Txt {
54 let mut r = Txt::default();
55 self.0.with(&mut |v| {
56 r = if alternate { formatx!("{v:#?}") } else { formatx!("{v:?}") };
57 });
58 r
59 }
60
61 pub fn is_new(&self) -> bool {
69 self.last_update() == VARS.update_id()
70 }
71
72 pub fn get_new(&self) -> Option<BoxAnyVarValue> {
76 if self.is_new() { Some(self.get()) } else { None }
77 }
78
79 pub fn with_new<O>(&self, visitor: impl FnOnce(&dyn AnyVarValue) -> O) -> Option<O> {
83 if self.is_new() { Some(self.with(visitor)) } else { None }
84 }
85
86 pub fn try_set(&self, new_value: BoxAnyVarValue) -> Result<(), VarIsReadOnlyError> {
90 if new_value.type_id() != self.value_type() {
91 #[cfg(feature = "type_names")]
92 panic!(
93 "cannot set `{}` on variable of type `{}`",
94 new_value.type_name(),
95 self.value_type_name()
96 );
97 #[cfg(not(feature = "type_names"))]
98 panic!("cannot set variable, type mismatch");
99 }
100 self.handle_modify(self.0.set(new_value))
101 }
102
103 pub fn set(&self, new_value: BoxAnyVarValue) {
110 trace_debug_error!(self.try_set(new_value))
111 }
112
113 pub fn try_update(&self) -> Result<(), VarIsReadOnlyError> {
115 self.handle_modify(self.0.update())
116 }
117
118 pub fn update(&self) {
125 trace_debug_error!(self.try_update())
126 }
127
128 pub fn try_modify(&self, modify: impl FnOnce(&mut AnyVarModify) + Send + 'static) -> Result<(), VarIsReadOnlyError> {
132 let mut modify = Some(modify);
135 let modify = move |value: &mut AnyVarModify| {
136 #[cfg(debug_assertions)]
137 let type_id = (&*value.value as &dyn Any).type_id();
138
139 modify.take().unwrap()(value);
140
141 #[cfg(debug_assertions)]
142 if !value.update.is_empty() {
143 assert_eq!((&*value.value as &dyn Any).type_id(), type_id, "AnyVar::modify changed value type");
144 }
145 };
146
147 self.handle_modify(self.0.modify(smallbox!(modify)))
148 }
149
150 pub fn modify(&self, modify: impl FnOnce(&mut AnyVarModify) + Send + 'static) {
159 trace_debug_error!(self.try_modify(modify))
160 }
161
162 pub fn try_set_from(&self, other: &AnyVar) -> Result<(), VarIsReadOnlyError> {
167 let other = other.current_context();
168 if other.capabilities().is_const() {
169 self.try_set(other.get())
170 } else if self.capabilities().is_read_only() {
171 Err(VarIsReadOnlyError {})
172 } else {
173 let weak_other = other.downgrade();
174 self.try_modify(move |v| {
175 if let Some(other) = weak_other.upgrade() {
176 other.with(|ov| {
177 if *ov != **v {
178 let mut new_value = ov.clone_boxed();
180 assert!(v.try_swap(&mut *new_value), "set_from other var not of the same type");
181
182 v.push_tag(other.var_instance_tag());
184 }
185 v.set_modify_importance(other.modify_importance());
187 });
188 }
189 })
190 }
191 }
192
193 pub fn set_from(&self, other: &AnyVar) {
203 trace_debug_error!(self.try_set_from(other))
204 }
205
206 pub fn try_set_from_map(
210 &self,
211 other: &AnyVar,
212 map: impl FnOnce(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
213 ) -> Result<(), VarIsReadOnlyError> {
214 if other.capabilities().is_const() {
215 self.try_set(other.get())
216 } else if self.capabilities().is_read_only() {
217 Err(VarIsReadOnlyError {})
218 } else {
219 let weak_other = other.downgrade();
220 self.try_modify(move |v| {
221 if let Some(other) = weak_other.upgrade() {
222 other.with(|ov| {
223 let new_value = map(ov);
224 if v.set(new_value) {
225 v.push_tag(other.var_instance_tag());
227 }
228 v.set_modify_importance(other.modify_importance());
230 });
231 }
232 })
233 }
234 }
235
236 pub fn set_from_map(&self, other: &AnyVar, map: impl FnOnce(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) {
244 trace_debug_error!(self.try_set_from_map(other, map))
245 }
246
247 pub fn hook(&self, on_update: impl FnMut(&AnyVarHookArgs) -> bool + Send + 'static) -> VarHandle {
256 self.0.hook(smallbox!(on_update))
257 }
258
259 #[allow(clippy::manual_async_fn)] pub fn wait_match(&self, predicate: impl Fn(&dyn AnyVarValue) -> bool + Send + Sync) -> impl Future<Output = ()> + Send + Sync {
262 async move {
263 while !self.with(&predicate) {
264 let future = self.wait_update();
265 if self.with(&predicate) {
266 break;
267 }
268 future.await;
269 }
270 }
271 }
272
273 #[allow(clippy::manual_async_fn)] pub fn wait_next(&self) -> impl Future<Output = BoxAnyVarValue> + Send + Sync {
278 async {
279 self.wait_update().await;
280 self.get()
281 }
282 }
283
284 pub fn last_update(&self) -> VarUpdateId {
291 self.0.last_update()
292 }
293
294 pub fn wait_update(&self) -> impl Future<Output = VarUpdateId> + Send + Sync {
308 crate::future::WaitUpdateFut::new(self)
309 }
310
311 pub fn trace_value<S: Send + 'static>(&self, mut enter_value: impl FnMut(&AnyVarHookArgs) -> S + Send + 'static) -> VarHandle {
317 let span = self.with(|v| {
318 enter_value(&AnyVarHookArgs {
319 var_instance_tag: self.var_instance_tag(),
320 value: v,
321 update: false,
322 tags: &[],
323 })
324 });
325 let mut span = Some(span);
326 self.hook(move |v| {
327 let _ = span.take();
328 span = Some(enter_value(v));
329 true
330 })
331 }
332
333 fn handle_modify(&self, scheduled: bool) -> Result<(), VarIsReadOnlyError> {
334 match scheduled {
335 true => Ok(()),
336 false => Err(VarIsReadOnlyError {}),
337 }
338 }
339}
340impl AnyVar {
342 pub fn map_any(&self, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static, value_type: TypeId) -> AnyVar {
351 let caps = self.capabilities();
352
353 #[cfg(debug_assertions)]
354 let map = {
355 let mut map = map;
356 move |v: &dyn AnyVarValue| {
357 let output = map(v);
358 assert_eq!(value_type, output.type_id(), "map_any value type does not match");
359 output
360 }
361 };
362
363 if caps.is_contextual() {
364 let me = self.clone();
365 let map = Arc::new(Mutex::new(map));
366 return any_contextual_var(
368 move || me.clone().map_any_tail(clmv!(map, |v| map.lock()(v)), me.capabilities()),
369 value_type,
370 );
371 }
372 self.map_any_tail(map, caps)
373 }
374 fn map_any_tail(&self, mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static, caps: VarCapability) -> AnyVar {
376 let me = self.current_context();
377
378 let mut init_value = None;
379 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
380 let init_value = init_value.unwrap();
381
382 if caps.is_const() {
383 return crate::any_const_var(init_value);
384 }
385
386 let output = crate::any_var_derived(init_value, &me);
387 me.bind_impl(&output, map).perm();
388 output.hold(me).perm();
389
390 output.read_only()
391 }
392
393 pub fn map<O: VarValue>(&self, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> Var<O> {
401 let mapping = self.map_any(move |v| BoxAnyVarValue::new(map(v)), TypeId::of::<O>());
402 Var::new_any(mapping)
403 }
404
405 pub fn map_debug(&self, alternate: bool) -> Var<Txt> {
411 if alternate {
412 self.map(|v| formatx!("{v:#?}"))
413 } else {
414 self.map(|v| formatx!("{v:?}"))
415 }
416 }
417
418 pub fn filter_map_any(
428 &self,
429 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
430 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
431 value_type: TypeId,
432 ) -> AnyVar {
433 let caps = self.capabilities();
434
435 if caps.is_contextual() {
436 let me = self.clone();
437 let fns = Arc::new(Mutex::new((map, fallback_init)));
438 return any_contextual_var(
439 move || {
440 me.clone()
441 .filter_map_any_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, || fns.lock().1()), me.capabilities())
442 },
443 value_type,
444 );
445 }
446
447 self.filter_map_any_tail(map, fallback_init, caps)
448 }
449 fn filter_map_any_tail(
451 &self,
452 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
453 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
454 caps: VarCapability,
455 ) -> AnyVar {
456 let me = self.current_context();
457
458 let mut init_value = None;
459 me.with(&mut |v: &dyn AnyVarValue| init_value = map(v));
460 let init_value = match init_value {
461 Some(v) => v,
462 None => fallback_init(),
463 };
464
465 if caps.is_const() {
466 return crate::any_const_var(init_value);
467 }
468
469 let output = crate::any_var_derived(init_value, &me);
470 let weak_output = output.downgrade();
471
472 me.hook(move |args| {
473 match weak_output.upgrade() {
474 Some(o) => {
475 if let Some(new_value) = map(args.value) {
476 o.set(new_value);
477 }
478 true
479 }
480 None => {
481 false
483 }
484 }
485 })
486 .perm();
487 output.hold(me).perm();
488
489 output.read_only()
490 }
491
492 pub fn filter_map<O: VarValue>(
502 &self,
503 mut map: impl FnMut(&dyn AnyVarValue) -> Option<O> + Send + 'static,
504 fallback_init: impl Fn() -> O + Send + 'static,
505 ) -> Var<O> {
506 let mapping = self.filter_map_any(
507 move |v| map(v).map(BoxAnyVarValue::new),
508 move || BoxAnyVarValue::new(fallback_init()),
509 TypeId::of::<O>(),
510 );
511 Var::new_any(mapping)
512 }
513
514 pub fn map_bidi_any(
526 &self,
527 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
528 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
529 value_type: TypeId,
530 ) -> AnyVar {
531 let caps = self.capabilities();
532
533 if caps.is_contextual() {
534 let me = self.clone();
535 let fns = Arc::new(Mutex::new((map, map_back)));
536 return any_contextual_var(
537 move || {
538 me.clone()
539 .map_bidi_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, |v| fns.lock().1(v)), caps)
540 },
541 value_type,
542 );
543 }
544
545 self.map_bidi_tail(map, map_back, caps)
546 }
547 fn map_bidi_tail(
548 &self,
549 mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
550 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
551 caps: VarCapability,
552 ) -> AnyVar {
553 let me = self.current_context();
554
555 let mut init_value = None;
556 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
557 let init_value = init_value.unwrap();
558
559 if caps.is_const() {
560 return crate::any_const_var(init_value);
561 }
562
563 let output = crate::any_var_derived(init_value, &me);
564
565 me.bind_map_bidi_any(&output, map, map_back).perm();
566 output.hold(me).perm();
567
568 output
569 }
570
571 pub fn map_bidi_modify_any(
582 &self,
583 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
584 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
585 value_type: TypeId,
586 ) -> AnyVar {
587 let caps = self.capabilities();
588
589 if caps.is_contextual() {
590 let me = self.clone();
591 let fns = Arc::new(Mutex::new((map, modify_back)));
592 return any_contextual_var(
593 move || {
594 me.clone()
595 .map_bidi_modify_tail(clmv!(fns, |v| fns.lock().0(v)), clmv!(fns, |v, m| fns.lock().1(v, m)), caps)
596 },
597 value_type,
598 );
599 }
600 self.map_bidi_modify_tail(map, modify_back, caps)
601 }
602 fn map_bidi_modify_tail(
603 &self,
604 mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
605 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
606 caps: VarCapability,
607 ) -> AnyVar {
608 let me = self.current_context();
609
610 let mut init_value = None;
611 me.with(&mut |v: &dyn AnyVarValue| init_value = Some(map(v)));
612 let init_value = init_value.unwrap();
613
614 if caps.is_const() {
615 return crate::any_const_var(init_value);
616 }
617
618 let output = crate::any_var_derived(init_value, &me);
619 self.bind_map_any(&output, map).perm();
620 output.bind_modify_any(&me, modify_back).perm();
621 output.hold(me).perm();
622 output
623 }
624
625 pub fn filter_map_bidi_any(
637 &self,
638 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
639 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
640 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
641 value_type: TypeId,
642 ) -> AnyVar {
643 let caps = self.capabilities();
644
645 if caps.is_contextual() {
646 let me = self.clone();
647 let fns = Arc::new(Mutex::new((map, map_back, fallback_init)));
648 return any_contextual_var(
649 move || {
650 me.clone().filter_map_bidi_tail(
651 clmv!(fns, |v| fns.lock().0(v)),
652 clmv!(fns, |v| fns.lock().1(v)),
653 clmv!(fns, || fns.lock().2()),
654 caps,
655 )
656 },
657 value_type,
658 );
659 }
660
661 self.filter_map_bidi_tail(map, map_back, fallback_init, caps)
662 }
663 fn filter_map_bidi_tail(
664 &self,
665 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
666 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
667 fallback_init: impl Fn() -> BoxAnyVarValue + Send + 'static,
668 caps: VarCapability,
669 ) -> AnyVar {
670 let me = self.current_context();
671
672 let mut init_value = None;
673 me.with(&mut |v: &dyn AnyVarValue| init_value = map(v));
674 let init_value = init_value.unwrap_or_else(&fallback_init);
675
676 if caps.is_const() {
677 return crate::any_const_var(init_value);
678 }
679
680 let output = crate::any_var_derived(init_value, &me);
681
682 me.bind_filter_map_bidi_any(&output, map, map_back).perm();
683 output.hold(me).perm();
684
685 output
686 }
687
688 pub fn flat_map_any(&self, map: impl FnMut(&dyn AnyVarValue) -> AnyVar + Send + 'static, value_type: TypeId) -> AnyVar {
694 let caps = self.capabilities();
695
696 if caps.is_contextual() {
697 let me = self.clone();
698 let map = Arc::new(Mutex::new(map));
699 return any_contextual_var(
700 move || me.clone().flat_map_tail(clmv!(map, |v| map.lock()(v)), me.capabilities()),
701 value_type,
702 );
703 }
704
705 self.flat_map_tail(map, caps)
706 }
707 fn flat_map_tail(&self, map: impl FnMut(&dyn AnyVarValue) -> AnyVar + Send + 'static, caps: VarCapability) -> AnyVar {
708 if caps.is_const() {
709 return self.with(map);
710 }
711 let me = self.current_context();
712 let mapping = crate::var_impl::flat_map_var::FlatMapVar::new(me, smallbox!(map));
713 AnyVar(crate::DynAnyVar::FlatMap(mapping))
714 }
715
716 pub fn flat_map<O: VarValue>(&self, mut map: impl FnMut(&dyn AnyVarValue) -> Var<O> + Send + 'static) -> Var<O> {
722 let mapping = self.flat_map_any(
723 move |v| {
724 let typed = map(v);
725 typed.into()
726 },
727 TypeId::of::<O>(),
728 );
729 Var::new_any(mapping)
730 }
731}
732impl AnyVar {
734 pub fn bind(&self, other: &AnyVar) -> VarHandle {
740 self.bind_map_any(other, |v| v.clone_boxed())
741 }
742
743 pub fn set_bind(&self, other: &AnyVar) -> VarHandle {
750 other.set_from(self);
751 self.bind(other)
752 }
753
754 pub fn bind_map_any(&self, other: &AnyVar, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
760 let other_caps = other.capabilities();
761 if self.capabilities().is_const() || other_caps.is_always_read_only() {
762 return VarHandle::dummy();
763 }
764
765 if other_caps.is_contextual() {
766 self.bind_impl(&other.current_context(), map)
767 } else {
768 self.bind_impl(other, map)
769 }
770 }
771
772 pub fn bind_modify_any(&self, other: &AnyVar, modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static) -> VarHandle {
778 let self_caps = other.capabilities();
779 let other_caps = other.capabilities();
780 if self_caps.is_const() || other_caps.is_always_read_only() {
781 return VarHandle::dummy();
782 }
783
784 let mut source = Cow::Borrowed(self);
785 if self_caps.is_contextual() {
786 source = Cow::Owned(self.current_context());
787 }
788
789 if other_caps.is_contextual() {
790 source.bind_modify_impl(&other.current_context(), modify)
791 } else {
792 source.bind_modify_impl(other, modify)
793 }
794 }
795
796 pub fn set_bind_map_any(&self, other: &AnyVar, map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
803 let map = Arc::new(Mutex::new(map));
804 other.set_from_map(self, clmv!(map, |v| map.lock()(v)));
805
806 enum MapFn<F> {
807 Hot(F),
808 Cold(Arc<Mutex<F>>),
809 Taken,
810 }
811 let mut map = MapFn::Cold(map);
812 self.bind_map_any(other, move |v| match mem::replace(&mut map, MapFn::Taken) {
813 MapFn::Hot(mut f) => {
814 let r = f(v);
815 map = MapFn::Hot(f);
816 r
817 }
818 MapFn::Cold(f) => match Arc::try_unwrap(f) {
819 Ok(f) => {
820 let mut f = f.into_inner();
821 let r = f(v);
822 map = MapFn::Hot(f);
823 r
824 }
825 Err(f) => {
826 let r = f.lock()(v);
827 map = MapFn::Cold(f);
828 r
829 }
830 },
831 MapFn::Taken => unreachable!(),
832 })
833 }
834
835 pub fn bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> VarHandle {
841 self.bind_map_any(other, move |v| BoxAnyVarValue::new(map(v)))
842 }
843
844 pub fn bind_modify<O: VarValue>(
850 &self,
851 other: &Var<O>,
852 mut modify: impl FnMut(&dyn AnyVarValue, &mut VarModify<O>) + Send + 'static,
853 ) -> VarHandle {
854 self.bind_modify_any(other, move |v, m| modify(v, &mut m.downcast::<O>().unwrap()))
855 }
856
857 pub fn set_bind_map<O: VarValue>(&self, other: &Var<O>, mut map: impl FnMut(&dyn AnyVarValue) -> O + Send + 'static) -> VarHandle {
864 self.set_bind_map_any(other, move |v| BoxAnyVarValue::new(map(v)))
865 }
866
867 pub fn bind_bidi(&self, other: &AnyVar) -> VarHandles {
873 self.bind_map_bidi_any(other, |v| v.clone_boxed(), |v| v.clone_boxed())
874 }
875
876 pub fn bind_map_bidi_any(
882 &self,
883 other: &AnyVar,
884 map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
885 map_back: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static,
886 ) -> VarHandles {
887 assert!(!self.var_eq(other), "cannot bind var to itself");
888
889 let self_cap = self.capabilities();
890 let other_cap = other.capabilities();
891 if self_cap.is_const() || other_cap.is_const() {
892 return VarHandles::dummy();
893 }
894 if self_cap.is_always_read_only() {
895 return self.bind_map_any(other, map).into();
896 }
897 if other_cap.is_always_read_only() {
898 return other.bind_map_any(self, map_back).into();
899 }
900
901 let a = if other_cap.is_contextual() {
902 self.bind_impl(&other.current_context(), map)
903 } else {
904 self.bind_impl(other, map)
905 };
906 let b = if self_cap.is_contextual() {
907 other.bind_impl(&self.current_context(), map_back)
908 } else {
909 other.bind_impl(self, map_back)
910 };
911
912 a.chain(b)
913 }
914
915 pub fn bind_modify_bidi_any(
921 &self,
922 other: &AnyVar,
923 modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
924 modify_back: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static,
925 ) -> VarHandles {
926 let self_cap = self.capabilities();
927 let other_cap = other.capabilities();
928 if self_cap.is_const() || other_cap.is_const() {
929 return VarHandles::dummy();
930 }
931 if self_cap.is_always_read_only() {
932 return self.bind_modify_any(other, modify).into();
933 }
934 if other_cap.is_always_read_only() {
935 return other.bind_modify_any(self, modify_back).into();
936 }
937
938 let mut self_ = Cow::Borrowed(self);
939 if self_cap.is_contextual() {
940 self_ = Cow::Owned(self.current_context());
941 }
942
943 let a = if other_cap.is_contextual() {
944 self_.bind_modify_impl(&other.current_context(), modify)
945 } else {
946 self_.bind_modify_impl(other, modify)
947 };
948 let b = other.bind_modify_impl(&self_, modify_back);
949
950 a.chain(b)
951 }
952
953 pub fn bind_modify_bidi<O: VarValue>(
959 &self,
960 other: &Var<O>,
961 mut modify: impl FnMut(&dyn AnyVarValue, &mut VarModify<O>) + Send + 'static,
962 mut modify_back: impl FnMut(&O, &mut AnyVarModify) + Send + 'static,
963 ) -> VarHandles {
964 self.bind_modify_bidi_any(
965 other,
966 move |v, m| modify(v, &mut m.downcast::<O>().unwrap()),
967 move |v, m| modify_back(v.downcast_ref::<O>().unwrap(), m),
968 )
969 }
970
971 pub fn bind_filter_map_any(
977 &self,
978 other: &AnyVar,
979 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
980 ) -> VarHandle {
981 if self.capabilities().is_const() || other.capabilities().is_always_read_only() {
982 return VarHandle::dummy();
983 }
984
985 self.bind_filter_map_impl(other, map)
986 }
987
988 pub fn bind_filter_map<O: VarValue>(
994 &self,
995 other: &AnyVar,
996 mut map: impl FnMut(&dyn AnyVarValue) -> Option<O> + Send + 'static,
997 ) -> VarHandle {
998 self.bind_filter_map_any(other, move |v| map(v).map(BoxAnyVarValue::new))
999 }
1000
1001 pub fn bind_filter_map_bidi_any(
1008 &self,
1009 other: &AnyVar,
1010 map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1011 map_back: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1012 ) -> VarHandles {
1013 let self_cap = self.capabilities();
1014 let other_cap = other.capabilities();
1015 if self_cap.is_const() || other_cap.is_const() {
1016 return VarHandles::dummy();
1017 }
1018 if self_cap.is_always_read_only() {
1019 return self.bind_filter_map_any(other, map).into();
1020 }
1021 if other_cap.is_always_read_only() {
1022 return other.bind_filter_map_any(self, map_back).into();
1023 }
1024
1025 let a = self.bind_filter_map_impl(other, map);
1026 let b = other.bind_filter_map_impl(self, map_back);
1027
1028 a.chain(b)
1029 }
1030
1031 fn bind_impl(&self, other: &AnyVar, mut map: impl FnMut(&dyn AnyVarValue) -> BoxAnyVarValue + Send + 'static) -> VarHandle {
1033 let weak_other = other.downgrade();
1034 self.hook(move |args| {
1035 if let Some(other) = weak_other.upgrade() {
1036 if args.contains_tag(&other.var_instance_tag()) {
1037 return true;
1039 }
1040 let self_tag = args.var_instance_tag();
1041
1042 let new_value = map(args.value());
1043 let update = args.update();
1044 other.modify(move |v| {
1045 if v.set(new_value) || update {
1046 v.push_tag(self_tag);
1048 }
1049 if update {
1050 v.update();
1052 }
1053 });
1054 true
1055 } else {
1056 false
1057 }
1058 })
1059 }
1060
1061 fn bind_modify_impl(&self, other: &AnyVar, modify: impl FnMut(&dyn AnyVarValue, &mut AnyVarModify) + Send + 'static) -> VarHandle {
1063 let weak_other = other.downgrade();
1064 let weak_self = self.downgrade();
1065 let modify = Arc::new(Mutex::new(modify));
1066 self.hook(move |args| {
1067 if let Some(other) = weak_other.upgrade() {
1068 if args.contains_tag(&other.var_instance_tag()) {
1069 return true;
1071 }
1072
1073 let self_ = weak_self.upgrade().unwrap();
1074 let update = args.update();
1075 other.modify(clmv!(modify, |v| {
1076 let prev_update = mem::replace(&mut v.update, VarModifyUpdate::empty());
1077 self_.with(|source| {
1078 modify.lock()(source, v);
1079 });
1080
1081 if !v.update.is_empty() || update {
1082 v.push_tag(self_.var_instance_tag());
1084 }
1085 if update {
1086 v.update();
1088 }
1089 v.update |= prev_update;
1090 }));
1091 true
1092 } else {
1093 false
1094 }
1095 })
1096 }
1097
1098 fn bind_filter_map_impl(
1099 &self,
1100 other: &AnyVar,
1101 mut map: impl FnMut(&dyn AnyVarValue) -> Option<BoxAnyVarValue> + Send + 'static,
1102 ) -> VarHandle {
1103 let weak_other = other.downgrade();
1104 self.hook(move |args| {
1105 if let Some(other) = weak_other.upgrade() {
1106 if args.contains_tag(&other.var_instance_tag()) {
1107 return true;
1109 }
1110 let self_tag = args.var_instance_tag();
1111 let update = args.update();
1112 if let Some(new_value) = map(args.value()) {
1113 other.modify(move |v| {
1114 if v.set(new_value) || update {
1115 v.push_tag(self_tag);
1117 }
1118 if update {
1119 v.update();
1121 }
1122 });
1123 } else if update {
1124 other.modify(move |v| {
1125 v.update();
1126 v.push_tag(self_tag);
1127 });
1128 }
1129
1130 true
1131 } else {
1132 false
1133 }
1134 })
1135 }
1136}
1137impl AnyVar {
1139 pub fn animate(&self, animate: impl FnMut(&Animation, &mut AnyVarModify) + Send + 'static) -> AnimationHandle {
1145 if !self.capabilities().is_always_read_only() {
1146 let target = self.current_context();
1147 if !target.capabilities().is_always_read_only() {
1148 let wk_target = target.downgrade();
1151 let animate = Arc::new(Mutex::new(animate));
1152
1153 return VARS.animate(move |args| {
1154 if let Some(target) = wk_target.upgrade() {
1157 if target.modify_importance() > VARS.current_modify().importance {
1160 args.stop();
1163 return;
1164 }
1165
1166 let r = target.try_modify(clmv!(animate, args, |value| {
1168 (animate.lock())(&args, value);
1169 }));
1170
1171 if let Err(VarIsReadOnlyError { .. }) = r {
1172 args.stop();
1174 }
1175 } else {
1176 args.stop();
1178 }
1179 });
1180 }
1181 }
1182 AnimationHandle::dummy()
1183 }
1184
1185 pub fn sequence(&self, animate: impl FnMut(AnyVar) -> AnimationHandle + Send + 'static) -> VarHandle {
1192 if !self.capabilities().is_always_read_only() {
1193 let target = self.current_context();
1194 if !target.capabilities().is_always_read_only() {
1195 let (handle_hook, handle) = VarHandle::new();
1198
1199 let wk_target = target.downgrade();
1200
1201 #[derive(Clone)]
1202 struct SequenceController(Arc<dyn Fn() + Send + Sync + 'static>);
1203 impl AnimationController for SequenceController {
1204 fn on_stop(&self, _: &Animation) {
1205 let ctrl = self.clone();
1206 VARS.with_animation_controller(ctrl, || (self.0)());
1207 }
1208 }
1209 let animate = Mutex::new(animate);
1210 let animate = Arc::new(move || {
1211 if let Some(target) = wk_target.upgrade()
1212 && target.modify_importance() <= VARS.current_modify().importance()
1213 && handle_hook.is_alive()
1214 && VARS.animations_enabled().get()
1215 {
1216 (animate.lock())(target).perm();
1217 }
1218 });
1219 VARS.with_animation_controller(SequenceController(animate.clone()), || {
1220 animate();
1221 });
1222
1223 return handle;
1224 }
1225 }
1226 VarHandle::dummy()
1227 }
1228
1229 pub fn is_animating(&self) -> bool {
1241 self.0.is_animating()
1242 }
1243
1244 pub fn modify_importance(&self) -> usize {
1254 self.0.modify_importance()
1255 }
1256
1257 pub fn hook_animation_stop(&self, handler: impl FnOnce() + Send + 'static) -> VarHandle {
1269 let mut once = Some(handler);
1270 let handler: AnimationStopFn = smallbox!(move || { once.take().unwrap()() });
1271 self.0.hook_animation_stop(handler)
1272 }
1273
1274 pub fn wait_animation(&self) -> impl Future<Output = ()> + Send + Sync {
1280 crate::future::WaitIsNotAnimatingFut::new(self)
1281 }
1282}
1283impl AnyVar {
1285 pub fn downcast<T: VarValue>(self) -> Result<Var<T>, AnyVar> {
1287 if self.value_is::<T>() { Ok(Var::new_any(self)) } else { Err(self) }
1288 }
1289
1290 pub fn downcast_or<T: VarValue, F: Into<Var<T>>>(self, fallback_var: impl FnOnce(AnyVar) -> F) -> Var<T> {
1294 match self.downcast() {
1295 Ok(tv) => tv,
1296 Err(av) => fallback_var(av).into(),
1297 }
1298 }
1299
1300 pub fn value_type(&self) -> TypeId {
1302 self.0.value_type()
1303 }
1304
1305 #[cfg(feature = "type_names")]
1309 pub fn value_type_name(&self) -> &'static str {
1310 self.0.value_type_name()
1311 }
1312
1313 pub fn value_is<T: VarValue>(&self) -> bool {
1315 self.value_type() == TypeId::of::<T>()
1316 }
1317}
1318impl AnyVar {
1320 pub fn capabilities(&self) -> VarCapability {
1322 self.0.capabilities()
1323 }
1324
1325 pub fn strong_count(&self) -> usize {
1332 self.0.strong_count()
1333 }
1334
1335 pub fn downgrade(&self) -> WeakAnyVar {
1342 WeakAnyVar(self.0.downgrade())
1343 }
1344
1345 pub fn var_eq(&self, other: &AnyVar) -> bool {
1351 self.0.var_eq(&other.0)
1352 }
1353
1354 pub fn var_instance_tag(&self) -> VarInstanceTag {
1362 self.0.var_instance_tag()
1363 }
1364
1365 pub fn read_only(&self) -> AnyVar {
1371 AnyVar(self.0.clone_dyn().into_read_only())
1372 }
1373
1374 pub fn cow(&self) -> AnyVar {
1380 AnyVar(crate::DynAnyVar::Cow(crate::cow_var::CowVar::new(self.clone())))
1381 }
1382
1383 pub fn perm(&self) {
1388 VARS.perm(self.clone());
1389 }
1390
1391 pub fn hold(&self, thing: impl Any + Send) -> VarHandle {
1393 self.hold_impl(smallbox!(thing))
1394 }
1395 fn hold_impl(&self, thing: SmallBox<dyn Any + Send, smallbox::space::S2>) -> VarHandle {
1396 self.hook(move |_| {
1397 let _hold = &thing;
1398 true
1399 })
1400 }
1401
1402 pub fn current_context(&self) -> AnyVar {
1409 if self.capabilities().is_contextual() {
1410 AnyVar(self.0.current_context())
1411 } else {
1412 self.clone()
1413 }
1414 }
1415}
1416
1417pub struct WeakAnyVar(pub(crate) crate::var_impl::DynWeakAnyVar);
1419impl fmt::Debug for WeakAnyVar {
1420 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1421 f.debug_tuple("WeakAnyVar").field(&self.0).finish()
1422 }
1423}
1424impl Clone for WeakAnyVar {
1425 fn clone(&self) -> Self {
1426 Self(self.0.clone_dyn())
1427 }
1428}
1429impl WeakAnyVar {
1430 pub fn strong_count(&self) -> usize {
1432 self.0.strong_count()
1433 }
1434
1435 pub fn upgrade(&self) -> Option<AnyVar> {
1437 self.0.upgrade().map(AnyVar)
1438 }
1439}
1440
1441pub struct AnyVarHookArgs<'a> {
1443 pub(super) var_instance_tag: VarInstanceTag,
1444 pub(super) value: &'a dyn AnyVarValue,
1445 pub(super) update: bool,
1446 pub(super) tags: &'a [BoxAnyVarValue],
1447}
1448impl<'a> AnyVarHookArgs<'a> {
1449 pub fn new(var_instance_tag: VarInstanceTag, value: &'a dyn AnyVarValue, update: bool, tags: &'a [BoxAnyVarValue]) -> Self {
1451 Self {
1452 var_instance_tag,
1453 value,
1454 update,
1455 tags,
1456 }
1457 }
1458
1459 pub fn var_instance_tag(&self) -> VarInstanceTag {
1461 self.var_instance_tag
1462 }
1463
1464 pub fn value(&self) -> &'a dyn AnyVarValue {
1466 self.value
1467 }
1468
1469 pub fn update(&self) -> bool {
1473 self.update
1474 }
1475
1476 pub fn value_type(&self) -> TypeId {
1478 self.value.type_id()
1479 }
1480
1481 pub fn tags(&self) -> &[BoxAnyVarValue] {
1483 self.tags
1484 }
1485
1486 pub fn tags_vec(&self) -> Vec<BoxAnyVarValue> {
1488 self.tags.iter().map(|t| (*t).clone_boxed()).collect()
1489 }
1490
1491 pub fn downcast_value<T: VarValue>(&self) -> Option<&T> {
1493 self.value.downcast_ref()
1494 }
1495
1496 pub fn downcast_tags<T: VarValue>(&self) -> impl Iterator<Item = &T> + '_ {
1498 self.tags.iter().filter_map(|t| (*t).downcast_ref::<T>())
1499 }
1500
1501 pub fn contains_tag<T: VarValue>(&self, tag: &T) -> bool {
1505 self.downcast_tags::<T>().any(|t| t == tag)
1506 }
1507
1508 pub fn downcast<T: VarValue>(&self) -> Option<crate::VarHookArgs<'_, T>> {
1510 if TypeId::of::<T>() == self.value_type() {
1511 Some(crate::VarHookArgs {
1512 any: self,
1513 _t: PhantomData,
1514 })
1515 } else {
1516 None
1517 }
1518 }
1519}
1520
1521#[derive(Clone, Copy, PartialEq, Eq)]
1525pub struct VarInstanceTag(pub(crate) usize);
1526impl fmt::Debug for VarInstanceTag {
1527 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1528 if *self == Self::NOT_SHARED {
1529 write!(f, "NOT_SHARED")
1530 } else {
1531 write!(f, "0x{:X})", self.0)
1532 }
1533 }
1534}
1535impl VarInstanceTag {
1536 pub const NOT_SHARED: VarInstanceTag = VarInstanceTag(0);
1540}