misty_vm/
views.rs

1use std::{any::Any, fmt::Debug};
2
3use crate::{
4    client::MistyClientInner,
5    states::{MistyStateManager, RefMistyStates},
6};
7
8pub struct BoxedView {
9    inner: Box<dyn Any + Send + Sync>,
10}
11
12impl BoxedView {
13    pub fn new<R: Any + Default + Send + Sync + 'static>(v: R) -> Self {
14        Self { inner: Box::new(v) }
15    }
16
17    pub fn cast<R: Any + Default + Send + Sync + 'static>(self) -> R {
18        let r: Box<R> = self.inner.downcast().unwrap();
19        return *r;
20    }
21}
22
23pub trait MistyViewModel<R, S> {
24    fn update(&self, states: S, s: &mut R);
25}
26
27impl<R, S, F> MistyViewModel<R, S> for F
28where
29    F: Fn(S, &mut R),
30{
31    fn update(&self, states: S, s: &mut R) {
32        self(states, s)
33    }
34}
35
36pub(crate) trait ErasedMistyViewModel<R> {
37    fn should_update(&self, cx: &MistyStateManager) -> bool;
38    fn update(&self, cx: &MistyStateManager, s: &mut R);
39}
40
41struct BoxedErasedMistyViewModel<R> {
42    pub(crate) inner: Box<dyn ErasedMistyViewModel<R> + Send + Sync>,
43}
44struct BoxedMistyViewModel<R, S> {
45    inner: Box<dyn MistyViewModel<R, S> + Send + Sync>,
46}
47
48impl<R, S> Debug for BoxedMistyViewModel<R, S> {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.debug_struct("BoxedMistyViewModel").finish()
51    }
52}
53
54impl<R> Debug for BoxedErasedMistyViewModel<R> {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        f.debug_struct("BoxedErasedMistyViewModel").finish()
57    }
58}
59
60impl<R, S> ErasedMistyViewModel<R> for BoxedMistyViewModel<R, S>
61where
62    S: RefMistyStates,
63{
64    fn should_update(&self, cx: &MistyStateManager) -> bool {
65        return cx.contains_updated_state(&S::state_ids());
66    }
67    fn update(&self, cx: &MistyStateManager, s: &mut R) {
68        S::extract_refs(cx, |states| {
69            self.inner.update(states, s);
70        });
71    }
72}
73
74impl<R, S> BoxedMistyViewModel<R, S> {
75    pub fn new<T: MistyViewModel<R, S> + Send + Sync + 'static>(view_model: T) -> Self {
76        Self {
77            inner: Box::new(view_model),
78        }
79    }
80}
81
82pub struct MistyViewModelManager<R> {
83    models: Vec<BoxedErasedMistyViewModel<R>>,
84}
85
86#[derive(Default)]
87pub struct MistyViewModelManagerBuilder<R> {
88    models: Vec<BoxedErasedMistyViewModel<R>>,
89}
90
91impl<R> Debug for MistyViewModelManager<R> {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        f.debug_struct("MistyViewModelManager")
94            .field("models", &self.models)
95            .finish()
96    }
97}
98
99impl<R> MistyViewModelManagerBuilder<R> {
100    pub fn register<'a, S, V>(mut self, view_model: V) -> Self
101    where
102        S: RefMistyStates + 'static,
103        V: MistyViewModel<R, S> + Send + Sync + 'static,
104        R: 'static,
105    {
106        self.models.push(BoxedErasedMistyViewModel {
107            inner: Box::new(BoxedMistyViewModel::new(view_model)),
108        });
109        self
110    }
111
112    pub fn build(self) -> MistyViewModelManager<R> {
113        MistyViewModelManager {
114            models: self.models,
115        }
116    }
117}
118
119pub(crate) trait ViewNotifier: Debug {
120    fn build_view(&self, inner: &MistyClientInner) -> BoxedView;
121}
122
123impl<R: Default> MistyViewModelManager<R> {
124    pub fn builder() -> MistyViewModelManagerBuilder<R> {
125        Default::default()
126    }
127}
128
129impl<R: Any + Default + Send + Sync + 'static> ViewNotifier for MistyViewModelManager<R> {
130    fn build_view(&self, inner: &MistyClientInner) -> BoxedView {
131        let mut s = R::default();
132        for model in self.models.iter() {
133            if model.inner.should_update(&inner.state_manager) {
134                model.inner.update(&inner.state_manager, &mut s);
135            }
136        }
137
138        BoxedView::new(s)
139    }
140}