view.rs

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