use crate::{Ui, UiModule, Widget, WidgetId, WidgetRef, util::HashMap}; use std::{ hash::Hash, ops::{Index, IndexMut}, rc::Rc, }; pub trait Event: Sized { type Module: EventModule; type Data: Clone; } pub struct EventCtx<'a, Ctx, Data> { pub ui: &'a mut Ui, pub state: &'a mut Ctx, pub data: Data, } pub struct EventIdCtx<'a, Ctx, Data, W: ?Sized> { pub widget: WidgetRef, pub ui: &'a mut Ui, pub state: &'a mut Ctx, pub data: 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 { } pub trait DefaultEvent: Hash + Eq + 'static { type Data: Clone = (); } impl Event for E { type Module = DefaultEventModule; type Data = E::Data; } pub trait EventModule: UiModule + Default { fn register(&mut self, id: WidgetId, event: E, f: impl EventFn); fn run<'a>( &self, id: WidgetId, event: E, ) -> Option) + use<'a, Self, E, Ctx>>; } type EventFnMap = HashMap>>>; pub struct DefaultEventModule { map: HashMap::Data>>, } impl UiModule for DefaultEventModule { fn on_remove(&mut self, id: WidgetId) { for map in self.map.values_mut() { map.remove(&id); } } } pub trait HashableEvent: Event + Hash + Eq + 'static {} impl HashableEvent for E {} impl EventModule for DefaultEventModule { fn register(&mut self, id: WidgetId, event: E, f: impl EventFn::Data>) { self.map .entry(event) .or_default() .entry(id) .or_default() .push(Rc::new(f)); } fn run<'a>( &self, id: WidgetId, event: E, ) -> Option) + use<'a, E, Ctx>> { if let Some(map) = self.map.get(&event) && let Some(fs) = map.get(&id) { let fs = fs.clone(); Some(move |ctx: EventCtx::Data>| { for f in &fs { f(EventCtx { ui: ctx.ui, state: ctx.state, data: ctx.data.clone(), }) } }) } else { None } } } impl DefaultEventModule { pub fn run_all(&self, event: E, ctx: EventCtx) where E::Data: Clone, { if let Some(map) = self.map.get(&event) { for fs in map.values() { for f in fs { f(EventCtx { ui: ctx.ui, state: ctx.state, data: ctx.data.clone(), }) } } } } } impl Default for DefaultEventModule { fn default() -> Self { Self { map: Default::default(), } } } impl Ui { pub fn run_event( &mut self, ctx: &mut Ctx, id: WidgetRef, event: E, data: E::Data, ) { if let Some(f) = self .data .modules .get_mut::>() .run(id.id(), event) { f(EventCtx { ui: self, state: ctx, data, }); } } }