1use std::{cell::RefCell, rc::Rc};
2
3use crate::{Animation, Binding, Storage};
4
5use super::StateKey;
6
7#[derive(Clone)]
9pub struct State<T> {
10 initial_value: T,
11 storage: RefCell<Option<Rc<Storage>>>,
12 key: RefCell<Option<StateKey>>,
13}
14
15impl<T> State<T> where T: 'static + Clone {
16 pub fn new(initial_value: impl Into<T>) -> Self {
17 Self {
18 initial_value: initial_value.into(),
19 storage: RefCell::new(None),
20 key: RefCell::new(None),
21 }
22 }
23
24 pub fn is_linked(&self) -> bool {
25 self.storage.borrow().is_some() && self.key.borrow().is_some()
26 }
27
28 pub fn link(&self, storage: Rc<Storage>, key: StateKey) {
29 *self.storage.borrow_mut() = Some(storage.clone());
30 *self.key.borrow_mut() = Some(key.clone());
31
32 storage.initialize_if_needed(key, || self.initial_value.clone());
33 }
34
35 pub fn get(&self) -> T {
36 let storage = self.storage.borrow();
37 let storage = storage.as_ref().expect("Storage not linked prior to get");
38 storage.get::<T>(self.key.borrow().as_ref().unwrap())
39 }
40
41 fn add_change(&self, value: impl Into<T>, animation: Option<Animation>) {
42 let storage = self.storage.borrow();
43 let storage = storage.as_ref().expect("Storage not linked prior to set");
44 storage.add_change(self.key.borrow().clone().unwrap(), value.into(), animation);
45 }
46
47 pub fn set(&self, value: impl Into<T>) {
48 self.add_change(value, None)
49 }
50
51 pub fn set_with(&self, animation: Animation, value: impl Into<T>) {
52 self.add_change(value, Some(animation))
53 }
54
55 pub fn binding(&self) -> Binding<T> {
56 let self1 = self.clone();
57 let self2 = self.clone();
58 Binding::new(
59 move || self1.get(),
60 move |value| self2.set(value),
61 )
62 }
63}
64
65impl<T> Default for State<T> where T: 'static + Default + Clone {
66 fn default() -> Self {
67 Self::new(T::default())
68 }
69}