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