blitz_dom/events/
driver.rs

1use crate::{BaseDocument, DocumentMutator};
2use blitz_traits::events::{BlitzMouseButtonEvent, DomEvent, DomEventData, EventState, UiEvent};
3use std::collections::VecDeque;
4
5pub trait EventHandler {
6    fn handle_event(
7        &mut self,
8        chain: &[usize],
9        event: &mut DomEvent,
10        mutr: &mut DocumentMutator<'_>,
11        event_state: &mut EventState,
12    );
13}
14
15pub struct NoopEventHandler;
16impl EventHandler for NoopEventHandler {
17    fn handle_event(
18        &mut self,
19        _chain: &[usize],
20        _event: &mut DomEvent,
21        _mutr: &mut DocumentMutator<'_>,
22        _event_state: &mut EventState,
23    ) {
24        // Do nothing
25    }
26}
27
28pub struct EventDriver<'doc, Handler: EventHandler> {
29    mutr: DocumentMutator<'doc>,
30    handler: Handler,
31}
32
33impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> {
34    fn doc_mut(&mut self) -> &mut BaseDocument {
35        self.mutr.doc
36    }
37
38    fn doc(&self) -> &BaseDocument {
39        &*self.mutr.doc
40    }
41
42    pub fn new(mutr: DocumentMutator<'doc>, handler: Handler) -> Self {
43        EventDriver { mutr, handler }
44    }
45
46    pub fn handle_ui_event(&mut self, event: UiEvent) {
47        let viewport_scroll = self.doc().viewport_scroll();
48        let zoom = self.doc().viewport.zoom();
49
50        let mut hover_node_id = self.doc().hover_node_id;
51        let focussed_node_id = self.doc().focus_node_id;
52
53        // Update document input state (hover, focus, active, etc)
54        match &event {
55            UiEvent::MouseMove(event) => {
56                let dom_x = event.x + viewport_scroll.x as f32 / zoom;
57                let dom_y = event.y + viewport_scroll.y as f32 / zoom;
58                self.doc_mut().set_hover_to(dom_x, dom_y);
59                hover_node_id = self.doc().hover_node_id;
60            }
61            UiEvent::MouseDown(_) => {
62                self.doc_mut().active_node();
63                self.doc_mut().set_mousedown_node_id(hover_node_id);
64            }
65            UiEvent::MouseUp(_) => {
66                self.doc_mut().unactive_node();
67            }
68            _ => {}
69        };
70
71        let target = match event {
72            UiEvent::MouseMove(_) => hover_node_id,
73            UiEvent::MouseUp(_) => hover_node_id,
74            UiEvent::MouseDown(_) => hover_node_id,
75            UiEvent::KeyUp(_) => focussed_node_id,
76            UiEvent::KeyDown(_) => focussed_node_id,
77            UiEvent::Ime(_) => focussed_node_id,
78        };
79
80        let data = match event {
81            UiEvent::MouseMove(data) => DomEventData::MouseMove(BlitzMouseButtonEvent {
82                x: data.x + viewport_scroll.x as f32 / zoom,
83                y: data.y + viewport_scroll.y as f32 / zoom,
84                ..data
85            }),
86            UiEvent::MouseUp(data) => DomEventData::MouseUp(BlitzMouseButtonEvent {
87                x: data.x + viewport_scroll.x as f32 / zoom,
88                y: data.y + viewport_scroll.y as f32 / zoom,
89                ..data
90            }),
91            UiEvent::MouseDown(data) => DomEventData::MouseDown(BlitzMouseButtonEvent {
92                x: data.x + viewport_scroll.x as f32 / zoom,
93                y: data.y + viewport_scroll.y as f32 / zoom,
94                ..data
95            }),
96            UiEvent::KeyUp(data) => DomEventData::KeyUp(data),
97            UiEvent::KeyDown(data) => DomEventData::KeyDown(data),
98            UiEvent::Ime(data) => DomEventData::Ime(data),
99        };
100
101        let target = target.unwrap_or_else(|| self.doc().root_element().id);
102        let dom_event = DomEvent::new(target, data);
103
104        self.handle_dom_event(dom_event);
105    }
106
107    pub fn handle_dom_event(&mut self, event: DomEvent) {
108        let mut queue = VecDeque::with_capacity(4);
109        queue.push_back(event);
110
111        while let Some(mut event) = queue.pop_front() {
112            let chain = if event.bubbles {
113                self.doc().node_chain(event.target)
114            } else {
115                vec![event.target]
116            };
117
118            let mut event_state = EventState::default();
119            self.handler
120                .handle_event(&chain, &mut event, &mut self.mutr, &mut event_state);
121
122            if !event_state.is_cancelled() {
123                self.doc_mut()
124                    .handle_dom_event(&mut event, |new_evt| queue.push_back(new_evt));
125            }
126        }
127    }
128}