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