use std::any::TypeId;
use std::fmt::Debug;
use crate::Cap;
use crate::Handleable;
use crate::MutCap;
use crate::Object;
use crate::Renderable;
pub trait Widget<E, M>: Handleable<E, M> + Renderable + Object + Debug
where
E: 'static,
M: 'static,
{
fn type_id(&self) -> TypeId;
fn data<'c, D>(&self, cap: &'c dyn Cap) -> &'c D
where
Self: Sized,
D: 'static,
{
cap.data(self.id()).downcast_ref::<D>().unwrap()
}
fn data_mut<'c, D>(&self, cap: &'c mut dyn MutCap<E, M>) -> &'c mut D
where
Self: Sized,
D: 'static,
E: Debug,
M: Debug,
{
cap.data_mut(self.id()).downcast_mut::<D>().unwrap()
}
}
impl<E, M> dyn Widget<E, M>
where
E: 'static,
M: 'static,
{
pub fn is<T: Widget<E, M>>(&self) -> bool {
let t = TypeId::of::<T>();
let own_t = Widget::type_id(self);
t == own_t
}
pub fn downcast_ref<T: Widget<E, M>>(&self) -> Option<&T> {
if self.is::<T>() {
unsafe { Some(&*(self as *const dyn Widget<E, M> as *const T)) }
} else {
None
}
}
pub fn downcast_mut<T: Widget<E, M>>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
unsafe { Some(&mut *(self as *mut dyn Widget<E, M> as *mut T)) }
} else {
None
}
}
}