1use std::collections::{BTreeMap, HashMap};
2
3use std::iter;
4use std::rc::Rc;
5use_RefCell!();
6use crate::api::{math::Point2, CommonProperties, RenderContext, SceneAmbientLight, SceneLight};
7use pax_manifest::cartridge_generation::ComponentTransitionConfig;
8use pax_manifest::{
9 SettingsBlockElement, TemplateNodeSelectorInfo, TypeId, UniqueTemplateNodeIdentifier,
10};
11use pax_message::NativeInterrupt;
12use pax_runtime_api::pax_value::PaxAny;
13use pax_runtime_api::{borrow, use_RefCell, Variable};
14use piet::{Color, StrokeStyle};
15
16use crate::api::{Layer, Scroll, Window};
17
18use crate::{
19 create_new_common_properties, create_new_common_properties_from_columns,
20 property_columns_from_defined_properties, update_existing_common_properties,
21 update_existing_common_properties_from_columns, ErasedComponentDescriptor, ExpandedNode,
22 HandlerRegistry, ReceivedChildrenSource, RuntimeContext, RuntimePropertiesStackFrame,
23 TemplatePropertyPlan,
24};
25use pax_manifest::ValueDefinition;
26
27pub type InstanceNodePtr = Rc<dyn InstanceNode>;
30pub type InstanceNodePtrList = RefCell<Vec<InstanceNodePtr>>;
31pub type CommonPropertiesFactory = Box<
32 dyn Fn(
33 Rc<RuntimePropertiesStackFrame>,
34 Option<Rc<ExpandedNode>>,
35 ) -> Option<Rc<RefCell<CommonProperties>>>,
36>;
37pub type PropertiesFactory = Box<
38 dyn Fn(
39 Rc<RuntimePropertiesStackFrame>,
40 Option<Rc<ExpandedNode>>,
41 ) -> Option<Rc<RefCell<PaxAny>>>,
42>;
43pub type PropertiesScopeFactory = Box<dyn Fn(Rc<RefCell<PaxAny>>) -> HashMap<String, Variable>>;
44
45pub enum CommonPropertiesInit {
47 Default,
48 Inline {
49 defined_properties: BTreeMap<String, ValueDefinition>,
50 },
51 Template(Rc<TemplatePropertyPlan>),
52 Factory(CommonPropertiesFactory),
53}
54
55impl CommonPropertiesInit {
56 fn requires_pre_node_binding(&self) -> bool {
57 match self {
58 Self::Factory(_) => true,
59 Self::Inline { defined_properties } => defined_properties
60 .values()
61 .any(crate::value_uses_local_property_scope),
62 Self::Template(plan) => plan.requires_pre_node_binding,
63 Self::Default => false,
64 }
65 }
66
67 pub(crate) fn allocate(
70 &self,
71 stack: Rc<RuntimePropertiesStackFrame>,
72 ) -> Rc<RefCell<CommonProperties>> {
73 match self {
74 Self::Factory(factory) => {
75 factory(stack, None).expect("common properties factory must allocate properties")
76 }
77 _ => Rc::new(RefCell::new(CommonProperties::default())),
78 }
79 }
80
81 pub fn materialize(
82 &self,
83 stack_frame: Rc<RuntimePropertiesStackFrame>,
84 expanded_node: Option<Rc<ExpandedNode>>,
85 ) -> Option<Rc<RefCell<CommonProperties>>> {
86 match self {
87 CommonPropertiesInit::Default => expanded_node
88 .is_none()
89 .then(|| Rc::new(RefCell::new(CommonProperties::default()))),
90 CommonPropertiesInit::Inline { defined_properties } => {
91 if let Some(expanded_node) = expanded_node {
92 update_existing_common_properties(
93 &expanded_node,
94 defined_properties,
95 &stack_frame,
96 );
97 None
98 } else {
99 Some(create_new_common_properties(
100 defined_properties,
101 &stack_frame,
102 ))
103 }
104 }
105 CommonPropertiesInit::Template(plan) => {
106 let columns = plan.resolve(expanded_node.as_ref());
107 if let Some(node) = expanded_node {
108 update_existing_common_properties_from_columns(&node, &columns, &stack_frame);
109 None
110 } else {
111 Some(create_new_common_properties_from_columns(
112 &columns,
113 &stack_frame,
114 ))
115 }
116 }
117 CommonPropertiesInit::Factory(factory) => factory(stack_frame, expanded_node),
118 }
119 }
120}
121
122pub enum PropertiesInit {
124 DescriptorDefault(&'static ErasedComponentDescriptor),
125 DescriptorInline {
126 descriptor: &'static ErasedComponentDescriptor,
127 defined_properties: BTreeMap<String, ValueDefinition>,
128 },
129 Template {
130 descriptor: &'static ErasedComponentDescriptor,
131 plan: Rc<TemplatePropertyPlan>,
132 },
133 Factory(PropertiesFactory),
134}
135
136impl PropertiesInit {
137 fn requires_pre_node_binding(&self) -> bool {
138 match self {
139 Self::Factory(_) => true,
140 Self::DescriptorInline {
141 defined_properties, ..
142 } => defined_properties
143 .values()
144 .any(crate::value_uses_local_property_scope),
145 Self::Template { plan, .. } => plan.requires_pre_node_binding,
146 Self::DescriptorDefault(_) => false,
147 }
148 }
149
150 pub(crate) fn allocate(&self, stack: Rc<RuntimePropertiesStackFrame>) -> Rc<RefCell<PaxAny>> {
152 match self {
153 Self::DescriptorDefault(descriptor)
154 | Self::DescriptorInline { descriptor, .. }
155 | Self::Template { descriptor, .. } => {
156 Rc::new(RefCell::new((descriptor.create_properties)()))
157 }
158 Self::Factory(factory) => {
159 factory(stack, None).expect("properties factory must allocate properties")
160 }
161 }
162 }
163
164 pub fn materialize(
165 &self,
166 stack_frame: Rc<RuntimePropertiesStackFrame>,
167 expanded_node: Option<Rc<ExpandedNode>>,
168 ) -> Option<Rc<RefCell<PaxAny>>> {
169 match self {
170 PropertiesInit::DescriptorDefault(descriptor) => expanded_node
171 .is_none()
172 .then(|| Rc::new(RefCell::new((descriptor.create_properties)()))),
173 PropertiesInit::DescriptorInline {
174 descriptor,
175 defined_properties,
176 } => {
177 if let Some(expanded_node) = expanded_node {
178 let outer_ref = expanded_node.properties.borrow();
179 let rc = Rc::clone(&outer_ref);
180 let mut inner_ref = (*rc).borrow_mut();
181 (descriptor.apply_defined_properties)(
182 descriptor.typed_descriptor,
183 &mut inner_ref,
184 &property_columns_from_defined_properties(defined_properties),
185 &stack_frame,
186 );
187 None
188 } else {
189 let mut properties = (descriptor.create_properties)();
190 (descriptor.apply_defined_properties)(
191 descriptor.typed_descriptor,
192 &mut properties,
193 &property_columns_from_defined_properties(defined_properties),
194 &stack_frame,
195 );
196 Some(Rc::new(RefCell::new(properties)))
197 }
198 }
199 PropertiesInit::Template { descriptor, plan } => {
200 let columns = plan.resolve(expanded_node.as_ref());
201 if let Some(node) = expanded_node {
202 let properties = Rc::clone(&node.properties.borrow());
203 (descriptor.apply_defined_properties)(
204 descriptor.typed_descriptor,
205 &mut properties.borrow_mut(),
206 &columns,
207 &stack_frame,
208 );
209 None
210 } else {
211 let mut properties = (descriptor.create_properties)();
212 (descriptor.apply_defined_properties)(
213 descriptor.typed_descriptor,
214 &mut properties,
215 &columns,
216 &stack_frame,
217 );
218 Some(Rc::new(RefCell::new(properties)))
219 }
220 }
221 PropertiesInit::Factory(factory) => factory(stack_frame, expanded_node),
222 }
223 }
224}
225
226pub enum PropertiesScopeInit {
228 None,
229 Descriptor(&'static ErasedComponentDescriptor),
230 Factory(PropertiesScopeFactory),
231}
232
233impl PropertiesScopeInit {
234 pub fn build(&self, properties: Rc<RefCell<PaxAny>>) -> HashMap<String, Variable> {
235 match self {
236 PropertiesScopeInit::None => HashMap::new(),
237 PropertiesScopeInit::Descriptor(descriptor) => {
238 let props_ref = borrow!(properties.as_ref());
239 (descriptor.build_property_scope)(descriptor.typed_descriptor, &props_ref)
240 }
241 PropertiesScopeInit::Factory(factory) => factory(properties),
242 }
243 }
244}
245
246pub struct InstantiationArgs {
248 pub prototypical_common_properties: CommonPropertiesInit,
249 pub prototypical_properties: PropertiesInit,
250 pub handler_registry: Option<Rc<RefCell<HandlerRegistry>>>,
251 pub children: Option<InstanceNodePtrList>,
252 pub component_template: Option<InstanceNodePtrList>,
253 pub component_settings: Option<Vec<SettingsBlockElement>>,
254
255 pub template_node_identifier: Option<UniqueTemplateNodeIdentifier>,
256 pub template_node_type_id: Option<TypeId>,
257 pub template_node_selector_info: Option<TemplateNodeSelectorInfo>,
258 pub transition_config: ComponentTransitionConfig,
259 pub properties_scope: PropertiesScopeInit,
261}
262
263pub struct ReusableInstanceNodeArgs {
265 pub handler_registry: Option<Rc<RefCell<HandlerRegistry>>>,
266 pub children: InstanceNodePtrList,
267 pub template_node_identifier: Option<UniqueTemplateNodeIdentifier>,
268 pub template_node_type_id: Option<TypeId>,
269 pub template_node_selector_info: Option<TemplateNodeSelectorInfo>,
270}
271
272impl ReusableInstanceNodeArgs {
273 pub fn new(base: &BaseInstance) -> Self {
275 ReusableInstanceNodeArgs {
276 handler_registry: base.handler_registry.clone(),
277 children: base.instance_children.clone(),
278 template_node_identifier: base.template_node_identifier.clone(),
279 template_node_type_id: base.template_node_type_id.clone(),
280 template_node_selector_info: base.template_node_selector_info.clone(),
281 }
282 }
283}
284
285#[derive(Clone)]
286pub enum NodeType {
288 Component,
289 Primitive,
290}
291
292impl std::fmt::Debug for dyn InstanceNode {
293 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
294 self.resolve_debug(f, None)
295 }
296}
297
298pub trait InstanceNode {
313 fn base(&self) -> &BaseInstance;
315
316 fn instantiate(args: InstantiationArgs) -> Rc<Self>
317 where
318 Self: Sized;
319
320 fn resolve_debug(
321 &self,
322 f: &mut std::fmt::Formatter,
323 expanded_node: Option<&ExpandedNode>,
324 ) -> std::fmt::Result;
325
326 fn requires_non_reactive_update(&self, _expanded_node: &ExpandedNode) -> bool {
329 false
330 }
331
332 fn resolve_scene_light(
334 &self,
335 _expanded_node: &ExpandedNode,
336 _context: &RuntimeContext,
337 ) -> Option<SceneLight> {
338 None
339 }
340
341 fn resolve_scene_ambient_light(
343 &self,
344 _expanded_node: &ExpandedNode,
345 _context: &RuntimeContext,
346 ) -> Option<SceneAmbientLight> {
347 None
348 }
349
350 fn establishes_light_frame(&self) -> bool {
352 false
353 }
354
355 fn update(self: Rc<Self>, _expanded_node: &Rc<ExpandedNode>, _context: &Rc<RuntimeContext>) {}
357
358 #[allow(unused_variables)]
364 fn handle_pre_render(
365 &self,
366 expanded_node: &ExpandedNode,
367 context: &Rc<RuntimeContext>,
368 rcs: &mut dyn RenderContext,
369 ) {
370 }
372
373 #[allow(unused_variables)]
378 fn render(
379 &self,
380 expanded_node: &ExpandedNode,
381 context: &Rc<RuntimeContext>,
382 rcs: &mut dyn RenderContext,
383 ) {
384 }
385
386 #[allow(unused_variables)]
392 fn handle_post_render(
393 &self,
394 expanded_node: &ExpandedNode,
395 context: &Rc<RuntimeContext>,
396 rcs: &mut dyn RenderContext,
397 ) {
398 }
400
401 #[allow(unused_variables)]
406 fn handle_mount(
407 self: Rc<Self>,
408 expanded_node: &Rc<ExpandedNode>,
409 context: &Rc<RuntimeContext>,
410 ) {
411 let env = Rc::clone(&expanded_node.stack);
412 let children = borrow!(self.base().get_instance_children());
413 let children_with_envs = children.iter().cloned().zip(iter::repeat(env));
414
415 let new_children = expanded_node.generate_children(
416 children_with_envs,
417 context,
418 &expanded_node.parent_frame,
419 true,
420 );
421 expanded_node.children.set(new_children);
422 }
423
424 #[allow(unused_variables)]
427 fn handle_unmount(&self, expanded_node: &Rc<ExpandedNode>, context: &Rc<RuntimeContext>) {
428 }
432
433 #[allow(unused_variables)]
435 fn handle_scroll(&self, args_scroll: Scroll) {
436 }
438
439 fn get_template(&self) -> Option<&InstanceNodePtrList> {
440 None
441 }
442
443 fn clips_content(&self, _expanded_node: &ExpandedNode) -> bool {
445 false
446 }
447
448 fn ray_cast_test(&self, expanded_node: &ExpandedNode, ray: Point2<Window>) -> bool {
450 let t_and_b = expanded_node.transform_and_bounds.get();
451 let inverted_transform = t_and_b.transform.inverse();
452 let transformed_ray = inverted_transform * ray;
453 let (width, height) = t_and_b.bounds;
454 transformed_ray.x > 0.0
455 && transformed_ray.y > 0.0
456 && transformed_ray.x < width
457 && transformed_ray.y < height
458 }
459
460 fn scrolls_content(&self, _expanded_node: &ExpandedNode) -> bool {
462 false
463 }
464
465 fn property_requires_occlusion_recompute(&self, _property_name: &str) -> bool {
473 true
474 }
475
476 fn materializes_native_surface(&self, _expanded_node: &ExpandedNode) -> bool {
478 false
479 }
480
481 fn materializes_native_surface_before_children(&self, _expanded_node: &ExpandedNode) -> bool {
488 false
489 }
490
491 fn resolve_scroll_offset(&self, _expanded_node: &ExpandedNode) -> Option<(f64, f64)> {
493 None
494 }
495
496 fn received_children_source(&self) -> ReceivedChildrenSource {
509 if self.base().flags().is_component {
510 ReceivedChildrenSource::Projected
511 } else {
512 ReceivedChildrenSource::Owned
513 }
514 }
515
516 fn handle_native_interrupt(
517 &self,
518 _expanded_node: &Rc<ExpandedNode>,
519 _interrupt: &NativeInterrupt,
520 ) {
521 }
523
524 fn handle_control_flow_node_expansion(
525 self: Rc<Self>,
526 _expanded_node: &Rc<ExpandedNode>,
527 _context: &Rc<RuntimeContext>,
528 ) {
529 }
530
531 fn handle_setup_projected_children(
532 self: Rc<Self>,
533 _expanded_node: &Rc<ExpandedNode>,
534 _context: &Rc<RuntimeContext>,
535 ) {
536 }
537
538 fn resolve_coverage_path(&self, _expanded_node: &ExpandedNode) -> Option<kurbo::BezPath> {
539 None
540 }
541
542 fn resolve_alpha_mask_paints(
545 &self,
546 _expanded_node: &ExpandedNode,
547 ) -> Vec<pax_runtime_api::AlphaMaskPaint> {
548 Vec::new()
549 }
550
551 fn resolve_occlusion_path(&self, expanded_node: &ExpandedNode) -> Option<kurbo::BezPath> {
557 self.resolve_coverage_path(expanded_node)
558 }
559
560 fn resolve_coverage_opacity(&self, expanded_node: &ExpandedNode) -> f64 {
561 expanded_node.computed_opacity.get()
562 }
563
564 fn resolve_effect_clip_path(&self, _expanded_node: &ExpandedNode) -> Option<kurbo::BezPath> {
565 None
566 }
567}
568
569pub struct BaseInstance {
571 pub handler_registry: Option<Rc<RefCell<HandlerRegistry>>>,
572 pub instance_prototypical_properties: PropertiesInit,
573 pub instance_prototypical_common_properties: CommonPropertiesInit,
574 pub component_settings: Option<Vec<SettingsBlockElement>>,
575 pub template_node_identifier: Option<UniqueTemplateNodeIdentifier>,
576 pub template_node_type_id: Option<TypeId>,
577 pub template_node_selector_info: Option<TemplateNodeSelectorInfo>,
578 pub transition_config: ComponentTransitionConfig,
579 pub properties_scope: PropertiesScopeInit,
580 instance_children: InstanceNodePtrList,
581 flags: InstanceFlags,
582}
583
584#[derive(Clone)]
585pub struct InstanceFlags {
587 pub invisible_to_slot: bool,
592 pub invisible_to_raycasting: bool,
596 pub layer: Layer,
601
602 pub is_component: bool,
604
605 pub is_slot: bool,
607}
608
609impl BaseInstance {
610 pub(crate) fn requires_pre_node_binding(&self) -> bool {
611 self.instance_prototypical_common_properties
612 .requires_pre_node_binding()
613 || self
614 .instance_prototypical_properties
615 .requires_pre_node_binding()
616 || matches!(self.properties_scope, PropertiesScopeInit::Factory(_))
617 }
618
619 pub(crate) fn bind_properties(&self, node: &Rc<ExpandedNode>) {
624 if let (
625 CommonPropertiesInit::Template(common_plan),
626 PropertiesInit::Template { descriptor, plan },
627 ) = (
628 &self.instance_prototypical_common_properties,
629 &self.instance_prototypical_properties,
630 ) {
631 if Rc::ptr_eq(common_plan, plan) {
632 let columns = plan.resolve(Some(node));
633 update_existing_common_properties_from_columns(node, &columns, &node.stack);
634 let properties = Rc::clone(&node.properties.borrow());
635 (descriptor.apply_defined_properties)(
636 descriptor.typed_descriptor,
637 &mut properties.borrow_mut(),
638 &columns,
639 &node.stack,
640 );
641 return;
642 }
643 }
644 self.instance_prototypical_common_properties
645 .materialize(Rc::clone(&node.stack), Some(Rc::clone(node)));
646 self.instance_prototypical_properties
647 .materialize(Rc::clone(&node.stack), Some(Rc::clone(node)));
648 }
649
650 pub fn new(args: InstantiationArgs, flags: InstanceFlags) -> Self {
652 BaseInstance {
653 handler_registry: args.handler_registry,
654 instance_prototypical_common_properties: args.prototypical_common_properties,
655 instance_prototypical_properties: args.prototypical_properties,
656 component_settings: args.component_settings,
657 instance_children: args.children.unwrap_or_default(),
658 flags,
659 template_node_identifier: args.template_node_identifier,
660 template_node_type_id: args.template_node_type_id,
661 template_node_selector_info: args.template_node_selector_info,
662 transition_config: args.transition_config,
663 properties_scope: args.properties_scope,
664 }
665 }
666
667 pub fn get_handler_registry(&self) -> Option<Rc<RefCell<HandlerRegistry>>> {
672 match &self.handler_registry {
673 Some(registry) => Some(Rc::clone(registry)),
674 _ => None,
675 }
676 }
677
678 pub fn get_instance_children(&self) -> &InstanceNodePtrList {
684 &self.instance_children
685 }
686
687 pub fn flags(&self) -> &InstanceFlags {
689 &self.flags
690 }
691
692 pub fn transition_config(&self) -> &ComponentTransitionConfig {
693 &self.transition_config
694 }
695}
696
697pub struct StrokeInstance {
699 pub color: Color,
700 pub width: f64,
701 pub style: StrokeStyle,
702}