refactor project structure (start of redoing atomic branch without atomics)
This commit is contained in:
149
core/src/layout/event.rs
Normal file
149
core/src/layout/event.rs
Normal file
@@ -0,0 +1,149 @@
|
||||
use std::{hash::Hash, rc::Rc};
|
||||
|
||||
use crate::{
|
||||
layout::{Ui, UiModule, WeakWidgetId, WidgetId},
|
||||
util::{HashMap, Id},
|
||||
};
|
||||
|
||||
pub trait Event: Sized {
|
||||
type Module<Ctx: 'static>: EventModule<Self, Ctx>;
|
||||
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<W>,
|
||||
pub ui: &'a mut Ui,
|
||||
pub state: &'a mut Ctx,
|
||||
pub data: Data,
|
||||
}
|
||||
|
||||
pub trait EventFn<Ctx, Data>: Fn(EventCtx<Ctx, Data>) + 'static {}
|
||||
impl<F: Fn(EventCtx<Ctx, Data>) + 'static, Ctx, Data> EventFn<Ctx, Data> for F {}
|
||||
|
||||
pub trait WidgetEventFn<Ctx, Data, W>: Fn(EventIdCtx<Ctx, Data, W>) + 'static {}
|
||||
impl<F: Fn(EventIdCtx<Ctx, Data, W>) + 'static, Ctx, Data, W> WidgetEventFn<Ctx, Data, W> for F {}
|
||||
|
||||
pub trait DefaultEvent: Hash + Eq + 'static {
|
||||
type Data: Clone = ();
|
||||
}
|
||||
|
||||
impl<E: DefaultEvent> Event for E {
|
||||
type Module<Ctx: 'static> = DefaultEventModule<E, Ctx>;
|
||||
type Data = E::Data;
|
||||
}
|
||||
|
||||
pub trait EventModule<E: Event, Ctx>: UiModule + Default {
|
||||
fn register(&mut self, id: Id, event: E, f: impl EventFn<Ctx, E::Data>);
|
||||
fn run<'a>(
|
||||
&self,
|
||||
id: &Id,
|
||||
event: E,
|
||||
) -> Option<impl Fn(EventCtx<Ctx, E::Data>) + use<'a, Self, E, Ctx>>;
|
||||
}
|
||||
|
||||
type EventFnMap<Ctx, Data> = HashMap<Id, Vec<Rc<dyn EventFn<Ctx, Data>>>>;
|
||||
pub struct DefaultEventModule<E: Event, Ctx> {
|
||||
map: HashMap<E, EventFnMap<Ctx, <E as Event>::Data>>,
|
||||
}
|
||||
|
||||
impl<E: Event + 'static, Ctx: 'static> UiModule for DefaultEventModule<E, Ctx> {
|
||||
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<E: Event + Hash + Eq + 'static> HashableEvent for E {}
|
||||
|
||||
impl<E: HashableEvent, Ctx: 'static> EventModule<E, Ctx> for DefaultEventModule<E, Ctx> {
|
||||
fn register(&mut self, id: Id, event: E, f: impl EventFn<Ctx, <E as Event>::Data>) {
|
||||
self.map
|
||||
.entry(event)
|
||||
.or_default()
|
||||
.entry(id)
|
||||
.or_default()
|
||||
.push(Rc::new(f));
|
||||
}
|
||||
|
||||
fn run<'a>(
|
||||
&self,
|
||||
id: &Id,
|
||||
event: E,
|
||||
) -> Option<impl Fn(EventCtx<Ctx, E::Data>) + 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<Ctx, <E as Event>::Data>| {
|
||||
for f in &fs {
|
||||
f(EventCtx {
|
||||
ui: ctx.ui,
|
||||
state: ctx.state,
|
||||
data: ctx.data.clone(),
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: HashableEvent, Ctx: 'static> DefaultEventModule<E, Ctx> {
|
||||
pub fn run_all(&self, event: E, ctx: EventCtx<Ctx, E::Data>)
|
||||
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<E: Event + 'static, Ctx: 'static> Default for DefaultEventModule<E, Ctx> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
map: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ui {
|
||||
pub fn run_event<E: Event, Ctx: 'static, W>(
|
||||
&mut self,
|
||||
ctx: &mut Ctx,
|
||||
id: &WidgetId<W>,
|
||||
event: E,
|
||||
data: E::Data,
|
||||
) {
|
||||
if let Some(f) = self
|
||||
.data
|
||||
.modules
|
||||
.get_mut::<E::Module<Ctx>>()
|
||||
.run(&id.id(), event)
|
||||
{
|
||||
f(EventCtx {
|
||||
ui: self,
|
||||
state: ctx,
|
||||
data,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user