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