1use crate::{
2 AnyBox, AnyElement, AnyModel, AppContext, AvailableSpace, BorrowWindow, Bounds, Component,
3 Element, ElementId, EntityId, LayoutId, Model, Pixels, Size, ViewContext, VisualContext,
4 WeakModel, WindowContext,
5};
6use anyhow::{Context, Result};
7use std::{any::TypeId, marker::PhantomData, sync::Arc};
8
9pub trait Render: 'static + Sized {
10 type Element: Element<Self> + 'static + Send;
11
12 fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element;
13}
14
15pub struct View<V> {
16 pub(crate) model: Model<V>,
17}
18
19impl<V: Render> View<V> {
20 pub fn into_any(self) -> AnyView {
21 AnyView(Arc::new(self))
22 }
23}
24
25impl<V: 'static> View<V> {
26 pub fn downgrade(&self) -> WeakView<V> {
27 WeakView {
28 model: self.model.downgrade(),
29 }
30 }
31
32 pub fn update<C, R>(
33 &self,
34 cx: &mut C,
35 f: impl FnOnce(&mut V, &mut C::ViewContext<'_, '_, V>) -> R,
36 ) -> C::Result<R>
37 where
38 C: VisualContext,
39 {
40 cx.update_view(self, f)
41 }
42
43 pub fn read<'a>(&self, cx: &'a AppContext) -> &'a V {
44 self.model.read(cx)
45 }
46}
47
48impl<V> Clone for View<V> {
49 fn clone(&self) -> Self {
50 Self {
51 model: self.model.clone(),
52 }
53 }
54}
55
56impl<V: Render, ParentViewState: 'static> Component<ParentViewState> for View<V> {
57 fn render(self) -> AnyElement<ParentViewState> {
58 AnyElement::new(EraseViewState {
59 view: self,
60 parent_view_state_type: PhantomData,
61 })
62 }
63}
64
65impl<V> Element<()> for View<V>
66where
67 V: Render,
68{
69 type ElementState = AnyElement<V>;
70
71 fn id(&self) -> Option<crate::ElementId> {
72 Some(ElementId::View(self.model.entity_id))
73 }
74
75 fn initialize(
76 &mut self,
77 _: &mut (),
78 _: Option<Self::ElementState>,
79 cx: &mut ViewContext<()>,
80 ) -> Self::ElementState {
81 self.update(cx, |state, cx| {
82 let mut any_element = AnyElement::new(state.render(cx));
83 any_element.initialize(state, cx);
84 any_element
85 })
86 }
87
88 fn layout(
89 &mut self,
90 _: &mut (),
91 element: &mut Self::ElementState,
92 cx: &mut ViewContext<()>,
93 ) -> LayoutId {
94 self.update(cx, |state, cx| element.layout(state, cx))
95 }
96
97 fn paint(
98 &mut self,
99 _: Bounds<Pixels>,
100 _: &mut (),
101 element: &mut Self::ElementState,
102 cx: &mut ViewContext<()>,
103 ) {
104 self.update(cx, |state, cx| element.paint(state, cx))
105 }
106}
107
108pub struct WeakView<V> {
109 pub(crate) model: WeakModel<V>,
110}
111
112impl<V: 'static> WeakView<V> {
113 pub fn upgrade(&self) -> Option<View<V>> {
114 let model = self.model.upgrade()?;
115 Some(View { model })
116 }
117
118 pub fn update<R>(
119 &self,
120 cx: &mut WindowContext,
121 f: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
122 ) -> Result<R> {
123 let view = self.upgrade().context("error upgrading view")?;
124 Ok(view.update(cx, f))
125 }
126}
127
128impl<V> Clone for WeakView<V> {
129 fn clone(&self) -> Self {
130 Self {
131 model: self.model.clone(),
132 }
133 }
134}
135
136struct EraseViewState<V, ParentV> {
137 view: View<V>,
138 parent_view_state_type: PhantomData<ParentV>,
139}
140
141unsafe impl<V, ParentV> Send for EraseViewState<V, ParentV> {}
142
143impl<V: Render, ParentV: 'static> Component<ParentV> for EraseViewState<V, ParentV> {
144 fn render(self) -> AnyElement<ParentV> {
145 AnyElement::new(self)
146 }
147}
148
149impl<V: Render, ParentV: 'static> Element<ParentV> for EraseViewState<V, ParentV> {
150 type ElementState = AnyBox;
151
152 fn id(&self) -> Option<crate::ElementId> {
153 Element::id(&self.view)
154 }
155
156 fn initialize(
157 &mut self,
158 _: &mut ParentV,
159 _: Option<Self::ElementState>,
160 cx: &mut ViewContext<ParentV>,
161 ) -> Self::ElementState {
162 ViewObject::initialize(&mut self.view, cx)
163 }
164
165 fn layout(
166 &mut self,
167 _: &mut ParentV,
168 element: &mut Self::ElementState,
169 cx: &mut ViewContext<ParentV>,
170 ) -> LayoutId {
171 ViewObject::layout(&mut self.view, element, cx)
172 }
173
174 fn paint(
175 &mut self,
176 bounds: Bounds<Pixels>,
177 _: &mut ParentV,
178 element: &mut Self::ElementState,
179 cx: &mut ViewContext<ParentV>,
180 ) {
181 ViewObject::paint(&mut self.view, bounds, element, cx)
182 }
183}
184
185trait ViewObject: Send + Sync {
186 fn entity_type(&self) -> TypeId;
187 fn entity_id(&self) -> EntityId;
188 fn model(&self) -> AnyModel;
189 fn initialize(&self, cx: &mut WindowContext) -> AnyBox;
190 fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId;
191 fn paint(&self, bounds: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext);
192}
193
194impl<V> ViewObject for View<V>
195where
196 V: Render,
197{
198 fn entity_type(&self) -> TypeId {
199 TypeId::of::<V>()
200 }
201
202 fn entity_id(&self) -> EntityId {
203 self.model.entity_id
204 }
205
206 fn model(&self) -> AnyModel {
207 self.model.clone().into_any()
208 }
209
210 fn initialize(&self, cx: &mut WindowContext) -> AnyBox {
211 cx.with_element_id(self.entity_id(), |_global_id, cx| {
212 self.update(cx, |state, cx| {
213 let mut any_element = Box::new(AnyElement::new(state.render(cx)));
214 any_element.initialize(state, cx);
215 any_element
216 })
217 })
218 }
219
220 fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId {
221 cx.with_element_id(self.entity_id(), |_global_id, cx| {
222 self.update(cx, |state, cx| {
223 let element = element.downcast_mut::<AnyElement<V>>().unwrap();
224 element.layout(state, cx)
225 })
226 })
227 }
228
229 fn paint(&self, _: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext) {
230 cx.with_element_id(self.entity_id(), |_global_id, cx| {
231 self.update(cx, |state, cx| {
232 let element = element.downcast_mut::<AnyElement<V>>().unwrap();
233 element.paint(state, cx);
234 });
235 });
236 }
237}
238
239#[derive(Clone)]
240pub struct AnyView(Arc<dyn ViewObject>);
241
242impl AnyView {
243 pub fn downcast<V: 'static + Send>(self) -> Option<View<V>> {
244 self.0.model().downcast().map(|model| View { model })
245 }
246
247 pub(crate) fn entity_type(&self) -> TypeId {
248 self.0.entity_type()
249 }
250
251 pub(crate) fn draw(&self, available_space: Size<AvailableSpace>, cx: &mut WindowContext) {
252 let mut rendered_element = self.0.initialize(cx);
253 let layout_id = self.0.layout(&mut rendered_element, cx);
254 cx.window
255 .layout_engine
256 .compute_layout(layout_id, available_space);
257 let bounds = cx.window.layout_engine.layout_bounds(layout_id);
258 self.0.paint(bounds, &mut rendered_element, cx);
259 }
260}
261
262impl<ParentV: 'static> Component<ParentV> for AnyView {
263 fn render(self) -> AnyElement<ParentV> {
264 AnyElement::new(EraseAnyViewState {
265 view: self,
266 parent_view_state_type: PhantomData,
267 })
268 }
269}
270
271impl Element<()> for AnyView {
272 type ElementState = AnyBox;
273
274 fn id(&self) -> Option<crate::ElementId> {
275 Some(ElementId::View(self.0.entity_id()))
276 }
277
278 fn initialize(
279 &mut self,
280 _: &mut (),
281 _: Option<Self::ElementState>,
282 cx: &mut ViewContext<()>,
283 ) -> Self::ElementState {
284 self.0.initialize(cx)
285 }
286
287 fn layout(
288 &mut self,
289 _: &mut (),
290 element: &mut Self::ElementState,
291 cx: &mut ViewContext<()>,
292 ) -> LayoutId {
293 self.0.layout(element, cx)
294 }
295
296 fn paint(
297 &mut self,
298 bounds: Bounds<Pixels>,
299 _: &mut (),
300 element: &mut AnyBox,
301 cx: &mut ViewContext<()>,
302 ) {
303 self.0.paint(bounds, element, cx)
304 }
305}
306
307struct EraseAnyViewState<ParentViewState> {
308 view: AnyView,
309 parent_view_state_type: PhantomData<ParentViewState>,
310}
311
312unsafe impl<ParentV> Send for EraseAnyViewState<ParentV> {}
313
314impl<ParentV: 'static> Component<ParentV> for EraseAnyViewState<ParentV> {
315 fn render(self) -> AnyElement<ParentV> {
316 AnyElement::new(self)
317 }
318}
319
320impl<T, E> Render for T
321where
322 T: 'static + FnMut(&mut WindowContext) -> E,
323 E: 'static + Send + Element<T>,
324{
325 type Element = E;
326
327 fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
328 (self)(cx)
329 }
330}
331
332impl<ParentV: 'static> Element<ParentV> for EraseAnyViewState<ParentV> {
333 type ElementState = AnyBox;
334
335 fn id(&self) -> Option<crate::ElementId> {
336 Element::id(&self.view)
337 }
338
339 fn initialize(
340 &mut self,
341 _: &mut ParentV,
342 _: Option<Self::ElementState>,
343 cx: &mut ViewContext<ParentV>,
344 ) -> Self::ElementState {
345 self.view.0.initialize(cx)
346 }
347
348 fn layout(
349 &mut self,
350 _: &mut ParentV,
351 element: &mut Self::ElementState,
352 cx: &mut ViewContext<ParentV>,
353 ) -> LayoutId {
354 self.view.0.layout(element, cx)
355 }
356
357 fn paint(
358 &mut self,
359 bounds: Bounds<Pixels>,
360 _: &mut ParentV,
361 element: &mut Self::ElementState,
362 cx: &mut ViewContext<ParentV>,
363 ) {
364 self.view.0.paint(bounds, element, cx)
365 }
366}