use std::{iter, rc::Rc};
use_RefCell!();
use pax_runtime_api::pax_value::ImplToFromPaxAny;
use pax_runtime_api::{borrow, borrow_mut, use_RefCell, PaxValue, Property, ToPaxValue};
use crate::api::Layer;
use crate::{
BaseInstance, ExpandedNode, InstanceFlags, InstanceNode, InstantiationArgs, RuntimeContext,
};
pub struct ConditionalInstance {
base: BaseInstance,
}
impl ImplToFromPaxAny for ConditionalProperties {}
#[derive(Default)]
pub struct ConditionalProperties {
pub boolean_expression: Property<bool>,
}
impl ToPaxValue for ConditionalProperties {
fn to_pax_value(self) -> PaxValue {
PaxValue::Object(
vec![(
"boolean_expression".to_string(),
self.boolean_expression.to_pax_value(),
)]
.into_iter()
.collect(),
)
}
}
impl InstanceNode for ConditionalInstance {
fn instantiate(args: InstantiationArgs) -> Rc<Self>
where
Self: Sized,
{
Rc::new(Self {
base: BaseInstance::new(
args,
InstanceFlags {
invisible_to_slot: true,
invisible_to_raycasting: true,
layer: Layer::DontCare,
is_component: false,
},
),
})
}
fn handle_mount(
self: Rc<Self>,
expanded_node: &Rc<ExpandedNode>,
context: &Rc<RuntimeContext>,
) {
let weak_ref_self = Rc::downgrade(expanded_node);
let cloned_self = Rc::clone(&self);
let cloned_context = Rc::clone(context);
let cond_expr =
expanded_node.with_properties_unwrapped(|properties: &mut ConditionalProperties| {
properties.boolean_expression.clone()
});
let dep = cond_expr.untyped();
let old_val = RefCell::new(false);
expanded_node
.children
.replace_with(Property::computed_with_name(
move || {
let Some(cloned_expanded_node) = weak_ref_self.upgrade() else {
panic!("ran evaluator after expanded node dropped (conditional elem)")
};
let val = cond_expr.get();
if val == *borrow!(old_val) {
return cloned_expanded_node.children.get();
}
*borrow_mut!(old_val) = val;
if val {
let env = Rc::clone(&cloned_expanded_node.stack);
let children = borrow!(cloned_self.base().get_instance_children());
let children_with_envs = children.iter().cloned().zip(iter::repeat(env));
let res = cloned_expanded_node.generate_children(
children_with_envs,
&cloned_context,
&cloned_expanded_node.parent_frame,
);
res
} else {
cloned_expanded_node.generate_children(
vec![],
&cloned_context,
&cloned_expanded_node.parent_frame,
)
}
},
&[dep],
&format!("conditional_children (node id: {})", expanded_node.id.0),
));
}
fn resolve_debug(
&self,
f: &mut std::fmt::Formatter,
_expanded_node: Option<&ExpandedNode>,
) -> std::fmt::Result {
f.debug_struct("Conditional").finish()
}
fn base(&self) -> &BaseInstance {
&self.base
}
}