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