pax_runtime/
conditional.rs1use std::{iter, rc::Rc};
2use_RefCell!();
3
4use pax_runtime_api::pax_value::ImplToFromPaxAny;
5use pax_runtime_api::{borrow, borrow_mut, use_RefCell, PaxValue, Property, ToPaxValue};
6
7use crate::api::Layer;
8use crate::{
9 BaseInstance, ExpandedNode, InstanceFlags, InstanceNode, InstantiationArgs, RuntimeContext,
10};
11
12pub struct ConditionalInstance {
18 base: BaseInstance,
19}
20
21impl ImplToFromPaxAny for ConditionalProperties {}
22
23#[derive(Default)]
25pub struct ConditionalProperties {
26 pub boolean_expression: Property<bool>,
27}
28
29impl ToPaxValue for ConditionalProperties {
30 fn to_pax_value(self) -> PaxValue {
31 PaxValue::Object(
32 vec![(
33 "boolean_expression".to_string(),
34 self.boolean_expression.to_pax_value(),
35 )]
36 .into_iter()
37 .collect(),
38 )
39 }
40}
41
42impl InstanceNode for ConditionalInstance {
43 fn instantiate(args: InstantiationArgs) -> Rc<Self>
44 where
45 Self: Sized,
46 {
47 Rc::new(Self {
48 base: BaseInstance::new(
49 args,
50 InstanceFlags {
51 invisible_to_slot: true,
52 invisible_to_raycasting: true,
53 layer: Layer::DontCare,
54 is_component: false,
55 is_slot: false,
56 },
57 ),
58 })
59 }
60
61 fn handle_mount(
62 self: Rc<Self>,
63 expanded_node: &Rc<ExpandedNode>,
64 context: &Rc<RuntimeContext>,
65 ) {
66 self.handle_setup(expanded_node, context, true);
67 }
68
69 fn handle_control_flow_node_expansion(
70 self: Rc<Self>,
71 expanded_node: &Rc<ExpandedNode>,
72 context: &Rc<RuntimeContext>,
73 ) {
74 self.handle_setup(expanded_node, context, false);
75 }
76
77 fn resolve_debug(
78 &self,
79 f: &mut std::fmt::Formatter,
80 _expanded_node: Option<&ExpandedNode>,
81 ) -> std::fmt::Result {
82 f.debug_struct("Conditional").finish()
83 }
84
85 fn base(&self) -> &BaseInstance {
86 &self.base
87 }
88}
89
90impl ConditionalInstance {
91 fn handle_setup(
92 self: Rc<Self>,
93 expanded_node: &Rc<ExpandedNode>,
94 context: &Rc<RuntimeContext>,
95 is_mount: bool,
96 ) {
97 let weak_ref_self = Rc::downgrade(expanded_node);
98 let cloned_self = Rc::clone(&self);
99 let cloned_context = Rc::clone(context);
100
101 let cond_expr =
102 expanded_node.with_properties_unwrapped(|properties: &mut ConditionalProperties| {
103 properties.boolean_expression.clone()
104 });
105
106 let dep = cond_expr.untyped();
107
108 let old_val = RefCell::new(false);
109 expanded_node
110 .children
111 .replace_with(Property::computed_with_name(
112 move || {
113 let Some(cloned_expanded_node) = weak_ref_self.upgrade() else {
114 panic!("ran evaluator after expanded node dropped (conditional elem)")
115 };
116 let val = cond_expr.get();
117 if val == *borrow!(old_val) {
118 return cloned_expanded_node.children.get();
119 }
120 *borrow_mut!(old_val) = val;
121 if val {
122 let env = Rc::clone(&cloned_expanded_node.stack);
123 let children = borrow!(cloned_self.base().get_instance_children());
124 let children_with_envs = children.iter().cloned().zip(iter::repeat(env));
125 let res = cloned_expanded_node.generate_children(
126 children_with_envs,
127 &cloned_context,
128 &cloned_expanded_node.parent_frame,
129 is_mount,
130 );
131 res
132 } else {
133 cloned_expanded_node.generate_children(
134 vec![],
135 &cloned_context,
136 &cloned_expanded_node.parent_frame,
137 is_mount,
138 )
139 }
140 },
141 &[dep],
142 &format!("conditional_children (node id: {})", expanded_node.id.0),
143 ));
144 }
145}