view.rs

  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}