use std::marker::PhantomData;
use stdweb::web::event::*;
use stdweb::web::{Element, EventListenerHandle, IEventTarget};
use super::{OutputType, DOM};
macro_rules! declare_events {
($($name:ident : $type:ty ,)*) => {
pub struct Events<T: OutputType> {
$(
pub $name: Option<Box<dyn EventHandler<T, $type>>>,
)*
}
impl<T: OutputType> Default for Events<T> {
fn default() -> Self {
Events {
$(
$name: None,
)*
}
}
}
#[macro_export]
macro_rules! for_events {
($event:ident in $events:expr => $body:block) => {
$(
if let Some(ref mut $event) = $events.$name $body
)*
}
}
}
}
declare_events! {
abort: ResourceAbortEvent,
blur: BlurEvent,
change: ChangeEvent,
click: ClickEvent,
contextmenu: ContextMenuEvent,
dblclick: DoubleClickEvent,
drag: DragEvent,
dragend: DragEndEvent,
dragenter: DragEnterEvent,
dragexit: DragExitEvent,
dragleave: DragLeaveEvent,
dragover: DragOverEvent,
dragstart: DragStartEvent,
drop: DragDropEvent,
error: ResourceErrorEvent,
focus: FocusEvent,
input: InputEvent,
keydown: KeyDownEvent,
keypress: KeyPressEvent,
keyup: KeyUpEvent,
load: ResourceLoadEvent,
loadstart: LoadStartEvent,
mousedown: MouseDownEvent,
mouseenter: MouseEnterEvent,
mouseleave: MouseLeaveEvent,
mousemove: MouseMoveEvent,
mouseout: MouseOutEvent,
mouseover: MouseOverEvent,
mouseup: MouseUpEvent,
mousewheel: MouseWheelEvent,
progress: ProgressEvent,
resize: ResizeEvent,
scroll: ScrollEvent,
submit: SubmitEvent,
}
pub trait EventHandler<T: OutputType, E> {
fn attach(&mut self, target: &Element) -> EventListenerHandle;
fn render(&self) -> Option<String>;
}
pub trait IntoEventHandler<T: OutputType, E> {
fn into_event_handler(self) -> Box<dyn EventHandler<T, E>>;
}
pub struct EFn<F, E>(Option<F>, PhantomData<E>);
impl<F, E> EFn<F, E>
where
F: FnMut(E) + 'static,
E: ConcreteEvent,
{
pub fn new(f: F) -> Self {
EFn(Some(f), PhantomData)
}
}
impl<F, E> IntoEventHandler<DOM, E> for EFn<F, E>
where
F: FnMut(E) + 'static,
E: ConcreteEvent + 'static,
{
fn into_event_handler(self) -> Box<dyn EventHandler<DOM, E>> {
Box::new(self)
}
}
impl<F, E> IntoEventHandler<DOM, E> for F
where
F: FnMut(E) + 'static,
E: ConcreteEvent + 'static,
{
fn into_event_handler(self) -> Box<dyn EventHandler<DOM, E>> {
Box::new(EFn::new(self))
}
}
impl<F, E> EventHandler<DOM, E> for EFn<F, E>
where
F: FnMut(E) + 'static,
E: ConcreteEvent,
{
fn attach(&mut self, target: &Element) -> EventListenerHandle {
let handler = self.0.take().unwrap();
target.add_event_listener(handler)
}
fn render(&self) -> Option<String> {
None
}
}
impl<E> EventHandler<String, E> for &'static str {
fn attach(&mut self, _target: &Element) -> EventListenerHandle {
panic!("Silly wabbit, strings as event handlers are only for printing.");
}
fn render(&self) -> Option<String> {
Some(self.to_string())
}
}
impl<E> IntoEventHandler<String, E> for &'static str {
fn into_event_handler(self) -> Box<dyn EventHandler<String, E>> {
Box::new(self)
}
}