1use crate::Document;
2use bliss_traits::events::{
3 BlissPointerEvent, BlissPointerId, DomEvent, DomEventData, EventPhase, EventSink, EventState,
4 UiEvent,
5};
6use std::collections::VecDeque;
7
8pub trait EventHandler {
9 fn handle_event(
10 &mut self,
11 chain: &[usize],
12 event: &mut DomEvent,
13 doc: &mut dyn Document,
14 event_state: &mut EventState,
15 );
16}
17
18pub struct NoopEventHandler;
19impl EventHandler for NoopEventHandler {
20 fn handle_event(
21 &mut self,
22 _chain: &[usize],
23 _event: &mut DomEvent,
24 _doc: &mut dyn Document,
25 _event_state: &mut EventState,
26 ) {
27 }
29}
30
31pub struct EventDriver<'doc, Handler: EventHandler> {
32 doc: &'doc mut dyn Document,
33 handler: Handler,
34 queue: VecDeque<DomEvent>,
35 event_sink: Option<&'doc dyn EventSink>,
36}
37
38impl<'doc, Handler: EventHandler> EventDriver<'doc, Handler> {
39 pub fn new(doc: &'doc mut dyn Document, handler: Handler) -> Self {
40 EventDriver {
41 doc,
42 handler,
43 queue: VecDeque::with_capacity(4),
44 event_sink: None,
45 }
46 }
47
48 pub fn with_event_sink(
49 doc: &'doc mut dyn Document,
50 handler: Handler,
51 event_sink: &'doc dyn EventSink,
52 ) -> Self {
53 EventDriver {
54 doc,
55 handler,
56 queue: VecDeque::with_capacity(4),
57 event_sink: Some(event_sink),
58 }
59 }
60
61 pub fn handle_pointer_move(&mut self, event: &BlissPointerEvent) -> Option<usize> {
62 let mut doc = self.doc.inner_mut();
63
64 let prev_hover_node_id = doc.hover_node_id;
65 let changed = doc.set_hover_to(event.page_x(), event.page_y());
66 let hover_node_id = doc.hover_node_id;
67
68 drop(doc);
69
70 if !changed {
71 return prev_hover_node_id;
72 }
73
74 let doc = self.doc.inner();
75 let mut old_chain = prev_hover_node_id
76 .map(|id| doc.node_chain(id))
77 .unwrap_or_default();
78 let mut new_chain = hover_node_id
79 .map(|id| doc.node_chain(id))
80 .unwrap_or_default();
81 old_chain.reverse();
82 new_chain.reverse();
83
84 let old_len = old_chain.len();
86 let new_len = new_chain.len();
87
88 let first_difference_index = old_chain
89 .iter()
90 .zip(&new_chain)
91 .position(|(old, new)| old != new)
92 .unwrap_or_else(|| old_len.min(new_len));
93
94 drop(doc);
95
96 let is_mouse = event.is_mouse();
97
98 if let Some(target) = prev_hover_node_id {
99 self.handle_dom_event(DomEvent::new(
100 target,
101 DomEventData::PointerOut(event.clone()),
102 ));
103 if is_mouse {
104 self.handle_dom_event(DomEvent::new(target, DomEventData::MouseOut(event.clone())));
105 }
106
107 for node_id in old_chain
109 .get(first_difference_index..)
110 .unwrap_or(&[])
111 .iter()
112 {
113 self.handle_dom_event(DomEvent::new(
114 *node_id,
115 DomEventData::PointerLeave(event.clone()),
116 ));
117 if is_mouse {
118 self.handle_dom_event(DomEvent::new(
119 *node_id,
120 DomEventData::MouseLeave(event.clone()),
121 ));
122 }
123 }
124 }
125
126 if let Some(target) = hover_node_id {
127 self.handle_dom_event(DomEvent::new(
128 target,
129 DomEventData::PointerOver(event.clone()),
130 ));
131
132 if is_mouse {
133 self.handle_dom_event(DomEvent::new(
134 target,
135 DomEventData::MouseOver(event.clone()),
136 ));
137 }
138
139 for node_id in new_chain
141 .get(first_difference_index..)
142 .unwrap_or(&[])
143 .iter()
144 {
145 self.handle_dom_event(DomEvent::new(
146 *node_id,
147 DomEventData::PointerEnter(event.clone()),
148 ));
149
150 if is_mouse {
151 self.handle_dom_event(DomEvent::new(
152 *node_id,
153 DomEventData::MouseEnter(event.clone()),
154 ));
155 }
156 }
157 }
158
159 hover_node_id
160 }
161
162 pub fn handle_ui_event(&mut self, event: UiEvent) {
163 let doc = self.doc.inner();
164
165 let mut should_clear_hover = false;
166 let mut hover_node_id = doc.hover_node_id;
167 let focussed_node_id = doc.focus_node_id;
168 drop(doc);
169
170 match &event {
172 UiEvent::PointerMove(event) => {
173 hover_node_id = self.handle_pointer_move(event);
174 }
175 UiEvent::PointerDown(event) => {
176 hover_node_id = self.handle_pointer_move(event);
177 let mut doc = self.doc.inner_mut();
178 doc.active_node();
179 doc.set_mousedown_node_id(hover_node_id);
180 }
181 UiEvent::PointerUp(event) => {
182 hover_node_id = self.handle_pointer_move(event);
183 let mut doc = self.doc.inner_mut();
184 doc.unactive_node();
185
186 if event.is_primary && matches!(event.id, BlissPointerId::Finger(_)) {
187 should_clear_hover = true;
188 }
189 }
190 _ => {}
191 };
192
193 let target = match event {
194 UiEvent::PointerMove(_) => hover_node_id,
195 UiEvent::PointerUp(_) => hover_node_id,
196 UiEvent::PointerDown(_) => hover_node_id,
197 UiEvent::Wheel(_) => hover_node_id,
198 UiEvent::KeyUp(_) => focussed_node_id,
199 UiEvent::KeyDown(_) => focussed_node_id,
200 UiEvent::Ime(_) => focussed_node_id,
201 };
202 let target =
205 target.unwrap_or_else(|| self.doc.inner().root_element().map(|r| r.id).unwrap_or(0));
206
207 match event {
208 UiEvent::PointerMove(data) => {
209 self.handle_pointer_event(
210 target,
211 data,
212 DomEventData::PointerMove,
213 DomEventData::MouseMove,
214 );
215 }
216 UiEvent::PointerUp(data) => {
217 self.handle_pointer_event(
218 target,
219 data,
220 DomEventData::PointerUp,
221 DomEventData::MouseUp,
222 );
223 }
224 UiEvent::PointerDown(data) => {
225 self.handle_pointer_event(
226 target,
227 data,
228 DomEventData::PointerDown,
229 DomEventData::MouseDown,
230 );
231 }
232 UiEvent::Wheel(data) => {
233 self.handle_dom_event(DomEvent::new(target, DomEventData::Wheel(data)))
234 }
235 UiEvent::KeyUp(data) => {
236 self.handle_dom_event(DomEvent::new(target, DomEventData::KeyUp(data)))
237 }
238 UiEvent::KeyDown(data) => {
239 self.handle_dom_event(DomEvent::new(target, DomEventData::KeyDown(data)))
240 }
241 UiEvent::Ime(data) => {
242 self.handle_dom_event(DomEvent::new(target, DomEventData::Ime(data)))
243 }
244 };
245
246 if should_clear_hover {
248 self.doc.inner_mut().clear_hover();
249 }
250 }
251
252 pub fn handle_dom_event(&mut self, event: DomEvent) {
253 self.queue.push_back(event);
254 self.process_queue();
255 }
256
257 fn handle_pointer_event(
258 &mut self,
259 target: usize,
260 data: BlissPointerEvent,
261 make_ptr_data: impl FnOnce(BlissPointerEvent) -> DomEventData,
262 make_mouse_data: impl FnOnce(BlissPointerEvent) -> DomEventData,
263 ) {
264 let mut ptr_event = DomEvent::new(target, make_ptr_data(data.clone()));
265 let mut event_state = EventState::default();
266 event_state = self.run_handler_event(&mut ptr_event, event_state);
267 if !event_state.is_cancelled() && data.is_mouse() {
268 let mut mouse_event = DomEvent::new(target, make_mouse_data(data));
269 event_state = self.run_handler_event(&mut mouse_event, event_state);
270 }
271 if !event_state.is_cancelled() {
272 self.run_default_action(&mut ptr_event);
273 }
274 self.process_queue();
275 }
276
277 fn process_queue(&mut self) {
278 while let Some(mut event) = self.queue.pop_front() {
279 let event_state = self.run_handler_event(&mut event, EventState::default());
280 if !event_state.is_cancelled() {
281 self.run_default_action(&mut event);
282 }
283 }
284 }
285
286 fn run_handler_event(
287 &mut self,
288 event: &mut DomEvent,
289 initial_event_state: EventState,
290 ) -> EventState {
291 let chain = if event.bubbles {
292 let doc = self.doc.inner();
293 doc.node_chain(event.target)
294 } else {
295 vec![event.target]
296 };
297
298 let mut event_state = initial_event_state;
299
300 for node_id in &chain {
301 self.handler.handle_event(
302 std::slice::from_ref(node_id),
303 event,
304 self.doc,
305 &mut event_state,
306 );
307
308 if event_state.propagation_is_stopped() {
309 break;
310 }
311 }
312
313 if let Some(sink) = &self.event_sink {
314 let doc_id = self.doc.id();
315 sink.on_dom_event(doc_id, event, EventPhase::Target, event.target);
316 }
317
318 event_state
319 }
320
321 fn run_default_action(&mut self, event: &mut DomEvent) {
322 let mut doc = self.doc.inner_mut();
323 doc.handle_dom_event(event, |new_evt| self.queue.push_back(new_evt));
324 }
325}