68 lines
1.6 KiB
Rust
68 lines
1.6 KiB
Rust
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)
|
|
}
|
|
}
|