use crate::app::{Application, WeakMain};
use wasm_bindgen::closure::Closure;
use wasm_bindgen::JsCast;
pub trait Listener {
fn event_name(&self) -> &str;
fn js_function(&self) -> &js_sys::Function;
}
pub trait EventHandler<A: Application> {
fn create_event_listener(&mut self, main: &WeakMain<A>) -> Box<Listener>;
}
pub type ElementEventHandler<A> = ::std::cell::Cell<Option<Box<EventHandler<A>>>>;
macro_rules! impl_element_events_that_send_message_back_to_simi_app {
(
$(($handler_doc:expr, $HandlerType:ident, $listener_doc:expr, $ListenerType:ident))+
) => {$(
#[doc = $handler_doc]
pub struct $HandlerType<F> {
event_name: &'static str,
handler: Option<F>,
}
impl<F> $HandlerType<F> {
pub fn new(event_name: &'static str, handler: F) -> Self {
Self {
event_name,
handler: Some(handler),
}
}
}
impl<F,A> EventHandler<A> for $HandlerType<F>
where
A: Application,
F: Fn(web_sys::$HandlerType) -> A::Message + 'static,
{
fn create_event_listener(&mut self, main: &WeakMain<A>) -> Box<Listener> { let main = main.clone();
let handler = self.handler.take().expect("Event handler");
let handler = move |val: web_sys::$HandlerType| {
main.send_message(handler(val));
};
let closure = Closure::wrap(Box::new(handler) as Box<Fn(web_sys::$HandlerType)>);
Box::new(
$ListenerType{
event_name: self.event_name,
closure
}
)
}
}
#[doc = $listener_doc]
pub(crate) struct $ListenerType {
event_name: &'static str,
closure: Closure<Fn(web_sys::$HandlerType)>,
}
impl Listener for $ListenerType {
fn event_name(&self) -> &str {
self.event_name
}
fn js_function(&self) -> &js_sys::Function{
self.closure.as_ref().unchecked_ref()
}
}
)+};
}
impl_element_events_that_send_message_back_to_simi_app! {
(
"Event handler for FocusEvent",
FocusEvent,
"Event listener for FocusEvent",
FocusEventListener
)
(
"Event handler for MouseEvent",
MouseEvent,
"Event listener for MouseEvent",
MouseEventListener
)
(
"Event handler for WheelEvent",
WheelEvent,
"Event listener for WheelEvent",
WheelEventListener
)
(
"Event handler for UiEvent",
UiEvent,
"Event listener for UiEvent",
UiEventListener
)
(
"Event handler for InputEvent",
InputEvent,
"Event listener for InputEvent",
InputEventListener
)
(
"Event handler for KeyboardEvent",
KeyboardEvent,
"Event listener for KeyboardEvent",
KeyboardEventListener
)
(
"Event handler for Event",
Event,
"Event listener for Event",
EventListener
)
}