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