widget state
This commit is contained in:
@@ -17,6 +17,7 @@ mod event;
|
||||
mod input;
|
||||
mod render;
|
||||
mod sense;
|
||||
mod state;
|
||||
mod task;
|
||||
|
||||
pub use app::*;
|
||||
@@ -25,6 +26,7 @@ pub use event::*;
|
||||
pub use input::*;
|
||||
pub use render::*;
|
||||
pub use sense::*;
|
||||
pub use state::*;
|
||||
pub use task::*;
|
||||
|
||||
pub type Proxy<Event> = EventLoopProxy<Event>;
|
||||
@@ -98,6 +100,7 @@ pub struct DefaultRsc<State: 'static> {
|
||||
pub ui: UiData,
|
||||
pub events: EventManager<Self>,
|
||||
pub tasks: Tasks<Self>,
|
||||
pub state: WidgetState,
|
||||
_state: PhantomData<State>,
|
||||
}
|
||||
|
||||
@@ -109,11 +112,16 @@ impl<State> DefaultRsc<State> {
|
||||
ui: Default::default(),
|
||||
events: Default::default(),
|
||||
tasks,
|
||||
state: Default::default(),
|
||||
_state: Default::default(),
|
||||
},
|
||||
recv,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn create_state<T: 'static>(&mut self, id: impl IdLike, data: T) -> WeakState<T> {
|
||||
self.state.add(id.id(), data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<State> UiRsc for DefaultRsc<State> {
|
||||
@@ -158,6 +166,16 @@ impl<State: 'static> HasTasks for DefaultRsc<State> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<State: 'static> HasWidgetState for DefaultRsc<State> {
|
||||
fn widget_state(&self) -> &WidgetState {
|
||||
&self.state
|
||||
}
|
||||
|
||||
fn widget_state_mut(&mut self) -> &mut WidgetState {
|
||||
&mut self.state
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefaultApp<State: DefaultAppState> {
|
||||
rsc: DefaultRsc<State>,
|
||||
render: UiRenderState,
|
||||
@@ -289,3 +307,47 @@ impl<State: DefaultAppState> AppState for DefaultApp<State> {
|
||||
self.state.exit(&mut self.rsc, &mut self.render);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RscIdx<Rsc> {
|
||||
type Output;
|
||||
fn get(self, rsc: &Rsc) -> &Self::Output;
|
||||
fn get_mut(self, rsc: &mut Rsc) -> &mut Self::Output;
|
||||
}
|
||||
|
||||
impl<State: 'static, I: RscIdx<DefaultRsc<State>>> std::ops::Index<I> for DefaultRsc<State> {
|
||||
type Output = I::Output;
|
||||
|
||||
fn index(&self, index: I) -> &Self::Output {
|
||||
index.get(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<State: 'static, I: RscIdx<DefaultRsc<State>>> std::ops::IndexMut<I> for DefaultRsc<State> {
|
||||
fn index_mut(&mut self, index: I) -> &mut Self::Output {
|
||||
index.get_mut(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Widget, Rsc: UiRsc> RscIdx<Rsc> for WeakWidget<W> {
|
||||
type Output = W;
|
||||
|
||||
fn get(self, rsc: &Rsc) -> &Self::Output {
|
||||
&rsc.ui().widgets[self]
|
||||
}
|
||||
|
||||
fn get_mut(self, rsc: &mut Rsc) -> &mut Self::Output {
|
||||
&mut rsc.ui_mut().widgets[self]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static, Rsc: HasWidgetState> RscIdx<Rsc> for WeakState<T> {
|
||||
type Output = T;
|
||||
|
||||
fn get(self, rsc: &Rsc) -> &Self::Output {
|
||||
rsc.widget_state().get(self)
|
||||
}
|
||||
|
||||
fn get_mut(self, rsc: &mut Rsc) -> &mut Self::Output {
|
||||
rsc.widget_state_mut().get_mut(self)
|
||||
}
|
||||
}
|
||||
|
||||
67
src/default/state.rs
Normal file
67
src/default/state.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
use iris_core::{WidgetId, util::HashMap};
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
struct Key {
|
||||
id: WidgetId,
|
||||
ty: TypeId,
|
||||
i: usize,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WidgetState {
|
||||
counts: HashMap<(WidgetId, TypeId), usize>,
|
||||
map: HashMap<Key, Box<dyn Any>>,
|
||||
}
|
||||
|
||||
impl WidgetState {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
pub fn add<T: 'static>(&mut self, id: WidgetId, data: T) -> WeakState<T> {
|
||||
let ty = TypeId::of::<T>();
|
||||
let count = self.counts.entry((id, ty)).or_default();
|
||||
let key = Key { ty, i: *count, id };
|
||||
self.map.insert(key, Box::new(data));
|
||||
*count += 1;
|
||||
WeakState {
|
||||
key,
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
pub fn remove<T>(&mut self, state: WeakState<T>) {
|
||||
self.map.remove(&state.key);
|
||||
}
|
||||
pub fn get<T: 'static>(&self, state: WeakState<T>) -> &T {
|
||||
self.map.get(&state.key).unwrap().downcast_ref().unwrap()
|
||||
}
|
||||
pub fn get_mut<T: 'static>(&mut self, state: WeakState<T>) -> &mut T {
|
||||
self.map
|
||||
.get_mut(&state.key)
|
||||
.unwrap()
|
||||
.downcast_mut()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct WeakState<T> {
|
||||
key: Key,
|
||||
_pd: PhantomData<T>,
|
||||
}
|
||||
|
||||
pub trait HasWidgetState {
|
||||
fn widget_state(&self) -> &WidgetState;
|
||||
fn widget_state_mut(&mut self) -> &mut WidgetState;
|
||||
}
|
||||
|
||||
impl<'a, T: 'static> FnOnce<(&'a mut WidgetState,)> for WeakState<T> {
|
||||
type Output = &'a mut T;
|
||||
|
||||
extern "rust-call" fn call_once(self, (state,): (&'a mut WidgetState,)) -> Self::Output {
|
||||
state.get_mut(self)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user