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