pax_runtime_api/
variables.rs1use super::*;
4
5#[cfg(test)]
6mod tests;
7
8#[derive(Clone)]
10pub struct Variable {
11 untyped_property: UntypedProperty,
12 converted_to_pax_value: LocalProperty<PaxValue>,
13 rust_type: std::any::TypeId,
14}
15
16impl Variable {
17 pub fn new<T: PropertyValue + ToPaxValue>(untyped_property: UntypedProperty) -> Self {
19 Self::new_from_typed_property(LocalProperty::<T>::new_from_untyped(
20 untyped_property.clone(),
21 ))
22 }
23
24 pub fn new_from_typed_property<T: PropertyValue + ToPaxValue>(
26 property: impl PropertyBinding<T>,
27 ) -> Self {
28 let property = property.local();
29 let untyped_property = property.untyped();
30 let deps = [untyped_property.clone()];
31 let nested_watch = LocalProperty::<()>::default();
32 let pax_value_prop = LocalProperty::computed(
33 move || {
34 let value = property.get();
35 let dependencies = value.nested_properties();
36 if dependencies.is_empty() {
37 nested_watch.replace_with(LocalProperty::default());
38 } else {
39 let source = property.clone();
40 let initial = std::cell::Cell::new(true);
41 nested_watch.replace_with(LocalProperty::computed(
42 move || {
43 if !initial.replace(false) {
44 source.invalidate();
45 }
46 },
47 &dependencies,
48 ));
49 crate::properties::register_effect_property(&nested_watch);
50 nested_watch.get();
51 }
52 value.to_pax_value_in_graph()
53 },
54 &deps,
55 );
56 Variable {
57 untyped_property,
58 converted_to_pax_value: pax_value_prop,
59 rust_type: std::any::TypeId::of::<T>(),
60 }
61 }
62
63 pub fn try_typed_binding<T: PropertyValue + CoercionRules>(
67 &self,
68 name: &str,
69 ) -> Option<LocalProperty<T>> {
70 if self.rust_type != std::any::TypeId::of::<T>()
71 || !self.untyped_property.has_value_type::<T>()
72 || !pax_value::is_typed_binding_safe::<T>()
73 {
74 return None;
75 }
76 let source = LocalProperty::<T>::new_from_untyped(self.untyped_property.clone());
79 Some(LocalProperty::computed_with_name(
80 move || source.get(),
81 &[self.untyped_property.clone()],
82 name,
83 ))
84 }
85
86 pub fn get_untyped_property(&self) -> &UntypedProperty {
88 &self.untyped_property
89 }
90
91 pub fn get_as_pax_value(&self) -> PaxValue {
93 self.converted_to_pax_value.get()
94 }
95
96 pub fn read_pax_value_ref<V>(&self, f: impl FnOnce(&PaxValue) -> V) -> V {
98 self.converted_to_pax_value.read(f)
99 }
100}