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