even2/
lib.rs

1//! original source: https://github.com/willcrichton/types-over-strings/blob/master/src/event.rs
2
3#![forbid(unsafe_code)]
4
5use as_any::{AsAny, Downcast};
6use std::any::{Any, TypeId};
7use std::collections::HashMap;
8
9pub trait Event: AsAny {}
10
11type OneOneED<E> = Box<dyn FnMut(&E) + 'static>;
12type OneEventDispatcher<E> = Vec<OneOneED<E>>;
13
14pub struct EventDispatcher(HashMap<TypeId, (fn(&mut dyn Any, &dyn Event), Box<dyn Any>)>);
15
16fn dyn_delegate<E: Event>(listeners: &mut dyn Any, event: &dyn Event) {
17    let listeners = listeners
18        .downcast_mut::<OneEventDispatcher<E>>()
19        .expect("dyn_delegate: mismatching listeners type");
20    let event: &E = event
21        .downcast_ref()
22        .expect("dyn_delegate: mismatching event type");
23
24    for callback in listeners {
25        callback(event);
26    }
27}
28
29impl EventDispatcher {
30    #[inline]
31    pub fn new() -> EventDispatcher {
32        EventDispatcher(HashMap::new())
33    }
34
35    pub fn add_event_listener<E, F>(&mut self, f: F)
36    where
37        E: Event,
38        F: FnMut(&E) + 'static,
39    {
40        (*self
41            .0
42            .entry(TypeId::of::<E>())
43            .or_insert_with(|| (dyn_delegate::<E>, Box::new(Vec::<OneOneED<E>>::new())))
44            .1)
45            .downcast_mut::<OneEventDispatcher<E>>()
46            .unwrap()
47            .push(Box::new(f));
48    }
49
50    #[inline]
51    pub fn clear<E: Event>(&mut self) {
52        self.0.remove(&TypeId::of::<E>());
53    }
54
55    #[inline]
56    pub fn clear_all(&mut self) {
57        self.0.clear();
58    }
59
60    pub fn trigger<E: Event>(&mut self, event: &E) {
61        if let Some(listeners) = self.0.get_mut(&TypeId::of::<E>()) {
62            for callback in (*listeners.1).downcast_mut::<OneEventDispatcher<E>>().unwrap() {
63                callback(event);
64            }
65        }
66    }
67
68    pub fn trigger_dyn(&mut self, event: &dyn Event) {
69        if let Some(listeners) = self.0.get_mut(&event.type_id()) {
70            let d2 = listeners.0;
71            d2(&mut *listeners.1, event);
72        }
73    }
74}
75
76#[cfg(test)]
77mod test {
78    use super::*;
79    use std::{cell::RefCell, rc::Rc};
80
81    struct OnClick {
82        mouse_x: i32,
83        mouse_y: i32,
84    }
85
86    impl Event for OnClick {}
87
88    #[test]
89    fn basic() {
90        let mut node = EventDispatcher::new();
91        let x = Rc::new(RefCell::new(0));
92        let x2 = Rc::clone(&x);
93        node.add_event_listener(move |event: &OnClick| {
94            *x2.borrow_mut() += 1;
95            assert_eq!(event.mouse_x, 10);
96            assert_eq!(event.mouse_y, 5);
97        });
98        let e = OnClick {
99            mouse_x: 10,
100            mouse_y: 5,
101        };
102        node.trigger(&e);
103        node.trigger_dyn(&e);
104        assert_eq!(*x.borrow(), 2);
105    }
106}