event handler on events
This commit is contained in:
+21
-9
@@ -1,6 +1,7 @@
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use crate::event;
|
||||
@@ -11,7 +12,8 @@ pub trait Event {
|
||||
fn as_any(self: Box<Self>) -> Box<dyn Any>;
|
||||
}
|
||||
|
||||
pub struct EventHandlerFn(pub Box<dyn FnMut(Box<dyn Event>)>);
|
||||
#[derive(Clone)]
|
||||
pub struct EventHandlerFn(pub Arc<Mutex<dyn FnMut(&mut EventManager, Box<dyn Event>)>>);
|
||||
|
||||
impl std::fmt::Debug for EventHandlerFn {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
@@ -31,12 +33,17 @@ impl EventManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on<E: Event + 'static, F: FnMut(Box<E>) + 'static>(&mut self, mut f: F) {
|
||||
let wrapper = Box::new(move |evt: Box<dyn Event>| {
|
||||
if let Ok(concrete) = evt.as_any().downcast::<E>() {
|
||||
f(concrete);
|
||||
}
|
||||
}) as Box<dyn FnMut(Box<dyn Event>)>;
|
||||
pub fn on<E: Event + 'static, F: FnMut(&mut EventManager, Box<E>) + 'static>(
|
||||
&mut self,
|
||||
mut f: F,
|
||||
) {
|
||||
let wrapper = Arc::new(Mutex::new(
|
||||
move |e: &mut EventManager, evt: Box<dyn Event>| {
|
||||
if let Ok(concrete) = evt.as_any().downcast::<E>() {
|
||||
f(e, concrete);
|
||||
}
|
||||
},
|
||||
)) as Arc<Mutex<dyn FnMut(&mut EventManager, Box<dyn Event>)>>;
|
||||
|
||||
self.handlers
|
||||
.entry(TypeId::of::<E>())
|
||||
@@ -46,9 +53,14 @@ impl EventManager {
|
||||
|
||||
pub fn dispatch<E: Event + 'static + Clone>(&mut self, evt: E) {
|
||||
let tid = evt.type_id();
|
||||
|
||||
if let Some(handlers) = self.handlers.get_mut(&tid) {
|
||||
for h in handlers {
|
||||
(h.0)(Box::new(evt.clone()));
|
||||
// Clone handlers to avoid borrowing self during call
|
||||
let handler_clones: Vec<_> = handlers.iter().cloned().collect();
|
||||
|
||||
for h in handler_clones {
|
||||
let mut ha = h.0.lock().unwrap();
|
||||
(ha)(self, Box::new(evt.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user