1#[cfg(feature = "designtime")]
2use crate::constants::{
3 BUTTON_CLICK_HANDLERS, CHECKBOX_CHANGE_HANDLERS, CLAP_HANDLERS, CLICK_HANDLERS,
4 CONTEXT_MENU_HANDLERS, DOUBLE_CLICK_HANDLERS, KEY_DOWN_HANDLERS, KEY_PRESS_HANDLERS,
5 KEY_UP_HANDLERS, MOUSE_DOWN_HANDLERS, MOUSE_MOVE_HANDLERS, MOUSE_OUT_HANDLERS,
6 MOUSE_OVER_HANDLERS, MOUSE_UP_HANDLERS, SCROLL_HANDLERS, TEXTBOX_CHANGE_HANDLERS,
7 TOUCH_END_HANDLERS, TOUCH_MOVE_HANDLERS, TOUCH_START_HANDLERS, WHEEL_HANDLERS,
8};
9use crate::Globals;
10use core::fmt;
11use std::any::Any;
12use std::cell::RefCell;
13use std::rc::{Rc, Weak};
14
15use kurbo::Point;
16
17use pax_runtime_api::{
18 ArgsButtonClick, ArgsCheckboxChange, ArgsClap, ArgsClick, ArgsContextMenu, ArgsDoubleClick,
19 ArgsKeyDown, ArgsKeyPress, ArgsKeyUp, ArgsMouseDown, ArgsMouseMove, ArgsMouseOut,
20 ArgsMouseOver, ArgsMouseUp, ArgsScroll, ArgsTextboxChange, ArgsTouchEnd, ArgsTouchMove,
21 ArgsTouchStart, ArgsWheel, Axis, CommonProperties, NodeContext, RenderContext, Size,
22};
23
24use crate::{
25 compute_tab, ComponentInstance, InstanceNode, InstanceNodePtr, PropertiesComputable,
26 RuntimeContext, RuntimePropertiesStackFrame, TransformAndBounds,
27};
28
29pub struct ExpandedNode {
30 #[allow(dead_code)]
31 pub id_chain: Vec<u32>,
34
35 pub instance_node: InstanceNodePtr,
37
38 pub parent_expanded_node: RefCell<Weak<ExpandedNode>>,
41
42 pub containing_component: Weak<ExpandedNode>,
47
48 pub stack: Rc<RuntimePropertiesStackFrame>,
52
53 children: RefCell<Vec<Rc<ExpandedNode>>>,
55
56 pub properties: Rc<RefCell<dyn Any>>,
58
59 common_properties: Rc<RefCell<CommonProperties>>,
61
62 pub layout_properties: RefCell<Option<LayoutProperties>>,
66
67 pub expanded_slot_children: RefCell<Option<Vec<Rc<ExpandedNode>>>>,
72 pub expanded_and_flattened_slot_children: RefCell<Option<Vec<Rc<ExpandedNode>>>>,
77
78 pub attached: RefCell<u32>,
85
86 pub occlusion_id: RefCell<u32>,
89}
90
91macro_rules! dispatch_event_handler {
92 ($fn_name:ident, $arg_type:ty, $handler_field:ident, $handler_key:ident) => {
93 pub fn $fn_name(&self, args: $arg_type, globals: &Globals) {
94 if let Some(registry) = self.instance_node.base().get_handler_registry() {
95 let component_properties = if let Some(cc) = self.containing_component.upgrade() {
96 Rc::clone(&cc.properties)
97 } else {
98 Rc::clone(&self.properties)
99 };
100
101 let comp_props = self.layout_properties.borrow();
102 let bounds_self = comp_props.as_ref().unwrap().computed_tab.bounds;
103 let bounds_parent = self
104 .parent_expanded_node
105 .borrow()
106 .upgrade()
107 .map(|parent| {
108 let comp_props = parent.layout_properties.borrow();
109 let bounds_parent = comp_props.as_ref().unwrap().computed_tab.bounds;
110 bounds_parent
111 })
112 .unwrap_or(globals.viewport.bounds);
113 let context = NodeContext {
114 bounds_self,
115 bounds_parent,
116 frames_elapsed: globals.frames_elapsed,
117 #[cfg(feature = "designtime")]
118 designtime: globals.designtime.clone(),
119 };
120
121 let borrowed_registry = &(*registry).borrow();
122
123 #[cfg(not(feature = "designtime"))]
124 {
125 let handlers = &borrowed_registry.$handler_field;
126 handlers.iter().for_each(|handler| {
127 handler(Rc::clone(&component_properties), &context, args.clone());
128 });
129 }
130 #[cfg(feature = "designtime")]
131 {
132 if let Some(handlers) = borrowed_registry.handlers.get($handler_key) {
133 handlers.iter().for_each(|handler| {
134 handler(
135 Rc::clone(&component_properties),
136 &context,
137 Some(Box::new(args.clone()) as Box<dyn Any>),
138 );
139 });
140 };
141 }
142 }
143
144 if let Some(parent) = &self.parent_expanded_node.borrow().upgrade() {
145 parent.$fn_name(args, globals);
146 }
147 }
148 };
149}
150
151impl ExpandedNode {
152 pub fn root(template: Rc<ComponentInstance>, context: &mut RuntimeContext) -> Rc<Self> {
153 let root_env =
154 RuntimePropertiesStackFrame::new(Rc::new(RefCell::new(())) as Rc<RefCell<dyn Any>>);
155 let root_node = Self::new(template, root_env, context, Weak::new());
156 Rc::clone(&root_node).recurse_mount(context);
157 root_node
158 }
159
160 fn new(
161 template: Rc<dyn InstanceNode>,
162 env: Rc<RuntimePropertiesStackFrame>,
163 context: &mut RuntimeContext,
164 containing_component: Weak<ExpandedNode>,
165 ) -> Rc<Self> {
166 let properties = (&template.base().instance_prototypical_properties_factory)();
167 let common_properties = (&template
168 .base()
169 .instance_prototypical_common_properties_factory)();
170
171 Rc::new(ExpandedNode {
172 id_chain: vec![context.gen_uid().0],
173 instance_node: Rc::clone(&template),
174 attached: RefCell::new(0),
175 properties,
176 common_properties,
177 stack: env,
178 parent_expanded_node: Default::default(),
179 containing_component,
180
181 children: RefCell::new(Vec::new()),
182 layout_properties: RefCell::new(None),
183 expanded_slot_children: Default::default(),
184 expanded_and_flattened_slot_children: Default::default(),
185 occlusion_id: RefCell::new(0),
186 })
187 }
188
189 pub fn create_children_detached(
190 self: &Rc<Self>,
191 templates: impl IntoIterator<Item = (Rc<dyn InstanceNode>, Rc<RuntimePropertiesStackFrame>)>,
192 context: &mut RuntimeContext,
193 ) -> Vec<Rc<ExpandedNode>> {
194 let containing_component = if self.instance_node.base().flags().is_component {
195 Rc::downgrade(&self)
196 } else {
197 Weak::clone(&self.containing_component)
198 };
199
200 let mut children = Vec::new();
201
202 for (template, env) in templates {
203 children.push(Self::new(
204 template,
205 env,
206 context,
207 Weak::clone(&containing_component),
208 ));
209 }
210 children
211 }
212
213 pub fn attach_children(
214 self: &Rc<Self>,
215 new_children: Vec<Rc<ExpandedNode>>,
216 context: &mut RuntimeContext,
217 ) {
218 let mut curr_children = self.children.borrow_mut();
219 if *self.attached.borrow() > 0 {
221 for child in curr_children.iter() {
222 Rc::clone(child).recurse_unmount(context);
223 }
224 for child in new_children.iter() {
225 Rc::clone(child).recurse_mount(context);
226 }
227 }
228 for child in new_children.iter() {
229 *child.parent_expanded_node.borrow_mut() = Rc::downgrade(self);
230 }
231 *curr_children = new_children;
232 }
233
234 pub fn set_children(
235 self: &Rc<Self>,
236 templates: impl IntoIterator<Item = (Rc<dyn InstanceNode>, Rc<RuntimePropertiesStackFrame>)>,
237 context: &mut RuntimeContext,
238 ) {
239 let new_children = self.create_children_detached(templates, context);
240 self.attach_children(new_children, context);
241 }
242
243 pub fn recurse_update(self: &Rc<Self>, context: &mut RuntimeContext) {
246 self.get_common_properties()
247 .borrow_mut()
248 .compute_properties(&self.stack, context.expression_table());
249
250 let viewport = self
251 .parent_expanded_node
252 .borrow()
253 .upgrade()
254 .and_then(|p| {
255 let props = p.layout_properties.borrow();
256 props.as_ref().map(|c| c.computed_tab.clone())
257 })
258 .unwrap_or(context.globals().viewport.clone());
259
260 *self.layout_properties.borrow_mut() = Some(LayoutProperties {
261 computed_tab: compute_tab(self, &viewport),
262 });
263
264 if let Some(ref registry) = self.instance_node.base().handler_registry {
265 for handler in ®istry.borrow().tick_handlers {
266 handler(Rc::clone(&self.properties), &self.get_node_context(context))
267 }
268 }
269 Rc::clone(&self.instance_node).update(&self, context);
270 if *self.attached.borrow() > 0 {
271 self.instance_node.handle_native_patches(self, context);
272 }
273 if let Some(ref registry) = self.instance_node.base().handler_registry {
274 #[cfg(feature = "designtime")]
275 {
276 for handler in registry
277 .borrow()
278 .handlers
279 .get("pre_render")
280 .unwrap_or(&Vec::new())
281 {
282 handler(
283 Rc::clone(&self.properties),
284 &self.get_node_context(context),
285 None,
286 )
287 }
288 }
289 #[cfg(not(feature = "designtime"))]
290 {
291 for handler in ®istry.borrow().pre_render_handlers {
292 handler(Rc::clone(&self.properties), &self.get_node_context(context))
293 }
294 }
295 }
296 for child in self.children.borrow().iter() {
297 child.recurse_update(context);
298 }
299 }
300
301 fn recurse_mount(self: Rc<Self>, context: &mut RuntimeContext) {
302 if *self.attached.borrow() == 0 {
303 *self.attached.borrow_mut() += 1;
304 context.lookup.insert(self.id_chain[0], Rc::clone(&self));
305 self.instance_node.handle_mount(&self, context);
306 if let Some(ref registry) = self.instance_node.base().handler_registry {
307 #[cfg(feature = "designtime")]
308 {
309 for handler in registry
310 .borrow()
311 .handlers
312 .get("mount")
313 .unwrap_or(&Vec::new())
314 {
315 handler(
316 Rc::clone(&self.properties),
317 &self.get_node_context(context),
318 None,
319 )
320 }
321 }
322 #[cfg(not(feature = "designtime"))]
323 {
324 for handler in ®istry.borrow().mount_handlers {
325 handler(Rc::clone(&self.properties), &self.get_node_context(context))
326 }
327 }
328 }
329 }
330 for child in self.children.borrow().iter() {
331 Rc::clone(child).recurse_mount(context);
332 }
333 }
334
335 fn recurse_unmount(self: Rc<Self>, context: &mut RuntimeContext) {
336 for child in self.children.borrow().iter() {
337 Rc::clone(child).recurse_unmount(context);
338 }
339 if *self.attached.borrow() == 1 {
340 *self.attached.borrow_mut() -= 1;
341 context.lookup.remove(&self.id_chain[0]);
342 self.instance_node.handle_unmount(&self, context);
343 }
344 }
345
346 pub fn recurse_render(&self, context: &mut RuntimeContext, rcs: &mut dyn RenderContext) {
347 for child in self.children.borrow().iter().rev() {
348 child.recurse_render(context, rcs);
349 }
350 self.instance_node.render(&self, context, rcs);
351 }
352
353 pub fn with_properties_unwrapped<T: 'static, R>(
359 &self,
360 callback: impl FnOnce(&mut T) -> R,
361 ) -> R {
362 let mut borrowed = self.properties.borrow_mut();
364
365 let mut unwrapped_value = if let Some(val) = borrowed.downcast_mut::<T>() {
367 val
368 } else {
369 panic!() };
371 callback(&mut unwrapped_value)
372 }
373
374 pub fn recurse_visit_postorder<T>(
375 self: &Rc<Self>,
376 func: &impl Fn(&Rc<Self>, &mut T),
377 val: &mut T,
378 ) {
379 for child in self.children.borrow().iter().rev() {
380 child.recurse_visit_postorder(func, val);
381 }
382 func(self, val);
383 }
384
385 pub fn get_node_context(&self, context: &RuntimeContext) -> NodeContext {
386 let globals = context.globals();
387 let computed_props = self.layout_properties.borrow();
388 let bounds_self = computed_props
389 .as_ref()
390 .map(|v| v.computed_tab.bounds)
391 .unwrap_or(globals.viewport.bounds);
392 let parent = self.parent_expanded_node.borrow().upgrade();
393 let bounds_parent = parent
394 .as_ref()
395 .and_then(|p| {
396 let props = p.layout_properties.borrow();
397 props.as_ref().map(|v| v.computed_tab.bounds)
398 })
399 .unwrap_or(globals.viewport.bounds);
400 NodeContext {
401 frames_elapsed: globals.frames_elapsed,
402 bounds_self,
403 bounds_parent,
404 #[cfg(feature = "designtime")]
405 designtime: globals.designtime.clone(),
406 }
407 }
408
409 pub fn get_common_properties(&self) -> Rc<RefCell<CommonProperties>> {
410 Rc::clone(&self.common_properties)
411 }
412
413 pub fn ray_cast_test(&self, ray: &(f64, f64)) -> bool {
416 if self.instance_node.base().flags().invisible_to_raycasting {
418 return false;
419 }
420
421 let props = self.layout_properties.borrow();
422 let computed_tab = &props.as_ref().unwrap().computed_tab;
423
424 let inverted_transform = computed_tab.transform.inverse();
425 let transformed_ray = inverted_transform * Point { x: ray.0, y: ray.1 };
426
427 let relevant_bounds = computed_tab.bounds;
428
429 let res = transformed_ray.x > 0.0
431 && transformed_ray.y > 0.0
432 && transformed_ray.x < relevant_bounds.0
433 && transformed_ray.y < relevant_bounds.1;
434
435 res
436 }
437
438 pub fn get_size(&self) -> (Size, Size) {
441 self.instance_node.get_size(self)
442 }
443
444 pub fn get_size_computed(&self, bounds: (f64, f64)) -> (f64, f64) {
447 let size = self.get_size();
448 (
449 size.0.evaluate(bounds, Axis::X),
450 size.1.evaluate(bounds, Axis::Y),
451 )
452 }
453
454 pub fn get_clipping_size(&self) -> Option<(Size, Size)> {
457 None
458 }
459
460 pub fn get_clipping_size_computed(&self, bounds: (f64, f64)) -> (f64, f64) {
463 match self.get_clipping_size() {
464 None => bounds,
465 Some(size_raw) => (
466 size_raw.0.evaluate(bounds, Axis::X),
467 size_raw.1.evaluate(bounds, Axis::Y),
468 ),
469 }
470 }
471
472 pub fn get_scroll_offset(&mut self) -> (f64, f64) {
475 todo!("patch into an ExpandedNode-friendly way to track this state");
477 }
478
479 pub fn compute_flattened_slot_children(&self) {
480 if let Some(slot_children) = self.expanded_slot_children.borrow().as_ref() {
481 *self.expanded_and_flattened_slot_children.borrow_mut() =
482 Some(flatten_expanded_nodes_for_slot(&slot_children));
483 }
484 }
485
486 dispatch_event_handler!(
487 dispatch_scroll,
488 ArgsScroll,
489 scroll_handlers,
490 SCROLL_HANDLERS
491 );
492 dispatch_event_handler!(dispatch_clap, ArgsClap, clap_handlers, CLAP_HANDLERS);
493 dispatch_event_handler!(
494 dispatch_touch_start,
495 ArgsTouchStart,
496 touch_start_handlers,
497 TOUCH_START_HANDLERS
498 );
499
500 dispatch_event_handler!(
501 dispatch_touch_move,
502 ArgsTouchMove,
503 touch_move_handlers,
504 TOUCH_MOVE_HANDLERS
505 );
506 dispatch_event_handler!(
507 dispatch_touch_end,
508 ArgsTouchEnd,
509 touch_end_handlers,
510 TOUCH_END_HANDLERS
511 );
512 dispatch_event_handler!(
513 dispatch_key_down,
514 ArgsKeyDown,
515 key_down_handlers,
516 KEY_DOWN_HANDLERS
517 );
518 dispatch_event_handler!(dispatch_key_up, ArgsKeyUp, key_up_handlers, KEY_UP_HANDLERS);
519 dispatch_event_handler!(
520 dispatch_key_press,
521 ArgsKeyPress,
522 key_press_handlers,
523 KEY_PRESS_HANDLERS
524 );
525 dispatch_event_handler!(
526 dispatch_checkbox_change,
527 ArgsCheckboxChange,
528 checkbox_change_handlers,
529 CHECKBOX_CHANGE_HANDLERS
530 );
531 dispatch_event_handler!(
532 dispatch_textbox_change,
533 ArgsTextboxChange,
534 textbox_change_handlers,
535 TEXTBOX_CHANGE_HANDLERS
536 );
537 dispatch_event_handler!(
538 dispatch_button_click,
539 ArgsButtonClick,
540 button_click_handlers,
541 BUTTON_CLICK_HANDLERS
542 );
543 dispatch_event_handler!(
544 dispatch_mouse_down,
545 ArgsMouseDown,
546 mouse_down_handlers,
547 MOUSE_DOWN_HANDLERS
548 );
549 dispatch_event_handler!(
550 dispatch_mouse_up,
551 ArgsMouseUp,
552 mouse_up_handlers,
553 MOUSE_UP_HANDLERS
554 );
555 dispatch_event_handler!(
556 dispatch_mouse_move,
557 ArgsMouseMove,
558 mouse_move_handlers,
559 MOUSE_MOVE_HANDLERS
560 );
561 dispatch_event_handler!(
562 dispatch_mouse_over,
563 ArgsMouseOver,
564 mouse_over_handlers,
565 MOUSE_OVER_HANDLERS
566 );
567 dispatch_event_handler!(
568 dispatch_mouse_out,
569 ArgsMouseOut,
570 mouse_out_handlers,
571 MOUSE_OUT_HANDLERS
572 );
573 dispatch_event_handler!(
574 dispatch_double_click,
575 ArgsDoubleClick,
576 double_click_handlers,
577 DOUBLE_CLICK_HANDLERS
578 );
579 dispatch_event_handler!(
580 dispatch_context_menu,
581 ArgsContextMenu,
582 context_menu_handlers,
583 CONTEXT_MENU_HANDLERS
584 );
585 dispatch_event_handler!(dispatch_click, ArgsClick, click_handlers, CLICK_HANDLERS);
586 dispatch_event_handler!(dispatch_wheel, ArgsWheel, wheel_handlers, WHEEL_HANDLERS);
587}
588
589#[cfg_attr(debug_assertions, derive(Debug))]
591pub struct LayoutProperties {
592 pub computed_tab: TransformAndBounds,
594}
595
596fn flatten_expanded_nodes_for_slot(nodes: &[Rc<ExpandedNode>]) -> Vec<Rc<ExpandedNode>> {
599 let mut result = vec![];
600 for node in nodes {
601 if node.instance_node.base().flags().invisible_to_slot {
602 result.extend(flatten_expanded_nodes_for_slot(
603 node.children
604 .borrow()
605 .clone()
606 .into_iter()
607 .collect::<Vec<_>>()
608 .as_slice(),
609 ));
610 } else {
611 result.push(Rc::clone(&node))
612 }
613 }
614 result
615}
616
617#[cfg(debug_assertions)]
618impl std::fmt::Debug for ExpandedNode {
619 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
620 pub struct Fmt<F>(pub F)
623 where
624 F: Fn(&mut fmt::Formatter) -> fmt::Result;
625
626 impl<F> fmt::Debug for Fmt<F>
627 where
628 F: Fn(&mut fmt::Formatter) -> fmt::Result,
629 {
630 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
631 (self.0)(f)
632 }
633 }
634
635 f.debug_struct("ExpandedNode")
636 .field(
637 "instance_node",
638 &Fmt(|f| self.instance_node.resolve_debug(f, Some(self))),
639 )
640 .field("id_chain", &self.id_chain)
641 .field(
647 "children",
648 &self.children.try_borrow().iter().collect::<Vec<_>>(),
649 )
650 .field(
651 "parent",
652 &self
653 .parent_expanded_node
654 .borrow()
655 .upgrade()
656 .map(|v| v.id_chain.clone()),
657 )
658 .field("occlusion_id", &self.occlusion_id.borrow())
667 .field(
668 "containing_component",
669 &self
670 .containing_component
671 .upgrade()
672 .map(|v| v.id_chain.clone()),
673 )
674 .finish()
675 }
676}