use crate::{ ActiveData, IdLike, LayerId, Ui, Widget, WidgetData, WidgetId, WidgetRef, util::HashMap, }; use std::{ any::{Any, TypeId}, ops::{Index, IndexMut}, rc::Rc, }; pub trait Event: Sized + 'static + Clone { type Data<'a> = (); type State: Default = (); #[allow(unused_variables)] fn should_run(&self, data: &mut Self::Data<'_>) -> bool { true } } pub trait EventLike { type Event: Event; fn into_event(self) -> Self::Event; } impl EventLike for E { type Event = Self; fn into_event(self) -> Self::Event { self } } pub struct EventCtx<'a, Ctx, Data> { pub ui: &'a mut Ui, pub state: &'a mut Ctx, pub data: &'a mut Data, } pub struct EventIdCtx<'a, Ctx, Data, W: ?Sized> { pub widget: WidgetRef, pub ui: &'a mut Ui, pub state: &'a mut Ctx, pub data: &'a mut Data, } #[derive(Default)] pub struct EventManager { types: HashMap>, } impl EventManager { pub fn get_type(&mut self) -> &mut TypeEventManager { self.types .entry(Self::type_key::()) .or_insert(Box::new(TypeEventManager::::default())) .as_any() .downcast_mut() .unwrap() } pub fn register( &mut self, id: I, event: E, f: impl for<'a> EventFn::Data<'a>>, ) { self.get_type::().register(id, event, f); } pub fn type_key() -> TypeId { TypeId::of::>() } pub fn remove(&mut self, id: WidgetId) { for m in self.types.values_mut() { m.remove(id); } } pub fn draw(&mut self, data: &WidgetData, active: &ActiveData) { for t in &data.event_mgrs { self.types.get_mut(t).unwrap().draw(active); } } pub fn undraw(&mut self, data: &WidgetData, active: &ActiveData) { for t in &data.event_mgrs { self.types.get_mut(t).unwrap().undraw(active); } } } pub trait EventManagerLike { fn remove(&mut self, id: WidgetId); fn draw(&mut self, data: &ActiveData); fn undraw(&mut self, data: &ActiveData); fn as_any(&mut self) -> &mut dyn Any; } type EventData = (E, Rc EventFn::Data<'a>>>); pub struct TypeEventManager { // TODO: reduce visiblity!! pub active: HashMap>, map: HashMap>>, } impl EventManagerLike for TypeEventManager { fn remove(&mut self, id: WidgetId) { self.map.remove(&id); for layer in self.active.values_mut() { layer.remove(&id); } } fn draw(&mut self, data: &ActiveData) { self.active .entry(data.layer) .or_default() .entry(data.id) .or_default(); } fn undraw(&mut self, data: &ActiveData) { if let Some(layer) = self.active.get_mut(&data.layer) { layer.remove(&data.id); } } fn as_any(&mut self) -> &mut dyn Any { self } } impl Default for TypeEventManager { fn default() -> Self { Self { active: Default::default(), map: Default::default(), } } } impl TypeEventManager { fn register( &mut self, id: impl IdLike, event: impl EventLike, f: impl for<'a> EventFn>, ) { let event = event.into_event(); self.map .entry(id.id()) .or_default() .push((event, Rc::new(f))); } fn run_fn<'a>( &mut self, id: impl IdLike, ) -> impl for<'b> FnOnce(EventCtx>) + 'a { let fs = self.map.get(&id.id()).cloned().unwrap_or_default(); move |ctx| { for (e, f) in fs { if e.should_run(ctx.data) { f(EventCtx { ui: ctx.ui, state: ctx.state, data: ctx.data, }) } } } } } impl<'a, Ctx, Data, W2, W: Widget> Index> for EventIdCtx<'a, Ctx, Data, W2> { type Output = W; fn index(&self, index: WidgetRef) -> &Self::Output { &self.ui[index] } } impl<'a, Ctx, Data, W2, W: Widget> IndexMut> for EventIdCtx<'a, Ctx, Data, W2> { fn index_mut(&mut self, index: WidgetRef) -> &mut Self::Output { &mut self.ui[index] } } impl<'a, Ctx, Data, W: Widget> EventIdCtx<'a, Ctx, Data, W> { pub fn widget(&mut self) -> &mut W { &mut self.ui[self.widget] } } pub trait EventFn: Fn(EventCtx) + 'static {} impl) + 'static, Ctx, Data> EventFn for F {} pub trait WidgetEventFn: Fn(EventIdCtx) + 'static {} impl) + 'static, Ctx, Data, W: ?Sized> WidgetEventFn for F { } impl Ui { pub fn run_event( &mut self, ctx: &mut Ctx, id: impl IdLike, data: &mut ::Data<'_>, ) { let f = self.data.events.get_type::().run_fn(id); f(EventCtx { ui: self, state: ctx, data, }) } }