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}