nuit_core/state/
storage.rs1use std::{collections::HashMap, any::Any, cell::{RefCell, Cell}};
2
3use crate::{Animation, StateKey, Update};
4
5pub struct Storage {
7 state: RefCell<HashMap<StateKey, Box<dyn Any>>>,
8 changes: RefCell<HashMap<StateKey, Box<dyn Any>>>,
9 preapply: Cell<bool>,
10 update_callback: RefCell<Option<Box<dyn Fn(&Update)>>>,
11}
12
13impl Storage {
14 pub fn new() -> Self {
15 Self {
16 state: RefCell::new(HashMap::new()),
17 changes: RefCell::new(HashMap::new()),
18 preapply: Cell::new(false),
19 update_callback: RefCell::new(None),
20 }
21 }
22
23 pub(crate) fn initialize_if_needed<V>(&self, key: StateKey, value: impl FnOnce() -> V) where V: 'static {
24 if !self.state.borrow().contains_key(&key) {
25 self.state.borrow_mut().insert(key, Box::new(value()));
26 }
27 }
28
29 pub(crate) fn add_change<V>(&self, key: StateKey, value: V, animation: Option<Animation>) where V: 'static {
30 self.changes.borrow_mut().insert(key, Box::new(value));
31 self.fire_update_callback(&Update::new(animation));
32 }
33
34 pub(crate) fn get<T>(&self, key: &StateKey) -> T where T: Clone + 'static {
35 if self.preapply.get() && let Some(changed) = self.changes.borrow().get(key) {
36 changed.downcast_ref::<T>().cloned()
37 } else {
38 self.state.borrow()[key].downcast_ref::<T>().cloned()
39 }
40 .expect("State has invalid type")
41 }
42
43 pub(crate) fn with_preapplied_changes<T>(&self, action: impl FnOnce() -> T) -> T {
44 self.preapply.set(true);
45 let result = action();
46 self.preapply.set(false);
47 result
48 }
49
50 pub(crate) fn apply_changes(&self) {
51 let mut state = self.state.borrow_mut();
52 for (key, value) in self.changes.borrow_mut().drain() {
53 state.insert(key, value);
54 }
55 }
56
57 fn fire_update_callback(&self, update: &Update) {
58 if let Some(update_callback) = self.update_callback.borrow().as_ref() {
59 update_callback(&update);
60 }
61 }
62
63 pub fn set_update_callback(&self, update_callback: impl Fn(&Update) + 'static) {
64 *self.update_callback.borrow_mut() = Some(Box::new(update_callback));
65 }
66}