1use std::{any::Any, time::Instant};
2
3use glam::Vec2;
4use ori_graphics::{Frame, Rect, Renderer};
5use uuid::Uuid;
6
7use crate::{
8 AnyView, BoxConstraints, Context, DrawContext, Event, EventContext, EventSink, ImageCache,
9 LayoutContext, Lock, Lockable, PointerEvent, RequestRedrawEvent, Style, StyleSelector,
10 StyleSelectors, StyleStates, StyleTransition, Stylesheet, TransitionStates, View,
11};
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub struct NodeId {
15 uuid: Uuid,
16}
17
18impl NodeId {
19 pub fn new() -> Self {
20 Self {
21 uuid: Uuid::new_v4(),
22 }
23 }
24}
25
26impl Default for NodeId {
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32#[derive(Clone, Debug)]
33pub struct NodeState {
34 pub id: NodeId,
35 pub local_rect: Rect,
36 pub global_rect: Rect,
37 pub active: bool,
38 pub focused: bool,
39 pub hovered: bool,
40 pub last_draw: Instant,
41 pub style: Style,
42 pub transitions: TransitionStates,
43}
44
45impl Default for NodeState {
46 fn default() -> Self {
47 Self {
48 id: NodeId::new(),
49 local_rect: Rect::ZERO,
50 global_rect: Rect::ZERO,
51 active: false,
52 focused: false,
53 hovered: false,
54 last_draw: Instant::now(),
55 style: Style::default(),
56 transitions: TransitionStates::new(),
57 }
58 }
59}
60
61impl NodeState {
62 pub fn new(style: Style) -> Self {
63 Self {
64 style,
65 ..Default::default()
66 }
67 }
68
69 pub fn propagate_parent(&mut self, parent: &NodeState) {
70 self.global_rect = self.local_rect.translate(parent.global_rect.min);
71 }
72
73 pub fn propagate_child(&mut self, _child: &NodeState) {}
74
75 pub fn style_states(&self) -> StyleStates {
76 let mut states = StyleStates::new();
77
78 if self.active {
79 states.push("active");
80 }
81
82 if self.focused {
83 states.push("focus");
84 }
85
86 if self.hovered {
87 states.push("hover");
88 }
89
90 states
91 }
92
93 pub fn selector(&self) -> StyleSelector {
94 StyleSelector {
95 element: self.style.element.map(Into::into),
96 classes: self.style.classes.clone(),
97 states: self.style_states(),
98 }
99 }
100
101 pub fn delta(&self) -> f32 {
102 self.last_draw.elapsed().as_secs_f32()
103 }
104
105 pub fn transition<T: 'static>(
106 &mut self,
107 name: &str,
108 mut value: T,
109 transition: Option<StyleTransition>,
110 ) -> T {
111 (self.transitions).transition_any(name, &mut value, transition);
112 value
113 }
114
115 pub fn update_transitions(&mut self) -> bool {
116 self.transitions.update(self.delta())
117 }
118
119 fn draw(&mut self) {
120 self.last_draw = Instant::now();
121 }
122}
123
124impl<T: View> From<T> for Node {
125 fn from(view: T) -> Self {
126 Self::new(view)
127 }
128}
129
130pub struct Node {
132 #[cfg(feature = "multithread")]
133 view_state: Lock<Box<dyn Any + Send + Sync>>,
134 #[cfg(not(feature = "multithread"))]
135 view_state: Lock<Box<dyn Any>>,
136 node_state: Lock<NodeState>,
137 view: Box<dyn AnyView>,
138}
139
140impl Node {
141 pub fn new(view: impl View) -> Self {
142 let view_state = Box::new(View::build(&view));
143 let node_state = NodeState::new(View::style(&view));
144
145 Self {
146 view_state: Lock::new(view_state),
147 node_state: Lock::new(node_state),
148 view: Box::new(view),
149 }
150 }
151
152 pub fn set_offset(&self, offset: Vec2) {
153 let mut node_state = self.node_state.lock_mut();
154
155 let size = node_state.local_rect.size();
156 node_state.local_rect = Rect::min_size(offset, size);
157 }
158
159 pub fn states(&self) -> StyleStates {
160 self.node_state.lock_mut().style_states()
161 }
162
163 pub fn local_rect(&self) -> Rect {
164 self.node_state.lock_mut().local_rect
165 }
166
167 pub fn global_rect(&self) -> Rect {
168 self.node_state.lock_mut().global_rect
169 }
170
171 pub fn size(&self) -> Vec2 {
172 self.node_state.lock_mut().local_rect.size()
173 }
174}
175
176impl Node {
177 fn handle_pointer_event(&self, node_state: &mut NodeState, event: &PointerEvent) -> bool {
178 let hovered = node_state.global_rect.contains(event.position) && !event.left;
179 if hovered != node_state.hovered {
180 node_state.hovered = hovered;
181 true
182 } else {
183 false
184 }
185 }
186
187 pub fn event(&self, cx: &mut EventContext, event: &Event) {
188 let mut node_state = self.node_state.lock_mut();
189 node_state.style = self.view.style();
190 node_state.propagate_parent(cx.state);
191
192 if let Some(event) = event.get::<PointerEvent>() {
193 if self.handle_pointer_event(&mut node_state, event) {
194 cx.request_redraw();
195 }
196 }
197
198 {
199 let selector = node_state.selector();
200 let mut cx = EventContext {
201 style: cx.style,
202 state: &mut node_state,
203 renderer: cx.renderer,
204 selectors: &cx.selectors.clone().with(selector),
205 event_sink: cx.event_sink,
206 image_cache: cx.image_cache,
207 };
208
209 let mut view_state = self.view_state.lock_mut();
210 self.view.event(&mut **view_state, &mut cx, event);
211 }
212
213 cx.state.propagate_child(&node_state);
214 }
215
216 pub fn layout(&self, cx: &mut LayoutContext, bc: BoxConstraints) -> Vec2 {
217 let mut node_state = self.node_state.lock_mut();
218 node_state.style = self.view.style();
219
220 let size = {
221 let selector = node_state.selector();
222 let mut cx = LayoutContext {
223 style: cx.style,
224 state: &mut node_state,
225 renderer: cx.renderer,
226 selectors: &cx.selectors.clone().with(selector),
227 event_sink: cx.event_sink,
228 image_cache: cx.image_cache,
229 };
230
231 let mut view_state = self.view_state.lock_mut();
232 self.view.layout(&mut **view_state, &mut cx, bc)
233 };
234
235 node_state.local_rect = Rect::min_size(node_state.local_rect.min, size);
236 node_state.global_rect = Rect::min_size(node_state.global_rect.min, size);
237
238 cx.state.propagate_child(&node_state);
239
240 size
241 }
242
243 pub fn draw(&self, cx: &mut DrawContext) {
244 let mut node_state = self.node_state.lock_mut();
245 node_state.style = self.view.style();
246 node_state.propagate_parent(cx.state);
247
248 {
249 let selector = node_state.selector();
250 let mut cx = DrawContext {
251 style: cx.style,
252 state: &mut node_state,
253 frame: cx.frame,
254 renderer: cx.renderer,
255 selectors: &cx.selectors.clone().with(selector),
256 event_sink: cx.event_sink,
257 image_cache: cx.image_cache,
258 };
259
260 let mut view_state = self.view_state.lock_mut();
261 self.view.draw(&mut **view_state, &mut cx);
262
263 if cx.state.update_transitions() {
264 cx.request_redraw();
265 }
266
267 cx.state.draw();
268 }
269
270 cx.state.propagate_child(&node_state);
271 }
272}
273
274impl Node {
275 pub fn event_root(
276 &self,
277 style: &Stylesheet,
278 renderer: &dyn Renderer,
279 event_sink: &EventSink,
280 event: &Event,
281 image_cache: &mut ImageCache,
282 ) {
283 let mut node_state = self.node_state.lock_mut();
284 node_state.style = self.view.style();
285
286 if let Some(event) = event.get::<PointerEvent>() {
287 if self.handle_pointer_event(&mut node_state, event) {
288 event_sink.send(RequestRedrawEvent);
289 }
290 }
291
292 let selector = node_state.selector();
293 let mut cx = EventContext {
294 style,
295 state: &mut node_state,
296 renderer,
297 selectors: &StyleSelectors::new().with(selector),
298 event_sink,
299 image_cache,
300 };
301
302 let mut view_state = self.view_state.lock_mut();
303 self.view.event(&mut **view_state, &mut cx, event);
304 }
305
306 pub fn layout_root(
307 &self,
308 style: &Stylesheet,
309 renderer: &dyn Renderer,
310 window_size: Vec2,
311 event_sink: &EventSink,
312 image_cache: &mut ImageCache,
313 ) -> Vec2 {
314 let mut node_state = self.node_state.lock_mut();
315 node_state.style = self.view.style();
316
317 let selector = node_state.selector();
318 let mut cx = LayoutContext {
319 style,
320 state: &mut node_state,
321 renderer,
322 selectors: &StyleSelectors::new().with(selector),
323 event_sink,
324 image_cache,
325 };
326
327 let bc = BoxConstraints::new(Vec2::ZERO, window_size);
328 let mut view_state = self.view_state.lock_mut();
329 let size = self.view.layout(&mut **view_state, &mut cx, bc);
330
331 node_state.local_rect = Rect::min_size(node_state.local_rect.min, size);
332 node_state.global_rect = Rect::min_size(node_state.global_rect.min, size);
333
334 size
335 }
336
337 pub fn draw_root(
338 &self,
339 style: &Stylesheet,
340 frame: &mut Frame,
341 renderer: &dyn Renderer,
342 event_sink: &EventSink,
343 image_cache: &mut ImageCache,
344 ) {
345 let mut node_state = self.node_state.lock_mut();
346 node_state.style = self.view.style();
347
348 let selector = node_state.selector();
349 let mut cx = DrawContext {
350 style,
351 state: &mut node_state,
352 frame,
353 renderer,
354 selectors: &StyleSelectors::new().with(selector),
355 event_sink,
356 image_cache,
357 };
358
359 let mut view_state = self.view_state.lock_mut();
360 self.view.draw(&mut **view_state, &mut cx);
361
362 cx.state.draw();
363 }
364}