use crate::OutputType;
use htmlescape::encode_attribute;
use std::fmt::{Display, Error, Formatter};
use std::iter;
pub trait EventHandler<T: OutputType + Send, E: Send> {
fn attach(&mut self, target: &mut T::EventTarget) -> T::EventListenerHandle;
fn render(&self) -> Option<String>;
}
macro_rules! declare_events_struct {
($($name:ident,)*) => {
pub struct Events<T> where T: Send {
$(
pub $name: Option<T>,
)*
}
impl<T: Send> Events<T> {
pub fn iter(&self) -> impl Iterator<Item = (&'static str, &T)> {
iter::empty()
$(
.chain(
self.$name.iter()
.map(|value| (stringify!($name), value))
)
)*
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&'static str, &mut T)> {
iter::empty()
$(
.chain(
self.$name.iter_mut()
.map(|value| (stringify!($name), value))
)
)*
}
}
impl<T: 'static + Send> IntoIterator for Events<T> {
type Item = (&'static str, T);
type IntoIter = Box<dyn Iterator<Item = Self::Item>>;
fn into_iter(mut self) -> Self::IntoIter {
Box::new(
iter::empty()
$(
.chain(
iter::once(self.$name.take())
.filter(Option::is_some)
.map(|value| (stringify!($name), value.unwrap()))
)
)*
)
}
}
impl<T: Send> Default for Events<T> {
fn default() -> Self {
Events {
$(
$name: None,
)*
}
}
}
impl<T: Display + Send> Display for Events<T> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
$(
if let Some(ref value) = self.$name {
let attribute = encode_attribute(&value.to_string());
write!(f, " on{}=\"{}\"", stringify!($name), attribute)?;
}
)*
Ok(())
}
}
}
}
declare_events_struct! {
abort,
autocomplete,
autocompleteerror,
blur,
cancel,
canplay,
canplaythrough,
change,
click,
close,
contextmenu,
cuechange,
dblclick,
drag,
dragend,
dragenter,
dragexit,
dragleave,
dragover,
dragstart,
drop,
durationchange,
emptied,
ended,
error,
focus,
input,
invalid,
keydown,
keypress,
keyup,
load,
loadeddata,
loadedmetadata,
loadstart,
mousedown,
mouseenter,
mouseleave,
mousemove,
mouseout,
mouseover,
mouseup,
mousewheel,
pause,
play,
playing,
progress,
ratechange,
reset,
resize,
scroll,
seeked,
seeking,
select,
show,
sort,
stalled,
submit,
suspend,
timeupdate,
toggle,
volumechange,
waiting,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty_events_iter() {
let events: Events<&str> = Events::default();
let mut iter = events.iter();
assert_eq!(iter.next(), None);
}
#[test]
fn test_events_iter() {
let mut events: Events<&str> = Events::default();
events.abort = Some("abort");
events.waiting = Some("waiting");
let mut iter = events.iter();
assert_eq!(iter.next(), Some(("abort", &"abort")));
assert_eq!(iter.next(), Some(("waiting", &"waiting")));
assert_eq!(iter.next(), None);
}
#[test]
fn test_events_iter_mut() {
let mut events: Events<&str> = Events::default();
events.abort = Some("abort");
events.waiting = Some("waiting");
let mut iter = events.iter_mut();
assert_eq!(iter.next(), Some(("abort", &mut "abort")));
assert_eq!(iter.next(), Some(("waiting", &mut "waiting")));
assert_eq!(iter.next(), None);
}
#[test]
fn test_events_into_iter() {
let mut events: Events<&str> = Events::default();
events.abort = Some("abort");
events.waiting = Some("waiting");
let mut iter = events.into_iter();
assert_eq!(iter.next(), Some(("abort", "abort")));
assert_eq!(iter.next(), Some(("waiting", "waiting")));
assert_eq!(iter.next(), None);
}
}