use std::{boxed::Box, future::Future, pin::Pin};
#[cfg(not(feature = "threadsafe"))]
pub type EventHandlerAsyncCallback<O, A> =
dyn FnMut(O, A) -> Pin<Box<dyn Future<Output = ()> + 'static>> + 'static;
#[cfg(not(feature = "threadsafe"))]
pub type EventHandlerSyncCallback<H, A> = dyn FnMut(&H, A) + 'static;
#[cfg(feature = "threadsafe")]
pub type EventHandlerAsyncCallback<O, A> =
dyn FnMut(O, A) -> Pin<Box<dyn Future<Output = ()> + 'static>> + Send + 'static;
#[cfg(feature = "threadsafe")]
pub type EventHandlerSyncCallback<H, A> = dyn FnMut(&H, A) + Send + 'static;
pub enum EventHandler<H, O, A> {
Sync(Box<EventHandlerSyncCallback<H, A>>),
Async(Box<EventHandlerAsyncCallback<O, A>>),
}
pub(crate) trait Event<H, O, A> {
fn register_handler(&mut self, handler: EventHandler<H, O, A>);
}
pub trait EventExt<H, O, A> {
#[cfg(not(feature = "threadsafe"))]
fn register<X>(&mut self, handler: X)
where
X: FnMut(&H, A) + 'static;
#[cfg(feature = "threadsafe")]
fn register<X>(&mut self, handler: X)
where
X: FnMut(&H, A) + Send + 'static;
#[cfg(not(feature = "threadsafe"))]
fn register_async<X, F>(&mut self, handler: X)
where
X: FnMut(O, A) -> F + 'static,
F: Future<Output = ()> + 'static;
#[cfg(feature = "threadsafe")]
fn register_async<X, F>(&mut self, handler: X)
where
X: FnMut(O, A) -> F + Send + 'static,
F: Future<Output = ()> + 'static;
}
impl<H, O, A, T> EventExt<H, O, A> for T
where
T: Event<H, O, A>,
{
#[cfg(not(feature = "threadsafe"))]
fn register<X>(&mut self, mut handler: X)
where
X: FnMut(&H, A) + 'static,
{
self.register_handler(EventHandler::Sync(Box::new(move |h, args| {
handler(h, args);
})));
}
#[cfg(feature = "threadsafe")]
fn register<X>(&mut self, mut handler: X)
where
X: FnMut(&H, A) + Send + 'static,
{
self.register_handler(EventHandler::Sync(Box::new(move |h, args| {
handler(h, args);
})));
}
#[cfg(not(feature = "threadsafe"))]
fn register_async<X, F>(&mut self, mut handler: X)
where
X: FnMut(O, A) -> F + 'static,
F: Future<Output = ()> + 'static,
{
self.register_handler(EventHandler::Async(Box::new(move |h, args| {
Box::pin(handler(h, args))
})));
}
#[cfg(feature = "threadsafe")]
fn register_async<X, F>(&mut self, mut handler: X)
where
X: FnMut(O, A) -> F + Send + 'static,
F: Future<Output = ()> + 'static,
{
self.register_handler(EventHandler::Async(Box::new(move |h, args| {
Box::pin(handler(h, args))
})));
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! decl_event {
($name:ident < $owner:ty >) => {
pub struct $name {
#[allow(dead_code)]
pub(crate) owner: crate::rc::Weak<$owner>,
}
impl $name {
#[allow(dead_code)]
pub(crate) fn new(owner: crate::rc::Weak<$owner>) -> Self { Self { owner } }
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! decl_browser_event {
($name:ident) => {
decl_event!($name<BrowserWindowOwner>);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! def_event {
( $name:ident<$handle_type:ty, $owner_type:ty, $arg_type:ty> (&mut $this:ident, $arg_name:ident) $body:block ) => {
impl crate::event::Event<$handle_type, $owner_type, $arg_type> for $name {
fn register_handler(&mut $this, $arg_name: crate::event::EventHandler<$handle_type, $owner_type, $arg_type>) $body
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! def_browser_event {
( $name:ident<$arg_type:ty> (&mut $this:ident, $arg_name:ident) $body:block ) => {
def_event!($name<BrowserWindowHandle, BrowserWindow, $arg_type> (&mut $this, $arg_name) $body);
}
}