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> {
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<crate::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<crate::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_id(&self) -> EntityId;
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_id(&self) -> EntityId {
154 self.state.entity_id
155 }
156
157 fn initialize(&mut self, cx: &mut WindowContext) -> AnyBox {
158 cx.with_element_id(self.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.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.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<ParentV: 'static> IntoAnyElement<ParentV> for AnyView {
191 fn into_any(self) -> AnyElement<ParentV> {
192 AnyElement::new(EraseAnyViewState {
193 view: self,
194 parent_view_state_type: PhantomData,
195 })
196 }
197}
198
199impl Element for AnyView {
200 type ViewState = ();
201 type ElementState = AnyBox;
202
203 fn id(&self) -> Option<crate::ElementId> {
204 Some(ElementId::View(self.view.lock().entity_id()))
205 }
206
207 fn initialize(
208 &mut self,
209 _: &mut Self::ViewState,
210 _: Option<Self::ElementState>,
211 cx: &mut ViewContext<Self::ViewState>,
212 ) -> Self::ElementState {
213 self.view.lock().initialize(cx)
214 }
215
216 fn layout(
217 &mut self,
218 _: &mut Self::ViewState,
219 element: &mut Self::ElementState,
220 cx: &mut ViewContext<Self::ViewState>,
221 ) -> LayoutId {
222 self.view.lock().layout(element, cx)
223 }
224
225 fn paint(
226 &mut self,
227 bounds: Bounds<Pixels>,
228 _: &mut (),
229 element: &mut AnyBox,
230 cx: &mut ViewContext<Self::ViewState>,
231 ) {
232 self.view.lock().paint(bounds, element, cx)
233 }
234}
235
236struct EraseAnyViewState<ParentViewState> {
237 view: AnyView,
238 parent_view_state_type: PhantomData<ParentViewState>,
239}
240
241unsafe impl<ParentV> Send for EraseAnyViewState<ParentV> {}
242unsafe impl<ParentV> Sync for EraseAnyViewState<ParentV> {}
243
244impl<ParentV: 'static> IntoAnyElement<ParentV> for EraseAnyViewState<ParentV> {
245 fn into_any(self) -> AnyElement<ParentV> {
246 AnyElement::new(self)
247 }
248}
249
250impl<ParentV: 'static> Element for EraseAnyViewState<ParentV> {
251 type ViewState = ParentV;
252 type ElementState = AnyBox;
253
254 fn id(&self) -> Option<crate::ElementId> {
255 Element::id(&self.view)
256 }
257
258 fn initialize(
259 &mut self,
260 _: &mut Self::ViewState,
261 _: Option<Self::ElementState>,
262 cx: &mut ViewContext<Self::ViewState>,
263 ) -> Self::ElementState {
264 self.view.view.lock().initialize(cx)
265 }
266
267 fn layout(
268 &mut self,
269 _: &mut Self::ViewState,
270 element: &mut Self::ElementState,
271 cx: &mut ViewContext<Self::ViewState>,
272 ) -> LayoutId {
273 self.view.view.lock().layout(element, cx)
274 }
275
276 fn paint(
277 &mut self,
278 bounds: Bounds<Pixels>,
279 _: &mut Self::ViewState,
280 element: &mut Self::ElementState,
281 cx: &mut ViewContext<Self::ViewState>,
282 ) {
283 self.view.view.lock().paint(bounds, element, cx)
284 }
285}
286
287impl Clone for AnyView {
288 fn clone(&self) -> Self {
289 Self {
290 view: self.view.clone(),
291 }
292 }
293}