better global state structure?

This commit is contained in:
2025-12-19 21:54:48 -05:00
parent 30bc55c78e
commit bae17235c6
23 changed files with 335 additions and 230 deletions

View File

@@ -1,7 +1,6 @@
use crate::{HasEvents, HasState, HasUi, Ui, Widget, WidgetRef};
use std::ops::{Deref, DerefMut};
use crate::{HasUi, Ui, Widget, WidgetRef};
pub struct EventCtx<'a, State, Data> {
pub state: &'a mut State,
pub data: &'a mut Data,
@@ -14,21 +13,47 @@ pub struct EventIdCtx<'a, State, Data, W: ?Sized> {
}
impl<State: HasUi, Data, W: ?Sized> Deref for EventIdCtx<'_, State, Data, W> {
type Target = Ui;
type Target = State;
fn deref(&self) -> &Self::Target {
self.state.ui_ref()
self.state
}
}
impl<State: HasUi, Data, W: ?Sized> DerefMut for EventIdCtx<'_, State, Data, W> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.state.ui()
self.state
}
}
impl<'a, State: HasUi + 'static, Data, W: Widget> EventIdCtx<'a, State, Data, W> {
impl<'a, State: HasUi, Data, W: Widget> EventIdCtx<'a, State, Data, W> {
pub fn widget(&mut self) -> &mut W {
&mut self.state.ui()[self.widget]
&mut self.state.get_mut()[self.widget]
}
}
impl<State: HasUi, Data, W: Widget> HasUi for EventIdCtx<'_, State, Data, W> {
fn get(&self) -> &Ui {
self.state.ui()
}
fn get_mut(&mut self) -> &mut Ui {
self.state.ui_mut()
}
}
impl<State: HasUi, Data, W: Widget> HasState for EventIdCtx<'_, State, Data, W> {
type State = State;
}
impl<State: HasEvents<State = State>, Data, W: Widget> HasEvents
for EventIdCtx<'_, State, Data, W>
{
fn get(&self) -> &super::EventManager<Self::State> {
self.state.events()
}
fn get_mut(&mut self) -> &mut super::EventManager<Self::State> {
self.state.events_mut()
}
}

View File

