1mod constraint;
2mod node;
3
4use std::{num::NonZero, sync::Arc, time::Instant};
5
6use log::debug;
7use parking_lot::RwLock;
8use rayon::prelude::*;
9
10use crate::{
11 Clipboard, ComputeResourceManager,
12 cursor::CursorEvent,
13 px::{PxPosition, PxSize},
14 renderer::Command,
15};
16
17pub use constraint::{Constraint, DimensionValue};
18pub use node::{
19 ComponentNode, ComponentNodeMetaData, ComponentNodeMetaDatas, ComponentNodeTree, ComputedData,
20 ImeRequest, MeasureFn, MeasurementError, StateHandlerFn, StateHandlerInput, WindowRequests,
21 measure_node, measure_nodes, place_node,
22};
23
24pub struct ComponentTree {
26 tree: indextree::Arena<ComponentNode>,
28 metadatas: ComponentNodeMetaDatas,
30 node_queue: Vec<indextree::NodeId>,
32}
33
34impl Default for ComponentTree {
35 fn default() -> Self {
36 Self::new()
37 }
38}
39
40impl ComponentTree {
41 pub fn new() -> Self {
43 let tree = indextree::Arena::new();
44 let node_queue = Vec::new();
45 let metadatas = ComponentNodeMetaDatas::new();
46 Self {
47 tree,
48 node_queue,
49 metadatas,
50 }
51 }
52
53 pub fn clear(&mut self) {
55 self.tree.clear();
56 self.metadatas.clear();
57 self.node_queue.clear();
58 }
59
60 pub fn get(&self, node_id: indextree::NodeId) -> Option<&ComponentNode> {
62 self.tree.get(node_id).map(|n| n.get())
63 }
64
65 pub fn get_mut(&mut self, node_id: indextree::NodeId) -> Option<&mut ComponentNode> {
67 self.tree.get_mut(node_id).map(|n| n.get_mut())
68 }
69
70 pub fn current_node(&self) -> Option<&ComponentNode> {
72 self.node_queue
73 .last()
74 .and_then(|node_id| self.get(*node_id))
75 }
76
77 pub fn current_node_mut(&mut self) -> Option<&mut ComponentNode> {
79 let node_id = self.node_queue.last()?;
80 self.get_mut(*node_id)
81 }
82
83 pub fn add_node(&mut self, node_component: ComponentNode) {
87 let new_node_id = self.tree.new_node(node_component);
88 if let Some(current_node_id) = self.node_queue.last_mut() {
89 current_node_id.append(new_node_id, &mut self.tree);
90 }
91 let metadata = ComponentNodeMetaData::none();
92 self.metadatas.insert(new_node_id, metadata);
93 self.node_queue.push(new_node_id);
94 }
95
96 pub fn pop_node(&mut self) {
98 self.node_queue.pop();
99 }
100
101 pub fn compute(
111 &mut self,
112 screen_size: PxSize,
113 mut cursor_position: Option<PxPosition>,
114 mut cursor_events: Vec<CursorEvent>,
115 mut keyboard_events: Vec<winit::event::KeyEvent>,
116 mut ime_events: Vec<winit::event::Ime>,
117 modifiers: winit::keyboard::ModifiersState,
118 compute_resource_manager: Arc<RwLock<ComputeResourceManager>>,
119 gpu: &wgpu::Device,
120 clipboard: &mut Clipboard,
121 ) -> (Vec<(Command, PxSize, PxPosition)>, WindowRequests) {
122 let Some(root_node) = self.tree.get_node_id_at(NonZero::new(1).unwrap()) else {
123 return (vec![], WindowRequests::default());
124 };
125 let screen_constraint = Constraint::new(
126 DimensionValue::Fixed(screen_size.width),
127 DimensionValue::Fixed(screen_size.height),
128 );
129
130 let measure_timer = Instant::now();
131 debug!("Start measuring the component tree...");
132
133 match measure_node(
136 root_node,
137 &screen_constraint,
138 &self.tree,
139 &self.metadatas,
140 compute_resource_manager,
141 gpu,
142 ) {
143 Ok(_root_computed_data) => {
144 debug!("Component tree measured in {:?}", measure_timer.elapsed());
145 }
146 Err(e) => {
147 panic!(
148 "Root node ({root_node:?}) measurement failed: {e:?}. Aborting draw command computation."
149 );
150 }
151 }
152
153 let compute_draw_timer = Instant::now();
154 debug!("Start computing draw commands...");
155 let commands = compute_draw_commands_parallel(
158 root_node,
159 &self.tree,
160 &self.metadatas,
161 screen_size.width.0,
162 screen_size.height.0,
163 );
164 debug!(
165 "Draw commands computed in {:?}, total commands: {}",
166 compute_draw_timer.elapsed(),
167 commands.len()
168 );
169
170 let state_handler_timer = Instant::now();
171 let mut window_requests = WindowRequests::default();
172 debug!("Start executing state handlers...");
173 for node_id in root_node
174 .reverse_traverse(&self.tree)
175 .filter_map(|edge| match edge {
176 indextree::NodeEdge::Start(id) => Some(id),
177 indextree::NodeEdge::End(_) => None,
178 })
179 {
180 let Some(state_handler) = self
181 .tree
182 .get(node_id)
183 .and_then(|n| n.get().state_handler_fn.as_ref())
184 else {
185 continue;
186 };
187
188 let current_cursor_position = cursor_position.map(|pos| {
190 let abs_pos = self
192 .metadatas
193 .get(&node_id)
194 .and_then(|m| m.abs_position)
195 .unwrap();
196 pos - abs_pos
198 });
199 let computed_data_option = self.metadatas.get(&node_id).and_then(|m| m.computed_data);
201
202 if let Some(node_computed_data) = computed_data_option {
203 let input = StateHandlerInput {
205 computed_data: node_computed_data,
206 cursor_position_rel: current_cursor_position,
207 cursor_position_abs: &mut cursor_position,
208 cursor_events: &mut cursor_events,
209 keyboard_events: &mut keyboard_events,
210 ime_events: &mut ime_events,
211 key_modifiers: modifiers,
212 requests: &mut window_requests,
213 clipboard,
214 };
215 state_handler(input);
216 if let Some(ref mut ime_request) = window_requests.ime_request
218 && ime_request.position.is_none()
219 {
220 ime_request.position = Some(
221 self.metadatas
222 .get(&node_id)
223 .and_then(|m| m.abs_position)
224 .unwrap(),
225 )
226 }
227 } else {
228 log::warn!(
229 "Computed data not found for node {node_id:?} during state handler execution."
230 );
231 }
232 }
233 debug!(
234 "State handlers executed in {:?}",
235 state_handler_timer.elapsed()
236 );
237 (commands, window_requests)
238 }
239}
240
241#[derive(Debug, Clone, Copy)]
243struct Rect {
244 x: i32,
245 y: i32,
246 width: i32,
247 height: i32,
248}
249
250impl Rect {
251 fn intersects(&self, other: &Rect) -> bool {
252 self.x < other.x + other.width
253 && self.x + self.width > other.x
254 && self.y < other.y + other.height
255 && self.y + self.height > other.y
256 }
257}
258
259fn compute_draw_commands_parallel(
268 node_id: indextree::NodeId,
269 tree: &ComponentNodeTree,
270 metadatas: &ComponentNodeMetaDatas,
271 screen_width: i32,
273 screen_height: i32,
274) -> Vec<(Command, PxSize, PxPosition)> {
275 compute_draw_commands_inner_parallel(
276 PxPosition::ZERO,
277 true,
278 node_id,
279 tree,
280 metadatas,
281 screen_width,
282 screen_height,
283 )
284}
285
286fn compute_draw_commands_inner_parallel(
287 start_pos: PxPosition,
288 is_root: bool,
289 node_id: indextree::NodeId,
290 tree: &ComponentNodeTree,
291 metadatas: &ComponentNodeMetaDatas,
292 screen_width: i32,
293 screen_height: i32,
294) -> Vec<(Command, PxSize, PxPosition)> {
295 let mut local_commands = Vec::new();
296
297 let mut metadata = metadatas.get_mut(&node_id).unwrap();
299 let rel_pos = match metadata.rel_position {
300 Some(pos) => pos,
301 None if is_root => PxPosition::ZERO,
302 _ => return local_commands, };
304 let self_pos = start_pos + rel_pos;
305 metadata.abs_position = Some(self_pos);
306
307 let size = metadata
308 .computed_data
309 .map(|d| PxSize {
310 width: d.width,
311 height: d.height,
312 })
313 .unwrap_or_default();
314
315 let screen_rect = Rect {
317 x: 0,
318 y: 0,
319 width: screen_width,
320 height: screen_height,
321 };
322 let node_rect = Rect {
323 x: self_pos.x.0,
324 y: self_pos.y.0,
325 width: size.width.0,
326 height: size.height.0,
327 };
328
329 if size.width.0 > 0 && size.height.0 > 0 && node_rect.intersects(&screen_rect) {
331 for cmd in metadata.commands.drain(..) {
332 local_commands.push((cmd, size, self_pos));
333 }
334 }
335
336 drop(metadata); let children: Vec<_> = node_id.children(tree).collect();
340 let child_results: Vec<Vec<_>> = children
341 .into_par_iter()
342 .map(|child| {
343 let parent_abs_pos = metadatas.get(&node_id).unwrap().abs_position.unwrap();
345 compute_draw_commands_inner_parallel(
346 parent_abs_pos, false,
348 child,
349 tree,
350 metadatas,
351 screen_width,
352 screen_height,
353 )
354 })
355 .collect();
356
357 for child_cmds in child_results {
358 local_commands.extend(child_cmds);
359 }
360
361 local_commands
362}