1use std::any::Any;
2use std::cell::RefCell;
3use std::iter;
4use std::rc::Rc;
5
6use crate::declarative_macros::handle_vtable_update_optional;
7use crate::{
8 BaseInstance, ExpandedNode, InstanceFlags, InstanceNode, InstantiationArgs, RuntimeContext,
9};
10use pax_runtime_api::Layer;
11
12pub struct RepeatInstance {
18 pub base: BaseInstance,
19}
20
21#[derive(Default)]
24pub struct RepeatProperties {
25 pub source_expression_vec:
26 Option<Box<dyn pax_runtime_api::PropertyInstance<Vec<Rc<RefCell<dyn Any>>>>>>,
27 pub source_expression_range:
28 Option<Box<dyn pax_runtime_api::PropertyInstance<std::ops::Range<isize>>>>,
29 last_len: usize,
30 last_bounds: (f64, f64),
31}
32
33pub struct RepeatItem {
34 pub elem: Rc<RefCell<dyn Any>>,
35 pub i: usize,
36}
37
38impl InstanceNode for RepeatInstance {
39 fn instantiate(args: InstantiationArgs) -> Rc<Self>
40 where
41 Self: Sized,
42 {
43 Rc::new(Self {
44 base: BaseInstance::new(
45 args,
46 InstanceFlags {
47 invisible_to_slot: true,
48 invisible_to_raycasting: true,
49 layer: Layer::DontCare,
50 is_component: false,
51 },
52 ),
53 })
54 }
55
56 #[cfg(debug_assertions)]
57 fn resolve_debug(
58 &self,
59 f: &mut std::fmt::Formatter,
60 _expanded_node: Option<&ExpandedNode>,
61 ) -> std::fmt::Result {
62 f.debug_struct("Repeat").finish()
63 }
64
65 fn base(&self) -> &BaseInstance {
66 &self.base
67 }
68
69 fn update(self: Rc<Self>, expanded_node: &Rc<ExpandedNode>, context: &mut RuntimeContext) {
70 let new_vec =
71 expanded_node.with_properties_unwrapped(|properties: &mut RepeatProperties| {
72 handle_vtable_update_optional(
73 context.expression_table(),
74 &expanded_node.stack,
75 properties.source_expression_range.as_mut(),
76 );
77 handle_vtable_update_optional(
78 context.expression_table(),
79 &expanded_node.stack,
80 properties.source_expression_vec.as_mut(),
81 );
82
83 let vec = if let Some(ref source) = properties.source_expression_range {
84 Box::new(
85 source
86 .get()
87 .clone()
88 .map(|v| Rc::new(RefCell::new(v)) as Rc<RefCell<dyn Any>>),
89 ) as Box<dyn ExactSizeIterator<Item = Rc<RefCell<dyn Any>>>>
90 } else if let Some(ref source) = properties.source_expression_vec {
91 Box::new(source.get().clone().into_iter())
92 as Box<dyn ExactSizeIterator<Item = Rc<RefCell<dyn Any>>>>
93 } else {
94 unreachable!();
96 };
97
98 let current_len = vec.len();
99 let exp_props = expanded_node.layout_properties.borrow();
100 let current_bounds = exp_props
101 .as_ref()
102 .map(|t| t.computed_tab.bounds)
103 .unwrap_or_default();
104 let update_children =
105 current_len != properties.last_len || current_bounds != properties.last_bounds;
106 properties.last_len = current_len;
107 properties.last_bounds = current_bounds;
108 update_children.then_some(vec)
109 });
110
111 if let Some(vec) = new_vec {
112 let template_children = self.base().get_instance_children();
113 let children_with_envs = iter::repeat(template_children)
114 .zip(vec.into_iter())
115 .enumerate()
116 .flat_map(|(i, (children, elem))| {
117 let new_repeat_item = Rc::new(RefCell::new(RepeatItem {
118 i,
119 elem: Rc::clone(&elem),
120 })) as Rc<RefCell<dyn Any>>;
121 let new_env = expanded_node.stack.push(&new_repeat_item);
122 children.clone().into_iter().zip(iter::repeat(new_env))
123 });
124 expanded_node.set_children(children_with_envs, context);
125 }
126 }
127
128 fn handle_mount(&self, _expanded_node: &Rc<ExpandedNode>, _context: &mut RuntimeContext) {
129 }
132}