use crate::prelude::*;
use hashbrown::HashMap;
use std::any::{Any, TypeId};
pub trait Model: 'static + Sized {
fn build(self, cx: &mut Context) -> &Self {
let current = if cx.tree.is_ignored(cx.current) {
cx.tree.get_layout_parent(cx.current).unwrap()
} else {
cx.current
};
if let Some(models) = cx.models.get_mut(¤t) {
models.insert(TypeId::of::<Self>(), Box::new(self));
} else {
let mut models: HashMap<TypeId, Box<dyn ModelData>> = HashMap::new();
models.insert(TypeId::of::<Self>(), Box::new(self));
cx.models.insert(current, models);
}
cx.models
.get(¤t)
.unwrap()
.get(&TypeId::of::<Self>())
.unwrap()
.as_any_ref()
.downcast_ref::<Self>()
.unwrap()
}
#[allow(unused_variables)]
fn event(&mut self, cx: &mut EventContext, event: &mut Event) {}
#[cfg(debug_assertions)]
fn name(&self) -> Option<&'static str> {
None
}
}
pub(crate) trait ModelData: Any {
#[allow(unused_variables)]
fn event(&mut self, cx: &mut EventContext, event: &mut Event) {}
fn as_any_ref(&self) -> &dyn Any;
#[cfg(debug_assertions)]
fn name(&self) -> Option<&'static str>;
}
impl dyn ModelData {
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
self.as_any_ref().downcast_ref()
}
}
impl<T: Model> ModelData for T {
fn event(&mut self, cx: &mut EventContext, event: &mut Event) {
<T as Model>::event(self, cx, event);
}
fn as_any_ref(&self) -> &dyn Any {
self
}
#[cfg(debug_assertions)]
fn name(&self) -> Option<&'static str> {
<T as Model>::name(self)
}
}
impl Model for () {}