embedded_ui/
state.rs

1use alloc::{boxed::Box, vec::Vec};
2use core::{
3    any::{Any, TypeId},
4    borrow::Borrow,
5};
6
7use crate::{event::Event, render::Renderer, widget::Widget};
8
9// TODO: Not just any, but specific "State" trait with Default, etc.??? Is it possible
10
11pub enum State {
12    None,
13    Some(Box<dyn Any>),
14}
15
16impl State {
17    pub fn new<T: 'static>(state: T) -> Self {
18        Self::Some(Box::new(state))
19    }
20
21    pub fn downcast_ref<T: 'static>(&self) -> &T {
22        match self {
23            State::None => panic!("Downcast of stateless state"),
24            State::Some(state) => state.downcast_ref().expect("Downcast state"),
25        }
26    }
27
28    pub fn downcast_mut<T: 'static>(&mut self) -> &mut T {
29        match self {
30            State::None => panic!("Downcast of stateless state"),
31            State::Some(state) => state.downcast_mut().expect("Downcast mut state"),
32        }
33    }
34
35    pub fn reset<T: 'static>(&mut self)
36    where
37        T: Default,
38    {
39        match self {
40            State::None => panic!("Reset of stateless state"),
41            State::Some(state) => {
42                *state.downcast_mut::<T>().expect("Downcast reset state") = T::default();
43            },
44        }
45    }
46}
47
48#[derive(Clone, Copy, PartialEq)]
49pub struct StateTag(pub TypeId);
50
51impl StateTag {
52    pub fn stateless() -> Self {
53        Self::of::<()>()
54    }
55
56    pub fn of<T: 'static>() -> Self {
57        Self(TypeId::of::<T>())
58    }
59}
60
61pub struct StateNode {
62    pub tag: StateTag,
63    pub state: State,
64    pub children: Vec<StateNode>,
65}
66
67impl StateNode {
68    pub fn stateless() -> Self {
69        Self { tag: StateTag::stateless(), state: State::None, children: vec![] }
70    }
71
72    pub fn new<'a, Message, R: Renderer, E: Event, S>(
73        widget: impl Borrow<dyn Widget<Message, R, E, S> + 'a>,
74    ) -> Self {
75        let widget = widget.borrow();
76
77        Self { tag: widget.state_tag(), state: widget.state(), children: widget.state_children() }
78    }
79
80    pub fn get<T: 'static>(&self) -> &T {
81        self.state.downcast_ref()
82    }
83
84    pub fn get_mut<T: 'static>(&mut self) -> &mut T {
85        self.state.downcast_mut()
86    }
87
88    pub fn reset<T: 'static>(&mut self)
89    where
90        T: Default,
91    {
92        self.state.reset::<T>()
93    }
94}