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