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