raui_retained/
lib.rs

1use raui_core::{
2    Lifetime, LifetimeLazy, Managed, ValueReadAccess, ValueWriteAccess,
3    application::ChangeNotifier,
4    widget::{FnWidget, WidgetRef, component::WidgetComponent, context::*, node::WidgetNode},
5};
6use std::{
7    any::Any,
8    marker::PhantomData,
9    ops::{Deref, DerefMut},
10    ptr::NonNull,
11};
12
13#[allow(unused_variables)]
14pub trait ViewState: Any + Send + Sync {
15    fn on_mount(&mut self, context: WidgetMountOrChangeContext) {}
16    fn on_unmount(&mut self, context: WidgetUnmountContext) {}
17    fn on_change(&mut self, context: WidgetMountOrChangeContext) {}
18    fn on_render(&self, context: WidgetContext) -> WidgetNode;
19    fn as_any(&self) -> &dyn Any;
20    fn as_any_mut(&mut self) -> &mut dyn Any;
21}
22
23pub struct View<T: ViewState> {
24    inner: Box<dyn ViewState>,
25    lifetime: Box<Lifetime>,
26    _phantom: PhantomData<fn() -> T>,
27}
28
29impl<T: ViewState + Default> Default for View<T> {
30    fn default() -> Self {
31        Self::new(T::default())
32    }
33}
34
35impl<T: ViewState> View<T> {
36    pub fn new(state: T) -> Self
37    where
38        T: 'static,
39    {
40        Self {
41            inner: Box::new(state),
42            lifetime: Default::default(),
43            _phantom: Default::default(),
44        }
45    }
46
47    pub fn into_inner(self) -> Box<dyn ViewState> {
48        self.inner
49    }
50
51    pub fn as_dyn(&'_ self) -> Option<ValueReadAccess<'_, dyn ViewState>> {
52        self.lifetime.read(&*self.inner)
53    }
54
55    pub fn as_dyn_mut(&'_ mut self) -> Option<ValueWriteAccess<'_, dyn ViewState>> {
56        self.lifetime.write(&mut *self.inner)
57    }
58
59    pub fn read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
60        self.lifetime.read(self.inner.as_any().downcast_ref::<T>()?)
61    }
62
63    pub fn write(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
64        self.lifetime
65            .write(self.inner.as_any_mut().downcast_mut::<T>()?)
66    }
67
68    pub fn lazy(&self) -> LazyView<T> {
69        unsafe {
70            let ptr = self.inner.as_any().downcast_ref::<T>().unwrap() as *const T as *mut T;
71            LazyView {
72                inner: NonNull::new_unchecked(ptr),
73                lifetime: self.lifetime.lazy(),
74            }
75        }
76    }
77
78    pub fn component(&self) -> WidgetComponent {
79        WidgetComponent::new(self.widget(), std::any::type_name::<Self>())
80    }
81
82    pub fn widget(&self) -> FnWidget {
83        let this = self.lazy();
84        FnWidget::closure(move |context| {
85            let this_mount = this.clone();
86            let this_unmount = this.clone();
87            let this_change = this.clone();
88            context.life_cycle.mount(move |context| {
89                if let Some(mut this) = this_mount.write() {
90                    this.on_mount(context);
91                }
92            });
93            context.life_cycle.unmount(move |context| {
94                if let Some(mut this) = this_unmount.write() {
95                    this.on_unmount(context);
96                }
97            });
98            context.life_cycle.change(move |context| {
99                if let Some(mut this) = this_change.write() {
100                    this.on_change(context);
101                }
102            });
103            this.write()
104                .map(|this| this.on_render(context))
105                .unwrap_or_default()
106        })
107    }
108}
109
110pub struct LazyView<T: ViewState> {
111    inner: NonNull<T>,
112    lifetime: LifetimeLazy,
113}
114
115unsafe impl<T: ViewState> Send for LazyView<T> {}
116unsafe impl<T: ViewState> Sync for LazyView<T> {}
117
118impl<T: ViewState> Clone for LazyView<T> {
119    fn clone(&self) -> Self {
120        Self {
121            inner: self.inner,
122            lifetime: self.lifetime.clone(),
123        }
124    }
125}
126
127impl<T: ViewState> LazyView<T> {
128    pub fn as_dyn(&'_ self) -> Option<ValueReadAccess<'_, dyn ViewState>> {
129        unsafe { self.lifetime.read(self.inner.as_ref()) }
130    }
131
132    pub fn as_dyn_mut(&'_ self) -> Option<ValueWriteAccess<'_, dyn ViewState>> {
133        unsafe { self.lifetime.write(self.inner.as_ptr().as_mut()?) }
134    }
135
136    pub fn read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
137        unsafe { self.lifetime.read(self.inner.as_ref()) }
138    }
139
140    pub fn write(&'_ self) -> Option<ValueWriteAccess<'_, T>> {
141        unsafe { self.lifetime.write(self.inner.as_ptr().as_mut()?) }
142    }
143}
144
145pub struct ViewValue<T> {
146    inner: T,
147    notifier: Option<ChangeNotifier>,
148    id: WidgetRef,
149}
150
151impl<T> ViewValue<T> {
152    pub fn new(value: T) -> Self {
153        Self {
154            inner: value,
155            notifier: None,
156            id: Default::default(),
157        }
158    }
159
160    pub fn with_notifier(mut self, notifier: ChangeNotifier) -> Self {
161        self.bind_notifier(notifier);
162        self
163    }
164
165    pub fn bind_notifier(&mut self, notifier: ChangeNotifier) {
166        if self.notifier.is_none()
167            && let Some(id) = self.id.read()
168        {
169            notifier.notify(id);
170        }
171        self.notifier = Some(notifier);
172    }
173
174    pub fn unbind_notifier(&mut self) {
175        self.notifier = None;
176    }
177
178    pub fn bound_notifier(&self) -> Option<&ChangeNotifier> {
179        self.notifier.as_ref()
180    }
181
182    pub fn widget_ref(&self) -> WidgetRef {
183        self.id.clone()
184    }
185}
186
187impl<T> Deref for ViewValue<T> {
188    type Target = T;
189
190    fn deref(&self) -> &Self::Target {
191        &self.inner
192    }
193}
194
195impl<T> DerefMut for ViewValue<T> {
196    fn deref_mut(&mut self) -> &mut Self::Target {
197        if let Some(notifier) = self.notifier.as_ref()
198            && let Some(id) = self.id.read()
199        {
200            notifier.notify(id);
201        }
202        &mut self.inner
203    }
204}
205
206pub struct SharedView<T: ViewState> {
207    inner: Managed<Option<View<T>>>,
208}
209
210impl<T: ViewState> Default for SharedView<T> {
211    fn default() -> Self {
212        Self {
213            inner: Default::default(),
214        }
215    }
216}
217
218impl<T: ViewState> SharedView<T> {
219    pub fn new(view: View<T>) -> Self {
220        Self {
221            inner: Managed::new(Some(view)),
222        }
223    }
224
225    pub fn replace(&mut self, view: View<T>) {
226        if let Some(mut inner) = self.inner.write() {
227            *inner = Some(view);
228        }
229    }
230
231    pub fn clear(&mut self) {
232        if let Some(mut inner) = self.inner.write() {
233            *inner = None;
234        }
235    }
236
237    pub fn read(&'_ self) -> Option<ValueReadAccess<'_, View<T>>> {
238        self.inner.read()?.remap(|inner| inner.as_ref()).ok()
239    }
240
241    pub fn write(&'_ mut self) -> Option<ValueWriteAccess<'_, View<T>>> {
242        self.inner.write()?.remap(|inner| inner.as_mut()).ok()
243    }
244}
245
246impl<T: ViewState> ViewState for SharedView<T> {
247    fn on_render(&self, context: WidgetContext) -> WidgetNode {
248        self.inner
249            .read()
250            .and_then(|inner| {
251                inner
252                    .as_ref()
253                    .map(|inner| inner.component().key(context.key).into())
254            })
255            .unwrap_or_default()
256    }
257
258    fn as_any(&self) -> &dyn Any {
259        self
260    }
261
262    fn as_any_mut(&mut self) -> &mut dyn Any {
263        self
264    }
265}