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