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