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}