use crate::{ layout::{IdFnTag, Ui, UiModule, Widget, WidgetId, WidgetIdFn, WidgetLike}, util::Id, }; pub trait UiCtx { fn ui(&mut self) -> &mut Ui where Self: Sized; } pub trait Event: Sized { type Module: UiModule + EventModule + Default; type Data; } pub trait EventModule> { fn register(&mut self, id: Id, event: E, f: impl EventFn); } pub trait EventFn: FnMut(&mut Ctx, Data) + 'static {} impl EventFn for F {} pub trait Eventable { fn on>( self, event: E, f: impl EventFn, ) -> impl WidgetIdFn + Eventable; fn id_on>( self, event: E, f: impl FnMut(&WidgetId, &mut Ctx, E::Data) + 'static, ) -> impl WidgetIdFn + Eventable where W: Widget; fn edit_on>( self, event: E, f: impl FnMut(&mut W, E::Data) + 'static, ) -> impl WidgetIdFn + Eventable where W: Widget, Ctx: UiCtx; } pub trait Ctxable { /// sets context which lets event functions work without needing to specify generics fn ctx(self) -> impl WidgetLike + Eventable; } impl, Tag> Ctxable for W { fn ctx(self) -> impl WidgetLike + Eventable { self } } impl, Ctx, Tag> Eventable for W { fn on>( self, event: E, f: impl EventFn, ) -> impl WidgetIdFn + Eventable { move |ui| { let id = self.add(ui); ui.modules .get_mut::() .register(id.id.duplicate(), event, f); id } } fn id_on>( self, event: E, mut f: impl FnMut(&WidgetId, &mut Ctx, E::Data) + 'static, ) -> impl WidgetIdFn + Eventable where W::Widget: Widget, { self.with_id(move |ui, id| { let id2 = id.clone(); id.on(event, move |ctx, pos| f(&id2, ctx, pos)).add(ui) }) } fn edit_on>( self, event: E, mut f: impl FnMut(&mut W::Widget, E::Data) + 'static, ) -> impl WidgetIdFn + Eventable where W::Widget: Widget, Ctx: UiCtx, { self.id_on(event, move |id, ctx, pos| f(&mut ctx.ui()[id], pos)) } }