use super::*;
#[cfg(test)]
mod tests;
#[derive(Clone)]
pub struct Variable {
untyped_property: UntypedProperty,
converted_to_pax_value: LocalProperty<PaxValue>,
rust_type: std::any::TypeId,
}
impl Variable {
pub fn new<T: PropertyValue + ToPaxValue>(untyped_property: UntypedProperty) -> Self {
Self::new_from_typed_property(LocalProperty::<T>::new_from_untyped(
untyped_property.clone(),
))
}
pub fn new_from_typed_property<T: PropertyValue + ToPaxValue>(
property: impl PropertyBinding<T>,
) -> Self {
let property = property.local();
let untyped_property = property.untyped();
let deps = [untyped_property.clone()];
let nested_watch = LocalProperty::<()>::default();
let pax_value_prop = LocalProperty::computed(
move || {
let value = property.get();
let dependencies = value.nested_properties();
if dependencies.is_empty() {
nested_watch.replace_with(LocalProperty::default());
} else {
let source = property.clone();
let initial = std::cell::Cell::new(true);
nested_watch.replace_with(LocalProperty::computed(
move || {
if !initial.replace(false) {
source.invalidate();
}
},
&dependencies,
));
crate::properties::register_effect_property(&nested_watch);
nested_watch.get();
}
value.to_pax_value_in_graph()
},
&deps,
);
Variable {
untyped_property,
converted_to_pax_value: pax_value_prop,
rust_type: std::any::TypeId::of::<T>(),
}
}
pub fn try_typed_binding<T: PropertyValue + CoercionRules>(
&self,
name: &str,
) -> Option<LocalProperty<T>> {
if self.rust_type != std::any::TypeId::of::<T>()
|| !self.untyped_property.has_value_type::<T>()
|| !pax_value::is_typed_binding_safe::<T>()
{
return None;
}
let source = LocalProperty::<T>::new_from_untyped(self.untyped_property.clone());
Some(LocalProperty::computed_with_name(
move || source.get(),
&[self.untyped_property.clone()],
name,
))
}
pub fn get_untyped_property(&self) -> &UntypedProperty {
&self.untyped_property
}
pub fn get_as_pax_value(&self) -> PaxValue {
self.converted_to_pax_value.get()
}
pub fn read_pax_value_ref<V>(&self, f: impl FnOnce(&PaxValue) -> V) -> V {
self.converted_to_pax_value.read(f)
}
}