view.rs

  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<Mutex<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + 'static>>,
 12}
 13
 14impl<V: 'static> View<V> {
 15    pub fn into_any(self) -> AnyView {
 16        AnyView(Arc::new(self))
 17    }
 18}
 19
 20impl<V> Clone for View<V> {
 21    fn clone(&self) -> Self {
 22        Self {
 23            state: self.state.clone(),
 24            render: self.render.clone(),
 25        }
 26    }
 27}
 28
 29pub fn view<V, E>(
 30    state: Handle<V>,
 31    render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
 32) -> View<V>
 33where
 34    E: Component<V>,
 35{
 36    View {
 37        state,
 38        render: Arc::new(Mutex::new(
 39            move |state: &mut V, cx: &mut ViewContext<'_, '_, V>| render(state, cx).render(),
 40        )),
 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.lock())(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> {}
 99
100impl<V: 'static, ParentV: 'static> Component<ParentV> for EraseViewState<V, ParentV> {
101    fn render(self) -> AnyElement<ParentV> {
102        AnyElement::new(self)
103    }
104}
105
106impl<V: 'static, ParentV: 'static> Element<ParentV> for EraseViewState<V, ParentV> {
107    type ElementState = AnyBox;
108
109    fn id(&self) -> Option<crate::ElementId> {
110        Element::id(&self.view)
111    }
112
113    fn initialize(
114        &mut self,
115        _: &mut ParentV,
116        _: Option<Self::ElementState>,
117        cx: &mut ViewContext<ParentV>,
118    ) -> Self::ElementState {
119        ViewObject::initialize(&mut self.view, cx)
120    }
121
122    fn layout(
123        &mut self,
124        _: &mut ParentV,
125        element: &mut Self::ElementState,
126        cx: &mut ViewContext<ParentV>,
127    ) -> LayoutId {
128        ViewObject::layout(&mut self.view, element, cx)
129    }
130
131    fn paint(
132        &mut self,
133        bounds: Bounds<Pixels>,
134        _: &mut ParentV,
135        element: &mut Self::ElementState,
136        cx: &mut ViewContext<ParentV>,
137    ) {
138        ViewObject::paint(&mut self.view, bounds, element, cx)
139    }
140}
141
142trait ViewObject: Send + Sync {
143    fn entity_id(&self) -> EntityId;
144    fn initialize(&self, cx: &mut WindowContext) -> AnyBox;
145    fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId;
146    fn paint(&self, bounds: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext);
147}
148
149impl<V: 'static> ViewObject for View<V> {
150    fn entity_id(&self) -> EntityId {
151        self.state.entity_id
152    }
153
154    fn initialize(&self, cx: &mut WindowContext) -> AnyBox {
155        cx.with_element_id(self.entity_id(), |_global_id, cx| {
156            self.state.update(cx, |state, cx| {
157                let mut any_element = Box::new((self.render.lock())(state, cx));
158                any_element.initialize(state, cx);
159                any_element as AnyBox
160            })
161        })
162    }
163
164    fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId {
165        cx.with_element_id(self.entity_id(), |_global_id, cx| {
166            self.state.update(cx, |state, cx| {
167                let element = element.downcast_mut::<AnyElement<V>>().unwrap();
168                element.layout(state, cx)
169            })
170        })
171    }
172
173    fn paint(&self, _: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext) {
174        cx.with_element_id(self.entity_id(), |_global_id, cx| {
175            self.state.update(cx, |state, cx| {
176                let element = element.downcast_mut::<AnyElement<V>>().unwrap();
177                element.paint(state, cx);
178            });
179        });
180    }
181}
182
183#[derive(Clone)]
184pub struct AnyView(Arc<dyn ViewObject>);
185
186impl<ParentV: 'static> Component<ParentV> for AnyView {
187    fn render(self) -> AnyElement<ParentV> {
188        AnyElement::new(EraseAnyViewState {
189            view: self,
190            parent_view_state_type: PhantomData,
191        })
192    }
193}
194
195impl Element<()> for AnyView {
196    type ElementState = AnyBox;
197
198    fn id(&self) -> Option<crate::ElementId> {
199        Some(ElementId::View(self.0.entity_id()))
200    }
201
202    fn initialize(
203        &mut self,
204        _: &mut (),
205        _: Option<Self::ElementState>,
206        cx: &mut ViewContext<()>,
207    ) -> Self::ElementState {
208        self.0.initialize(cx)
209    }
210
211    fn layout(
212        &mut self,
213        _: &mut (),
214        element: &mut Self::ElementState,
215        cx: &mut ViewContext<()>,
216    ) -> LayoutId {
217        self.0.layout(element, cx)
218    }
219
220    fn paint(
221        &mut self,
222        bounds: Bounds<Pixels>,
223        _: &mut (),
224        element: &mut AnyBox,
225        cx: &mut ViewContext<()>,
226    ) {
227        self.0.paint(bounds, element, cx)
228    }
229}
230
231struct EraseAnyViewState<ParentViewState> {
232    view: AnyView,
233    parent_view_state_type: PhantomData<ParentViewState>,
234}
235
236unsafe impl<ParentV> Send for EraseAnyViewState<ParentV> {}
237
238impl<ParentV: 'static> Component<ParentV> for EraseAnyViewState<ParentV> {
239    fn render(self) -> AnyElement<ParentV> {
240        AnyElement::new(self)
241    }
242}
243
244impl<ParentV: 'static> Element<ParentV> for EraseAnyViewState<ParentV> {
245    type ElementState = AnyBox;
246
247    fn id(&self) -> Option<crate::ElementId> {
248        Element::id(&self.view)
249    }
250
251    fn initialize(
252        &mut self,
253        _: &mut ParentV,
254        _: Option<Self::ElementState>,
255        cx: &mut ViewContext<ParentV>,
256    ) -> Self::ElementState {
257        self.view.0.initialize(cx)
258    }
259
260    fn layout(
261        &mut self,
262        _: &mut ParentV,
263        element: &mut Self::ElementState,
264        cx: &mut ViewContext<ParentV>,
265    ) -> LayoutId {
266        self.view.0.layout(element, cx)
267    }
268
269    fn paint(
270        &mut self,
271        bounds: Bounds<Pixels>,
272        _: &mut ParentV,
273        element: &mut Self::ElementState,
274        cx: &mut ViewContext<ParentV>,
275    ) {
276        self.view.0.paint(bounds, element, cx)
277    }
278}