1#![allow(dead_code)]
8
9use alloc::{collections::BTreeMap, vec::Vec};
10
11pub type NodeId = usize;
17
18pub type FixedPoint = i32;
20
21pub const FP_SHIFT: i32 = 6;
23
24#[inline]
26pub const fn fp_from_int(v: i32) -> FixedPoint {
27 v << FP_SHIFT
28}
29
30#[inline]
32pub const fn fp_to_int(v: FixedPoint) -> i32 {
33 v >> FP_SHIFT
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
42pub enum EventType {
43 Click,
44 MouseDown,
45 MouseUp,
46 MouseMove,
47 MouseOver,
48 MouseOut,
49 KeyDown,
50 KeyUp,
51 KeyPress,
52 Focus,
53 Blur,
54 Submit,
55 Input,
56 Change,
57 Scroll,
58 Load,
59 Unload,
60 Resize,
61}
62
63impl EventType {
64 pub fn bubbles_default(self) -> bool {
66 match self {
67 Self::Click
68 | Self::MouseDown
69 | Self::MouseUp
70 | Self::MouseMove
71 | Self::MouseOver
72 | Self::MouseOut
73 | Self::KeyDown
74 | Self::KeyUp
75 | Self::KeyPress
76 | Self::Input
77 | Self::Change
78 | Self::Scroll
79 | Self::Submit => true,
80 Self::Focus | Self::Blur | Self::Load | Self::Unload | Self::Resize => false,
81 }
82 }
83
84 pub fn cancelable_default(self) -> bool {
86 matches!(
87 self,
88 Self::Click
89 | Self::MouseDown
90 | Self::MouseUp
91 | Self::KeyDown
92 | Self::KeyPress
93 | Self::Submit
94 )
95 }
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
100pub enum EventPhase {
101 #[default]
103 None,
104 Capture,
106 Target,
108 Bubble,
110}
111
112#[derive(Debug, Clone)]
118pub struct Event {
119 pub event_type: EventType,
121 pub target: NodeId,
123 pub current_target: NodeId,
125 pub phase: EventPhase,
127 pub bubbles: bool,
129 pub cancelable: bool,
131 pub default_prevented: bool,
133 pub propagation_stopped: bool,
135 pub immediate_propagation_stopped: bool,
137 pub mouse_x: i32,
139 pub mouse_y: i32,
141 pub button: u8,
143 pub key_code: u32,
145 pub char_code: u32,
147 pub modifiers: u8,
149}
150
151impl Event {
152 pub fn new(event_type: EventType, target: NodeId) -> Self {
154 Self {
155 event_type,
156 target,
157 current_target: target,
158 phase: EventPhase::None,
159 bubbles: event_type.bubbles_default(),
160 cancelable: event_type.cancelable_default(),
161 default_prevented: false,
162 propagation_stopped: false,
163 immediate_propagation_stopped: false,
164 mouse_x: 0,
165 mouse_y: 0,
166 button: 0,
167 key_code: 0,
168 char_code: 0,
169 modifiers: 0,
170 }
171 }
172
173 pub fn mouse(event_type: EventType, target: NodeId, x: i32, y: i32, button: u8) -> Self {
175 let mut ev = Self::new(event_type, target);
176 ev.mouse_x = x;
177 ev.mouse_y = y;
178 ev.button = button;
179 ev
180 }
181
182 pub fn keyboard(event_type: EventType, target: NodeId, key_code: u32, char_code: u32) -> Self {
184 let mut ev = Self::new(event_type, target);
185 ev.key_code = key_code;
186 ev.char_code = char_code;
187 ev
188 }
189
190 pub fn prevent_default(&mut self) {
192 if self.cancelable {
193 self.default_prevented = true;
194 }
195 }
196
197 pub fn stop_propagation(&mut self) {
199 self.propagation_stopped = true;
200 }
201
202 pub fn stop_immediate_propagation(&mut self) {
204 self.propagation_stopped = true;
205 self.immediate_propagation_stopped = true;
206 }
207
208 pub fn shift_key(&self) -> bool {
210 self.modifiers & 1 != 0
211 }
212
213 pub fn ctrl_key(&self) -> bool {
215 self.modifiers & 2 != 0
216 }
217
218 pub fn alt_key(&self) -> bool {
220 self.modifiers & 4 != 0
221 }
222
223 pub fn meta_key(&self) -> bool {
225 self.modifiers & 8 != 0
226 }
227}
228
229#[derive(Debug, Clone, PartialEq, Eq)]
235pub struct EventListener {
236 pub event_type: EventType,
238 pub callback_id: usize,
240 pub use_capture: bool,
242}
243
244impl EventListener {
245 pub fn new(event_type: EventType, callback_id: usize, use_capture: bool) -> Self {
246 Self {
247 event_type,
248 callback_id,
249 use_capture,
250 }
251 }
252}
253
254#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
260pub struct HitRect {
261 pub x: i32,
262 pub y: i32,
263 pub width: i32,
264 pub height: i32,
265 pub node_id: NodeId,
266}
267
268impl HitRect {
269 pub fn new(x: i32, y: i32, width: i32, height: i32, node_id: NodeId) -> Self {
270 Self {
271 x,
272 y,
273 width,
274 height,
275 node_id,
276 }
277 }
278
279 pub fn contains(&self, px: i32, py: i32) -> bool {
281 px >= self.x && px < self.x + self.width && py >= self.y && py < self.y + self.height
282 }
283}
284
285#[derive(Debug, Clone, Default)]
291pub struct NodeTree {
292 parents: BTreeMap<NodeId, NodeId>,
294}
295
296impl NodeTree {
297 pub fn new() -> Self {
298 Self {
299 parents: BTreeMap::new(),
300 }
301 }
302
303 pub fn set_parent(&mut self, child: NodeId, parent: NodeId) {
305 self.parents.insert(child, parent);
306 }
307
308 pub fn parent(&self, node: NodeId) -> Option<NodeId> {
310 self.parents.get(&node).copied()
311 }
312
313 pub fn ancestor_path(&self, node: NodeId) -> Vec<NodeId> {
315 let mut path = Vec::new();
316 let mut current = node;
317 path.push(current);
318 while let Some(parent) = self.parents.get(¤t) {
319 path.push(*parent);
320 current = *parent;
321 }
322 path.reverse();
323 path
324 }
325
326 pub fn remove(&mut self, node: NodeId) {
328 self.parents.remove(&node);
329 }
330}
331
332pub struct EventDispatcher {
338 listeners: BTreeMap<NodeId, Vec<EventListener>>,
340 node_tree: NodeTree,
342 hit_boxes: Vec<HitRect>,
344 invoked: Vec<(usize, EventType)>,
346}
347
348impl Default for EventDispatcher {
349 fn default() -> Self {
350 Self::new()
351 }
352}
353
354impl EventDispatcher {
355 pub fn new() -> Self {
356 Self {
357 listeners: BTreeMap::new(),
358 node_tree: NodeTree::new(),
359 hit_boxes: Vec::new(),
360 invoked: Vec::new(),
361 }
362 }
363
364 pub fn node_tree(&self) -> &NodeTree {
366 &self.node_tree
367 }
368
369 pub fn node_tree_mut(&mut self) -> &mut NodeTree {
371 &mut self.node_tree
372 }
373
374 pub fn add_event_listener(
378 &mut self,
379 node: NodeId,
380 event_type: EventType,
381 callback_id: usize,
382 use_capture: bool,
383 ) {
384 let listener = EventListener::new(event_type, callback_id, use_capture);
385 self.listeners.entry(node).or_default().push(listener);
386 }
387
388 pub fn remove_event_listener(
390 &mut self,
391 node: NodeId,
392 event_type: EventType,
393 callback_id: usize,
394 use_capture: bool,
395 ) -> bool {
396 if let Some(list) = self.listeners.get_mut(&node) {
397 let before = list.len();
398 list.retain(|l| {
399 !(l.event_type == event_type
400 && l.callback_id == callback_id
401 && l.use_capture == use_capture)
402 });
403 list.len() < before
404 } else {
405 false
406 }
407 }
408
409 pub fn listeners_for(&self, node: NodeId) -> &[EventListener] {
411 self.listeners
412 .get(&node)
413 .map(|v| v.as_slice())
414 .unwrap_or(&[])
415 }
416
417 pub fn clear_listeners(&mut self, node: NodeId) {
419 self.listeners.remove(&node);
420 }
421
422 pub fn set_hit_boxes(&mut self, boxes: Vec<HitRect>) {
426 self.hit_boxes = boxes;
427 }
428
429 pub fn add_hit_box(&mut self, rect: HitRect) {
431 self.hit_boxes.push(rect);
432 }
433
434 pub fn clear_hit_boxes(&mut self) {
436 self.hit_boxes.clear();
437 }
438
439 pub fn hit_test(&self, x: i32, y: i32) -> Option<NodeId> {
442 for rect in self.hit_boxes.iter().rev() {
444 if rect.contains(x, y) {
445 return Some(rect.node_id);
446 }
447 }
448 None
449 }
450
451 pub fn take_invoked(&mut self) -> Vec<(usize, EventType)> {
456 core::mem::take(&mut self.invoked)
457 }
458
459 pub fn dispatch(&mut self, event: &mut Event) -> bool {
462 let path = self.node_tree.ancestor_path(event.target);
464 if path.is_empty() {
465 return event.default_prevented;
466 }
467
468 let target_idx = path.len() - 1;
469
470 event.phase = EventPhase::Capture;
472 for &node in &path[..target_idx] {
473 if event.propagation_stopped {
474 break;
475 }
476 event.current_target = node;
477 self.invoke_listeners(node, event, true);
478 }
479
480 if !event.propagation_stopped {
482 event.phase = EventPhase::Target;
483 event.current_target = event.target;
484 self.invoke_listeners(event.target, event, true);
486 if !event.immediate_propagation_stopped {
487 self.invoke_listeners(event.target, event, false);
488 }
489 }
490
491 if event.bubbles && !event.propagation_stopped {
493 event.phase = EventPhase::Bubble;
494 for &node in path[..target_idx].iter().rev() {
495 if event.propagation_stopped {
496 break;
497 }
498 event.current_target = node;
499 self.invoke_listeners(node, event, false);
500 }
501 }
502
503 event.default_prevented
504 }
505
506 fn invoke_listeners(&mut self, node: NodeId, event: &Event, capture: bool) {
510 let listeners: Vec<EventListener> = self.listeners.get(&node).cloned().unwrap_or_default();
512
513 for listener in &listeners {
514 if event.immediate_propagation_stopped {
515 break;
516 }
517 if listener.event_type != event.event_type {
518 continue;
519 }
520 if event.phase != EventPhase::Target && listener.use_capture != capture {
524 continue;
525 }
526 if event.phase == EventPhase::Target && listener.use_capture != capture {
527 continue;
528 }
529 self.invoked.push((listener.callback_id, event.event_type));
530 }
531 }
532
533 pub fn dispatch_click(&mut self, x: i32, y: i32, button: u8) -> Option<(NodeId, bool)> {
537 let target = self.hit_test(x, y)?;
538 let mut event = Event::mouse(EventType::Click, target, x, y, button);
539 let prevented = self.dispatch(&mut event);
540 Some((target, prevented))
541 }
542
543 pub fn dispatch_mouse_move(&mut self, x: i32, y: i32) -> Option<(NodeId, bool)> {
545 let target = self.hit_test(x, y)?;
546 let mut event = Event::mouse(EventType::MouseMove, target, x, y, 0);
547 let prevented = self.dispatch(&mut event);
548 Some((target, prevented))
549 }
550
551 pub fn dispatch_key(
553 &mut self,
554 target: NodeId,
555 event_type: EventType,
556 key_code: u32,
557 char_code: u32,
558 modifiers: u8,
559 ) -> bool {
560 let mut event = Event::keyboard(event_type, target, key_code, char_code);
561 event.modifiers = modifiers;
562 self.dispatch(&mut event)
563 }
564}
565
566#[cfg(test)]
571mod tests {
572 #[allow(unused_imports)]
573 use alloc::vec;
574
575 use super::*;
576
577 fn setup_tree() -> EventDispatcher {
578 let mut d = EventDispatcher::new();
580 d.node_tree_mut().set_parent(1, 0);
581 d.node_tree_mut().set_parent(2, 1);
582 d
583 }
584
585 #[test]
586 fn test_event_type_bubbles() {
587 assert!(EventType::Click.bubbles_default());
588 assert!(!EventType::Focus.bubbles_default());
589 assert!(!EventType::Load.bubbles_default());
590 assert!(EventType::KeyDown.bubbles_default());
591 }
592
593 #[test]
594 fn test_event_type_cancelable() {
595 assert!(EventType::Click.cancelable_default());
596 assert!(!EventType::MouseMove.cancelable_default());
597 assert!(EventType::Submit.cancelable_default());
598 }
599
600 #[test]
601 fn test_event_creation() {
602 let ev = Event::new(EventType::Click, 5);
603 assert_eq!(ev.event_type, EventType::Click);
604 assert_eq!(ev.target, 5);
605 assert!(ev.bubbles);
606 assert!(ev.cancelable);
607 assert!(!ev.default_prevented);
608 }
609
610 #[test]
611 fn test_event_mouse() {
612 let ev = Event::mouse(EventType::MouseDown, 3, 100, 200, 1);
613 assert_eq!(ev.mouse_x, 100);
614 assert_eq!(ev.mouse_y, 200);
615 assert_eq!(ev.button, 1);
616 assert_eq!(ev.target, 3);
617 }
618
619 #[test]
620 fn test_event_keyboard() {
621 let ev = Event::keyboard(EventType::KeyDown, 2, 13, 0);
622 assert_eq!(ev.key_code, 13);
623 assert_eq!(ev.char_code, 0);
624 }
625
626 #[test]
627 fn test_prevent_default() {
628 let mut ev = Event::new(EventType::Click, 0);
629 assert!(!ev.default_prevented);
630 ev.prevent_default();
631 assert!(ev.default_prevented);
632 }
633
634 #[test]
635 fn test_prevent_default_non_cancelable() {
636 let mut ev = Event::new(EventType::MouseMove, 0);
637 assert!(!ev.cancelable);
638 ev.prevent_default();
639 assert!(!ev.default_prevented);
640 }
641
642 #[test]
643 fn test_stop_propagation() {
644 let mut ev = Event::new(EventType::Click, 0);
645 ev.stop_propagation();
646 assert!(ev.propagation_stopped);
647 assert!(!ev.immediate_propagation_stopped);
648 }
649
650 #[test]
651 fn test_stop_immediate_propagation() {
652 let mut ev = Event::new(EventType::Click, 0);
653 ev.stop_immediate_propagation();
654 assert!(ev.propagation_stopped);
655 assert!(ev.immediate_propagation_stopped);
656 }
657
658 #[test]
659 fn test_modifier_keys() {
660 let mut ev = Event::new(EventType::KeyDown, 0);
661 ev.modifiers = 0b1111;
662 assert!(ev.shift_key());
663 assert!(ev.ctrl_key());
664 assert!(ev.alt_key());
665 assert!(ev.meta_key());
666
667 ev.modifiers = 0;
668 assert!(!ev.shift_key());
669 assert!(!ev.ctrl_key());
670 }
671
672 #[test]
673 fn test_hit_rect_contains() {
674 let r = HitRect::new(10, 20, 100, 50, 0);
675 assert!(r.contains(10, 20));
676 assert!(r.contains(50, 40));
677 assert!(r.contains(109, 69));
678 assert!(!r.contains(110, 20));
679 assert!(!r.contains(10, 70));
680 assert!(!r.contains(9, 20));
681 }
682
683 #[test]
684 fn test_node_tree_ancestor_path() {
685 let mut tree = NodeTree::new();
686 tree.set_parent(1, 0);
687 tree.set_parent(2, 1);
688 tree.set_parent(3, 1);
689
690 let path = tree.ancestor_path(2);
691 assert_eq!(path, vec![0, 1, 2]);
692
693 let path = tree.ancestor_path(0);
694 assert_eq!(path, vec![0]);
695 }
696
697 #[test]
698 fn test_add_remove_listener() {
699 let mut d = EventDispatcher::new();
700 d.add_event_listener(1, EventType::Click, 42, false);
701 assert_eq!(d.listeners_for(1).len(), 1);
702
703 let removed = d.remove_event_listener(1, EventType::Click, 42, false);
704 assert!(removed);
705 assert_eq!(d.listeners_for(1).len(), 0);
706 }
707
708 #[test]
709 fn test_remove_nonexistent_listener() {
710 let mut d = EventDispatcher::new();
711 let removed = d.remove_event_listener(1, EventType::Click, 99, false);
712 assert!(!removed);
713 }
714
715 #[test]
716 fn test_hit_test() {
717 let mut d = EventDispatcher::new();
718 d.add_hit_box(HitRect::new(0, 0, 800, 600, 0));
719 d.add_hit_box(HitRect::new(10, 10, 100, 50, 1));
720 d.add_hit_box(HitRect::new(20, 20, 30, 30, 2));
721
722 assert_eq!(d.hit_test(25, 25), Some(2));
724 assert_eq!(d.hit_test(5, 5), Some(0));
726 assert_eq!(d.hit_test(900, 900), None);
728 }
729
730 #[test]
731 fn test_dispatch_capture_bubble() {
732 let mut d = setup_tree();
733 d.add_event_listener(0, EventType::Click, 100, true);
735 d.add_event_listener(1, EventType::Click, 101, false);
736 d.add_event_listener(2, EventType::Click, 102, false);
737
738 let mut ev = Event::new(EventType::Click, 2);
739 d.dispatch(&mut ev);
740
741 let invoked = d.take_invoked();
742 assert_eq!(invoked.len(), 3);
744 assert_eq!(invoked[0].0, 100); assert_eq!(invoked[1].0, 102); assert_eq!(invoked[2].0, 101); }
748
749 #[test]
750 fn test_dispatch_stop_propagation() {
751 let mut d = setup_tree();
752 d.add_event_listener(0, EventType::Click, 100, true);
753 d.add_event_listener(1, EventType::Click, 101, true);
754 d.add_event_listener(2, EventType::Click, 102, false);
755
756 let mut ev = Event::new(EventType::Click, 2);
758 ev.propagation_stopped = false;
759 d.dispatch(&mut ev);
760 let invoked = d.take_invoked();
761 assert_eq!(invoked.len(), 3);
763 }
764
765 #[test]
766 fn test_dispatch_no_bubble() {
767 let mut d = setup_tree();
768 d.add_event_listener(0, EventType::Focus, 100, false);
769 d.add_event_listener(2, EventType::Focus, 102, false);
770
771 let mut ev = Event::new(EventType::Focus, 2);
772 assert!(!ev.bubbles);
773 d.dispatch(&mut ev);
774
775 let invoked = d.take_invoked();
776 assert_eq!(invoked.len(), 1);
778 assert_eq!(invoked[0].0, 102);
779 }
780
781 #[test]
782 fn test_dispatch_click_convenience() {
783 let mut d = EventDispatcher::new();
784 d.node_tree_mut().set_parent(1, 0);
785 d.add_hit_box(HitRect::new(0, 0, 100, 100, 1));
786 d.add_event_listener(1, EventType::Click, 50, false);
787
788 let result = d.dispatch_click(50, 50, 0);
789 assert!(result.is_some());
790 let (target, prevented) = result.unwrap();
791 assert_eq!(target, 1);
792 assert!(!prevented);
793 }
794
795 #[test]
796 fn test_dispatch_click_miss() {
797 let d = &mut EventDispatcher::new();
798 d.add_hit_box(HitRect::new(0, 0, 10, 10, 0));
799 let result = d.dispatch_click(100, 100, 0);
800 assert!(result.is_none());
801 }
802
803 #[test]
804 fn test_dispatch_key() {
805 let mut d = EventDispatcher::new();
806 d.add_event_listener(5, EventType::KeyDown, 77, false);
807
808 let prevented = d.dispatch_key(5, EventType::KeyDown, 65, 0, 0);
809 assert!(!prevented);
810 let invoked = d.take_invoked();
811 assert_eq!(invoked.len(), 1);
812 assert_eq!(invoked[0].0, 77);
813 }
814
815 #[test]
816 fn test_clear_listeners() {
817 let mut d = EventDispatcher::new();
818 d.add_event_listener(1, EventType::Click, 10, false);
819 d.add_event_listener(1, EventType::KeyDown, 11, false);
820 assert_eq!(d.listeners_for(1).len(), 2);
821 d.clear_listeners(1);
822 assert_eq!(d.listeners_for(1).len(), 0);
823 }
824
825 #[test]
826 fn test_multiple_listeners_same_node() {
827 let mut d = EventDispatcher::new();
828 d.add_event_listener(1, EventType::Click, 10, false);
829 d.add_event_listener(1, EventType::Click, 11, false);
830 d.add_event_listener(1, EventType::KeyDown, 12, false);
831
832 let mut ev = Event::new(EventType::Click, 1);
833 d.dispatch(&mut ev);
834 let invoked = d.take_invoked();
835 assert_eq!(invoked.len(), 2);
837 }
838
839 #[test]
840 fn test_fp_conversion() {
841 assert_eq!(fp_from_int(10), 640);
842 assert_eq!(fp_to_int(640), 10);
843 assert_eq!(fp_to_int(fp_from_int(42)), 42);
844 }
845
846 #[test]
847 fn test_event_phase_default() {
848 let phase = EventPhase::default();
849 assert_eq!(phase, EventPhase::None);
850 }
851
852 #[test]
853 fn test_node_tree_remove() {
854 let mut tree = NodeTree::new();
855 tree.set_parent(1, 0);
856 assert!(tree.parent(1).is_some());
857 tree.remove(1);
858 assert!(tree.parent(1).is_none());
859 }
860}