@@ -1,6 +1,6 @@
use crate::{
ActiveData, Event, EventCtx, EventFn, EventLike, HasRsc, HasUi, IdLike, LayerId, WidgetData,
WidgetId,
ActiveData, Event, EventCtx, EventFn, EventIdCtx, EventLike, IdLike, LayerId, Widget,
WidgetData, WidgetEventFn, WidgetId, WidgetRef,
util::{HashMap, TypeMap},
};
use std::{any::TypeId, rc::Rc};
@@ -22,11 +22,11 @@ impl<State: 'static> EventManager<State> {
self.types.type_or_default()
}
pub fn register<I: IdLike, E: EventLike>(
pub fn register<W: Widget + ?Sized, E: EventLike>(
&mut self,
id: I,
id: WidgetRef<W>,
event: E,
f: impl for<'a> EventFn<State, <E::Event as Event>::Data<'a>>,
f: impl for<'a> WidgetEventFn<State, <E::Event as Event>::Data<'a>, W>,
) {
self.get_type::<E>().register(id, event, f);
}
@@ -106,17 +106,23 @@ impl<State, E: Event> Default for TypeEventManager<State, E> {
}
impl<State: 'static, E: Event> TypeEventManager<State, E> {
fn register(
fn register<W: Widget + ?Sized>(
&mut self,
id: impl IdLike,
widget: WidgetRef<W>,
event: impl EventLike<Event = E>,
f: impl for<'a> EventFn<State, E::Data<'a>>,
f: impl for<'a> WidgetEventFn<State, E::Data<'a>, W>,
) {
let event = event.into_event();
self.map
.entry(id.id())
.or_default()
.push((event, Rc::new(f)));
self.map.entry(widget.id()).or_default().push((
event,
Rc::new(move |ctx| {
f(&mut EventIdCtx {
widget,
state: ctx.state,
data: ctx.data,
});
}),
));
}
pub fn run_fn<'a>(
@@ -127,7 +133,7 @@ impl<State: 'static, E: Event> TypeEventManager<State, E> {
move |ctx| {
for (e, f) in fs {
if e.should_run(ctx.data) {
f(EventCtx {
f(&mut EventCtx {
state: ctx.state,
data: ctx.data,
})
@@ -136,27 +142,3 @@ impl<State: 'static, E: Event> TypeEventManager<State, E> {
}
}
}
pub trait HasEvents: Sized {
type State: HasRsc<Rsc = Self>;
fn events(&mut self) -> &mut EventManager<Self::State>;
fn register_event<I: IdLike, E: EventLike>(
&mut self,
id: I,
event: E,
f: impl for<'a> EventFn<Self::State, <E::Event as Event>::Data<'a>>,
) where
Self: HasUi,
{
let id = id.id();
self.events().register(id, event, f);
self.ui()
.widgets
.data_mut(id)
.unwrap()
.event_mgrs
.insert(EventManager::<Self::State>::type_key::<E>());
}
}

View File

@@ -28,11 +28,14 @@ impl<E: Event> EventLike for E {
}
}
pub trait EventFn<State, Data>: Fn(EventCtx<State, Data>) + 'static {}
impl<State, F: Fn(EventCtx<State, Data>) + 'static, Data> EventFn<State, Data> for F {}
pub trait EventFn<State, Data>: Fn(&mut EventCtx<State, Data>) + 'static {}
impl<State, F: Fn(&mut EventCtx<State, Data>) + 'static, Data> EventFn<State, Data> for F {}
pub trait WidgetEventFn<State, Data, W: ?Sized>: Fn(EventIdCtx<State, Data, W>) + 'static {}
impl<State, F: Fn(EventIdCtx<State, Data, W>) + 'static, Data, W: ?Sized>
pub trait WidgetEventFn<State, Data, W: ?Sized>:
Fn(&mut EventIdCtx<State, Data, W>) + 'static
{
}
impl<State, F: Fn(&mut EventIdCtx<State, Data, W>) + 'static, Data, W: ?Sized>
WidgetEventFn<State, Data, W> for F
{
}

View File

@@ -1,29 +1,47 @@
use crate::{Event, EventCtx, EventLike, EventManager, HasEvents, HasUi, IdLike};
use crate::{
Event, EventCtx, EventLike, EventManager, HasUi, IdLike, Widget, WidgetEventFn, WidgetRef,
};
pub trait HasRsc: Sized + 'static {
type Rsc: HasEvents<State = Self> + HasUi;
fn rsc(&self) -> &Self::Rsc;
fn rsc_mut(&mut self) -> &mut Self::Rsc;
pub trait HasState {
type State: HasUi;
}
fn run_event<E: EventLike>(&mut self, id: impl IdLike, data: &mut <E::Event as Event>::Data<'_>)
where
Self: 'static,
pub trait HasEvents: Sized + HasState + HasUi {
fn get(&self) -> &EventManager<Self::State>;
fn get_mut(&mut self) -> &mut EventManager<Self::State>;
fn events(&self) -> &EventManager<Self::State> {
HasEvents::get(self)
}
fn events_mut(&mut self) -> &mut EventManager<Self::State> {
HasEvents::get_mut(self)
}
fn register_event<W: Widget + ?Sized, E: EventLike>(
&mut self,
id: WidgetRef<W>,
event: E,
f: impl for<'a> WidgetEventFn<Self::State, <E::Event as Event>::Data<'a>, W>,
) where
Self::State: 'static,
{
let f = self.rsc_mut().events().get_type::<E>().run_fn(id);
self.events_mut().register(id, event, f);
self.ui_mut()
.widgets
.data_mut(id)
.unwrap()
.event_mgrs
.insert(EventManager::<Self::State>::type_key::<E>());
}
}
pub trait RunEvents: HasEvents + HasState<State = Self> + 'static {
fn run_event<E: EventLike>(
&mut self,
id: impl IdLike,
data: &mut <E::Event as Event>::Data<'_>,
) {
let f = self.events_mut().get_type::<E>().run_fn(id);
f(EventCtx { state: self, data })
}
fn events(&mut self) -> &mut EventManager<Self> {
self.rsc_mut().events()
}
}
impl<R: HasRsc> HasUi for R {
fn ui_ref(&self) -> &crate::Ui {
self.rsc().ui_ref()
}
fn ui(&mut self) -> &mut crate::Ui {
self.rsc_mut().ui()
}
}
impl<T: HasEvents + HasState<State = Self> + 'static> RunEvents for T {}

View File

@@ -42,9 +42,25 @@ pub struct Ui {
resized: bool,
}
pub trait HasUi: Sized + 'static {
fn ui_ref(&self) -> &Ui;
fn ui(&mut self) -> &mut Ui;
pub trait HasUi: Sized {
fn get(&self) -> &Ui;
fn get_mut(&mut self) -> &mut Ui;
fn ui(&self) -> &Ui {
self.get()
}
fn ui_mut(&mut self) -> &mut Ui {
self.get_mut()
}
}
impl HasUi for Ui {
fn get(&self) -> &Ui {
self
}
fn get_mut(&mut self) -> &mut Ui {
self
}
}
impl Ui {

View File

@@ -1,7 +1,7 @@
use std::{marker::Unsize, mem::MaybeUninit, ops::CoerceUnsized, sync::mpsc::Sender};
use crate::{
Widget,
HasUi, Widget,
util::{RefCounter, SlotId},
};
@@ -143,3 +143,11 @@ impl<W> std::fmt::Debug for WidgetHandle<W> {
self.id.fmt(f)
}
}
impl<'a, W: Widget + 'a, State: HasUi> FnOnce<(&'a mut State,)> for WidgetRef<W> {
type Output = &'a mut W;
extern "rust-call" fn call_once(self, args: (&'a mut State,)) -> Self::Output {
&mut args.0.ui_mut()[self]
}
}

View File

@@ -19,7 +19,7 @@ pub trait WidgetLike<State: 'static + HasUi, Tag>: Sized {
}
fn set_root(self, state: &mut State) {
state.ui().root = Some(self.add(state));
state.get_mut().root = Some(self.add(state));
}
fn handles(self, state: &mut State) -> WidgetHandles<Self::Widget> {

View File

@@ -7,15 +7,15 @@ use super::*;
pub struct ArrTag;
pub struct WidgetTag;
impl<State: HasUi, W: Widget> WidgetLike<State, WidgetTag> for W {
impl<State: HasUi + 'static, W: Widget> WidgetLike<State, WidgetTag> for W {
type Widget = W;
fn add(self, state: &mut State) -> WidgetHandle<W> {
state.ui().add_widget(self)
state.get_mut().add_widget(self)
}
}
pub struct FnTag;
impl<State: HasUi, W: Widget, F: FnOnce(&mut State) -> W> WidgetLike<State, FnTag> for F {
impl<State: HasUi + 'static, W: Widget, F: FnOnce(&mut State) -> W> WidgetLike<State, FnTag> for F {
type Widget = W;
fn add(self, state: &mut State) -> WidgetHandle<W> {
self(state).add(state)
@@ -23,8 +23,8 @@ impl<State: HasUi, W: Widget, F: FnOnce(&mut State) -> W> WidgetLike<State, FnTa
}
pub struct IdTag;
impl<State: HasUi, W: ?Sized + Widget + Unsize<dyn Widget> + 'static> WidgetLike<State, IdTag>
for WidgetHandle<W>
impl<State: HasUi + 'static, W: ?Sized + Widget + Unsize<dyn Widget> + 'static>
WidgetLike<State, IdTag> for WidgetHandle<W>
{
type Widget = W;
fn add(self, _: &mut State) -> WidgetHandle<W> {
@@ -34,7 +34,7 @@ impl<State: HasUi, W: ?Sized + Widget + Unsize<dyn Widget> + 'static> WidgetLike
pub struct IdFnTag;
impl<
State: HasUi,
State: HasUi + 'static,
W: ?Sized + Widget + Unsize<dyn Widget> + 'static,
F: FnOnce(&mut State) -> WidgetHandle<W>,
> WidgetLike<State, IdFnTag> for F