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