use std::any::Any;
use crate::prelude::*;
pub struct CustomEvent<E: ?Sized> {
pub(crate) common: CommonEvent,
pub(crate) data: Box<dyn Any>,
_marker: std::marker::PhantomData<E>,
}
pub type RawCustomEvent = CustomEvent<dyn Any>;
pub fn new_custom_event(common: CommonEvent, data: Box<dyn Any>) -> RawCustomEvent {
CustomEvent { common, data, _marker: std::marker::PhantomData }
}
impl<E: ?Sized> std::ops::Deref for CustomEvent<E> {
type Target = CommonEvent;
#[inline]
fn deref(&self) -> &Self::Target { &self.common }
}
impl<E: ?Sized> std::ops::DerefMut for CustomEvent<E> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.common }
}
impl<E: Sized + 'static> CustomEvent<E> {
pub fn data(&self) -> &E { self.data.downcast_ref::<E>().unwrap() }
pub fn data_mut(&mut self) -> &mut E { self.data.downcast_mut::<E>().unwrap() }
}
impl<E: ?Sized> AsRef<ProviderCtx> for CustomEvent<E> {
fn as_ref(&self) -> &ProviderCtx { self.common.as_ref() }
}
impl<E: ?Sized> AsMut<ProviderCtx> for CustomEvent<E> {
fn as_mut(&mut self) -> &mut ProviderCtx { self.common.as_mut() }
}
impl RawCustomEvent {
pub fn downcast_ref<E: 'static>(&self) -> Option<&CustomEvent<E>> {
if self.data.downcast_ref::<E>().is_some() {
Some(unsafe { &*(self as *const CustomEvent<dyn Any> as *const CustomEvent<E>) })
} else {
None
}
}
pub fn downcast_mut<E: 'static>(&mut self) -> Option<&mut CustomEvent<E>> {
if self.data.downcast_mut::<E>().is_some() {
Some(unsafe { &mut *(self as *mut CustomEvent<dyn Any> as *mut CustomEvent<E>) })
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use crate::{prelude::*, reset_test_env, test_helper::*};
#[test]
fn custom_event() {
reset_test_env!();
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
struct MyCustomData(i32);
type MyCustomEvent = CustomEvent<MyCustomData>;
let (self_data, w_self_data) = split_value(None);
let (parent_data, w_parent_data) = split_value(None);
let w = fn_widget! {
@MockBox {
size: Size::new(100., 100.),
on_raw_custom: move |e: &mut RawCustomEvent| {
if let Some(e) = e.downcast_mut() {
*$write(w_parent_data) = Some(*e.data());
}
},
@MockBox {
size: Size::new(50., 50.),
on_mounted: move |e| {
e.window().bubble_custom_event(e.widget_id(), MyCustomData(1));
},
on_custom: move |e: &mut MyCustomEvent| {
*$write(w_self_data) = Some(*e.data());
}
}
}
};
let wnd = TestWindow::new_with_size(w, Size::new(100., 100.));
wnd.draw_frame();
assert_eq!(*self_data.read(), Some(MyCustomData(1)));
assert_eq!(*parent_data.read(), Some(MyCustomData(1)));
}
}