ori_core/
node.rs

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
130/// A node in the [`View`](crate::View) tree.
131pub 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}