1use std::collections::HashMap;
2
3use std::iter;
4use std::rc::Rc;
5use_RefCell!();
6use crate::api::{CommonProperties, RenderContext};
7use pax_manifest::UniqueTemplateNodeIdentifier;
8use pax_message::NativeInterrupt;
9use pax_runtime_api::pax_value::PaxAny;
10use pax_runtime_api::{borrow, use_RefCell, Variable};
11use piet::{Color, StrokeStyle};
12
13use crate::api::{Layer, Scroll};
14
15use crate::{ExpandedNode, HandlerRegistry, RuntimeContext, RuntimePropertiesStackFrame};
16
17pub type InstanceNodePtr = Rc<dyn InstanceNode>;
20pub type InstanceNodePtrList = RefCell<Vec<InstanceNodePtr>>;
21
22pub struct InstantiationArgs {
23 pub prototypical_common_properties_factory: Box<
24 dyn Fn(
25 Rc<RuntimePropertiesStackFrame>,
26 Option<Rc<ExpandedNode>>,
27 ) -> Option<Rc<RefCell<CommonProperties>>>,
28 >,
29 pub prototypical_properties_factory: Box<
30 dyn Fn(
31 Rc<RuntimePropertiesStackFrame>,
32 Option<Rc<ExpandedNode>>,
33 ) -> Option<Rc<RefCell<PaxAny>>>,
34 >,
35 pub handler_registry: Option<Rc<RefCell<HandlerRegistry>>>,
36 pub children: Option<InstanceNodePtrList>,
37 pub component_template: Option<InstanceNodePtrList>,
38
39 pub template_node_identifier: Option<UniqueTemplateNodeIdentifier>,
40 pub properties_scope_factory:
42 Option<Box<dyn Fn(Rc<RefCell<PaxAny>>) -> HashMap<String, Variable>>>,
43}
44
45pub struct ReusableInstanceNodeArgs {
46 pub handler_registry: Option<Rc<RefCell<HandlerRegistry>>>,
47 pub children: InstanceNodePtrList,
48 pub template_node_identifier: Option<UniqueTemplateNodeIdentifier>,
49}
50
51impl ReusableInstanceNodeArgs {
52 pub fn new(base: &BaseInstance) -> Self {
53 ReusableInstanceNodeArgs {
54 handler_registry: base.handler_registry.clone(),
55 children: base.instance_children.clone(),
56 template_node_identifier: base.template_node_identifier.clone(),
57 }
58 }
59}
60
61#[derive(Clone)]
62pub enum NodeType {
63 Component,
64 Primitive,
65}
66
67impl std::fmt::Debug for dyn InstanceNode {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 self.resolve_debug(f, None)
70 }
71}
72
73pub trait InstanceNode {
88 fn base(&self) -> &BaseInstance;
90
91 fn instantiate(args: InstantiationArgs) -> Rc<Self>
92 where
93 Self: Sized;
94
95 fn resolve_debug(
96 &self,
97 f: &mut std::fmt::Formatter,
98 expanded_node: Option<&ExpandedNode>,
99 ) -> std::fmt::Result;
100
101 fn update(self: Rc<Self>, _expanded_node: &Rc<ExpandedNode>, _context: &Rc<RuntimeContext>) {}
103
104 #[allow(unused_variables)]
110 fn handle_pre_render(
111 &self,
112 expanded_node: &ExpandedNode,
113 context: &Rc<RuntimeContext>,
114 rcs: &mut dyn RenderContext,
115 ) {
116 }
118
119 #[allow(unused_variables)]
124 fn render(
125 &self,
126 expanded_node: &ExpandedNode,
127 context: &Rc<RuntimeContext>,
128 rcs: &mut dyn RenderContext,
129 ) {
130 }
131
132 #[allow(unused_variables)]
138 fn handle_post_render(
139 &self,
140 expanded_node: &ExpandedNode,
141 context: &Rc<RuntimeContext>,
142 rcs: &mut dyn RenderContext,
143 ) {
144 }
146
147 #[allow(unused_variables)]
152 fn handle_mount(
153 self: Rc<Self>,
154 expanded_node: &Rc<ExpandedNode>,
155 context: &Rc<RuntimeContext>,
156 ) {
157 let env = Rc::clone(&expanded_node.stack);
158 let children = borrow!(self.base().get_instance_children());
159 let children_with_envs = children.iter().cloned().zip(iter::repeat(env));
160
161 let new_children = expanded_node.generate_children(
162 children_with_envs,
163 context,
164 &expanded_node.parent_frame,
165 true,
166 );
167 expanded_node.children.set(new_children);
168 }
169
170 #[allow(unused_variables)]
173 fn handle_unmount(&self, expanded_node: &Rc<ExpandedNode>, context: &Rc<RuntimeContext>) {
174 }
178
179 #[allow(unused_variables)]
181 fn handle_scroll(&self, args_scroll: Scroll) {
182 }
184
185 fn get_template(&self) -> Option<&InstanceNodePtrList> {
186 None
187 }
188
189 fn clips_content(&self, _expanded_node: &ExpandedNode) -> bool {
191 false
192 }
193
194 fn handle_native_interrupt(
195 &self,
196 _expanded_node: &Rc<ExpandedNode>,
197 _interrupt: &NativeInterrupt,
198 ) {
199 }
201
202 fn handle_control_flow_node_expansion(
203 self: Rc<Self>,
204 _expanded_node: &Rc<ExpandedNode>,
205 _context: &Rc<RuntimeContext>,
206 ) {
207 }
208
209 fn handle_setup_slot_children(
210 self: Rc<Self>,
211 _expanded_node: &Rc<ExpandedNode>,
212 _context: &Rc<RuntimeContext>,
213 ) {
214 }
215}
216
217pub struct BaseInstance {
218 pub handler_registry: Option<Rc<RefCell<HandlerRegistry>>>,
219 pub instance_prototypical_properties_factory: Box<
220 dyn Fn(
221 Rc<RuntimePropertiesStackFrame>,
222 Option<Rc<ExpandedNode>>,
223 ) -> Option<Rc<RefCell<PaxAny>>>,
224 >,
225 pub instance_prototypical_common_properties_factory: Box<
226 dyn Fn(
227 Rc<RuntimePropertiesStackFrame>,
228 Option<Rc<ExpandedNode>>,
229 ) -> Option<Rc<RefCell<CommonProperties>>>,
230 >,
231 pub template_node_identifier: Option<UniqueTemplateNodeIdentifier>,
232 pub properties_scope_factory:
233 Option<Box<dyn Fn(Rc<RefCell<PaxAny>>) -> HashMap<String, Variable>>>,
234 instance_children: InstanceNodePtrList,
235 flags: InstanceFlags,
236}
237
238#[derive(Clone)]
239pub struct InstanceFlags {
240 pub invisible_to_slot: bool,
244 pub invisible_to_raycasting: bool,
248 pub layer: Layer,
252
253 pub is_component: bool,
255
256 pub is_slot: bool,
258}
259
260impl BaseInstance {
261 pub fn new(args: InstantiationArgs, flags: InstanceFlags) -> Self {
262 BaseInstance {
263 handler_registry: args.handler_registry,
264 instance_prototypical_common_properties_factory: args
265 .prototypical_common_properties_factory,
266 instance_prototypical_properties_factory: args.prototypical_properties_factory,
267 instance_children: args.children.unwrap_or_default(),
268 flags,
269 template_node_identifier: args.template_node_identifier,
270 properties_scope_factory: args.properties_scope_factory,
271 }
272 }
273
274 pub fn get_handler_registry(&self) -> Option<Rc<RefCell<HandlerRegistry>>> {
279 match &self.handler_registry {
280 Some(registry) => Some(Rc::clone(registry)),
281 _ => None,
282 }
283 }
284
285 pub fn get_instance_children(&self) -> &InstanceNodePtrList {
290 &self.instance_children
291 }
292
293 pub fn flags(&self) -> &InstanceFlags {
294 &self.flags
295 }
296}
297
298pub struct StrokeInstance {
300 pub color: Color,
301 pub width: f64,
302 pub style: StrokeStyle,
303}