use std::{hash::Hash, rc::Rc}; use crate::{ layout::{Ui, UiModule, WeakWidgetId, WidgetId}, util::{HashMap, Id}, }; 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 type ECtx<'a, Ctx, Data, W> = EventIdCtx<'a, Ctx, Data, W>; pub struct EventIdCtx<'a, Ctx, Data, W> { pub id: &'a WeakWidgetId, pub ui: &'a mut Ui, pub state: &'a mut Ctx, pub data: Data, } pub trait EventFn: Fn(EventCtx) + 'static {} impl) + 'static, Ctx, Data> EventFn for F {} pub trait WidgetEventFn: Fn(EventIdCtx) + 'static {} impl) + 'static, Ctx, Data, W> 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: Id, event: E, f: impl EventFn); fn run<'a>( &self, id: &Id, 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: &Id) { 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: Id, 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: &Id, 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: &WidgetId, 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, }); } } }