use std::any::Any;
use std::fmt::{self, Debug};
use std::rc::Rc;
use crate::node::DispatchFn;
pub type GlobalEventHandlerFn<T> = dyn Fn(&dyn GlobalEvent, &GlobalEventCtx<T>) -> Result<(), String> + 'static;
pub trait GlobalEvent: Any + Send + Sync {
fn as_any(&self) -> &dyn Any;
fn name(&self) -> &'static str {
std::any::type_name::<Self>()
}
}
impl<T> GlobalEvent for T
where
T: Any + Send + Sync,
{
fn as_any(&self) -> &dyn Any {
self
}
}
pub fn downcast_event<E: GlobalEvent + 'static>(event: &dyn GlobalEvent) -> Option<&E> {
event.as_any().downcast_ref::<E>()
}
pub struct GlobalEventCtx<'a, T>
where
T: Debug + Clone,
{
pub dispatch: &'a DispatchFn<T>,
pub component_path: &'a [Rc<str>],
}
pub struct GlobalEventHandler<T>
where
T: Debug + Clone,
{
inner: Rc<GlobalEventHandlerFn<T>>,
}
impl<T> Clone for GlobalEventHandler<T>
where
T: Debug + Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.to_owned(),
}
}
}
impl<T> GlobalEventHandler<T>
where
T: Debug + Clone,
{
pub fn new<F>(handler: F) -> Self
where
F: Fn(&dyn GlobalEvent, &GlobalEventCtx<T>) -> Result<(), String> + 'static,
{
Self { inner: Rc::new(handler) }
}
pub fn call(&self, event: &dyn GlobalEvent, ctx: &GlobalEventCtx<T>) -> Result<(), String> {
(self.inner)(event, ctx)
}
}
impl<T> PartialEq for GlobalEventHandler<T>
where
T: Debug + Clone,
{
fn eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.inner, &other.inner)
}
}
impl<T> Eq for GlobalEventHandler<T> where T: Debug + Clone {}
impl<T> fmt::Debug for GlobalEventHandler<T>
where
T: Debug + Clone,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("[GlobalEventHandler]")
}
}
pub fn global_event_handler<T, F>(handler: F) -> GlobalEventHandler<T>
where
T: Debug + Clone,
F: Fn(&dyn GlobalEvent, &GlobalEventCtx<T>) -> Result<(), String> + 'static,
{
GlobalEventHandler::new(handler)
}