view.rs

  1use crate::{
  2    AnyBox, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element, ElementId,
  3    EntityId, Handle, LayoutId, Pixels, Size, ViewContext, VisualContext, WeakHandle,
  4    WindowContext,
  5};
  6use anyhow::{Context, Result};
  7use parking_lot::Mutex;
  8use std::{
  9    marker::PhantomData,
 10    sync::{Arc, Weak},
 11};
 12
 13pub struct View<V> {
 14    pub(crate) state: Handle<V>,
 15    render: Arc<Mutex<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + 'static>>,
 16}
 17
 18impl<V: 'static> View<V> {
 19    pub fn for_handle<E>(
 20        state: Handle<V>,
 21        render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
 22    ) -> View<V>
 23    where
 24        E: Component<V>,
 25    {
 26        View {
 27            state,
 28            render: Arc::new(Mutex::new(
 29                move |state: &mut V, cx: &mut ViewContext<'_, '_, V>| render(state, cx).render(),
 30            )),
 31        }
 32    }
 33}
 34
 35impl<V: 'static> View<V> {
 36    pub fn into_any(self) -> AnyView {
 37        AnyView(Arc::new(self))
 38    }
 39
 40    pub fn downgrade(&self) -> WeakView<V> {
 41        WeakView {
 42            state: self.state.downgrade(),
 43            render: Arc::downgrade(&self.render),
 44        }
 45    }
 46}
 47
 48impl<V: 'static> View<V> {
 49    pub fn update<C, R>(
 50        &self,
 51        cx: &mut C,
 52        f: impl FnOnce(&mut V, &mut C::ViewContext<'_, '_, V>) -> R,
 53    ) -> C::Result<R>
 54    where
 55        C: VisualContext,
 56    {
 57        cx.update_view(self, f)
 58    }
 59}
 60
 61impl<V> Clone for View<V> {
 62    fn clone(&self) -> Self {
 63        Self {
 64            state: self.state.clone(),
 65            render: self.render.clone(),
 66        }
 67    }
 68}
 69
 70impl<V: 'static, ParentViewState: 'static> Component<ParentViewState> for View<V> {
 71    fn render(self) -> AnyElement<ParentViewState> {
 72        AnyElement::new(EraseViewState {
 73            view: self,
 74            parent_view_state_type: PhantomData,
 75        })
 76    }
 77}
 78
 79impl<V: 'static> Element<()> for View<V> {
 80    type ElementState = AnyElement<V>;
 81
 82    fn id(&self) -> Option<crate::ElementId> {
 83        Some(ElementId::View(self.state.entity_id))
 84    }
 85
 86    fn initialize(
 87        &mut self,
 88        _: &mut (),
 89        _: Option<Self::ElementState>,
 90        cx: &mut ViewContext<()>,
 91    ) -> Self::ElementState {
 92        self.update(cx, |state, cx| {
 93            let mut any_element = (self.render.lock())(state, cx);
 94            any_element.initialize(state, cx);
 95            any_element
 96        })
 97    }
 98
 99    fn layout(
100        &mut self,
101        _: &mut (),
102        element: &mut Self::ElementState,
103        cx: &mut ViewContext<()>,
104    ) -> LayoutId {
105        self.update(cx, |state, cx| element.layout(state, cx))
106    }
107
108    fn paint(
109        &mut self,
110        _: Bounds<Pixels>,
111        _: &mut (),
112        element: &mut Self::ElementState,
113        cx: &mut ViewContext<()>,
114    ) {
115        self.update(cx, |state, cx| element.paint(state, cx))
116    }
117}
118
119pub struct WeakView<V> {
120    pub(crate) state: WeakHandle<V>,
121    render: Weak<Mutex<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + 'static>>,
122}
123
124impl<V: 'static> WeakView<V> {
125    pub fn upgrade(&self) -> Option<View<V>> {
126        let state = self.state.upgrade()?;
127        let render = self.render.upgrade()?;
128        Some(View { state, render })
129    }
130
131    pub fn update<R>(
132        &self,
133        cx: &mut WindowContext,
134        f: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
135    ) -> Result<R> {
136        let view = self.upgrade().context("error upgrading view")?;
137        Ok(view.update(cx, f))
138    }
139}
140
141impl<V> Clone for WeakView<V> {
142    fn clone(&self) -> Self {
143        Self {
144            state: self.state.clone(),
145            render: self.render.clone(),
146        }
147    }
148}
149
150struct EraseViewState<V, ParentV> {
151    view: View<V>,
152    parent_view_state_type: PhantomData<ParentV>,
153}
154
155unsafe impl<V, ParentV> Send for EraseViewState<V, ParentV> {}
156
157impl<V: 'static, ParentV: 'static> Component<ParentV> for EraseViewState<V, ParentV> {
158    fn render(self) -> AnyElement<ParentV> {
159        AnyElement::new(self)
160    }
161}
162
163impl<V: 'static, ParentV: 'static> Element<ParentV> for EraseViewState<V, ParentV> {
164    type ElementState = AnyBox;
165
166    fn id(&self) -> Option<crate::ElementId> {
167        Element::id(&self.view)
168    }
169
170    fn initialize(
171        &mut self,
172        _: &mut ParentV,
173        _: Option<Self::ElementState>,
174        cx: &mut ViewContext<ParentV>,
175    ) -> Self::ElementState {
176        ViewObject::initialize(&mut self.view, cx)
177    }
178
179    fn layout(
180        &mut self,
181        _: &mut ParentV,
182        element: &mut Self::ElementState,
183        cx: &mut ViewContext<ParentV>,
184    ) -> LayoutId {
185        ViewObject::layout(&mut self.view, element, cx)
186    }
187
188    fn paint(
189        &mut self,
190        bounds: Bounds<Pixels>,
191        _: &mut ParentV,
192        element: &mut Self::ElementState,
193        cx: &mut ViewContext<ParentV>,
194    ) {
195        ViewObject::paint(&mut self.view, bounds, element, cx)
196    }
197}
198
199trait ViewObject: Send + Sync {
200    fn entity_id(&self) -> EntityId;
201    fn initialize(&self, cx: &mut WindowContext) -> AnyBox;
202    fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId;
203    fn paint(&self, bounds: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext);
204}
205
206impl<V: 'static> ViewObject for View<V> {
207    fn entity_id(&self) -> EntityId {
208        self.state.entity_id
209    }
210
211    fn initialize(&self, cx: &mut WindowContext) -> AnyBox {
212        cx.with_element_id(self.entity_id(), |_global_id, cx| {
213            self.update(cx, |state, cx| {
214                let mut any_element = Box::new((self.render.lock())(state, cx));
215                any_element.initialize(state, cx);
216                any_element as AnyBox
217            })
218        })
219    }
220
221    fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId {
222        cx.with_element_id(self.entity_id(), |_global_id, cx| {
223            self.update(cx, |state, cx| {
224                let element = element.downcast_mut::<AnyElement<V>>().unwrap();
225                element.layout(state, cx)
226            })
227        })
228    }
229
230    fn paint(&self, _: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext) {
231        cx.with_element_id(self.entity_id(), |_global_id, cx| {
232            self.update(cx, |state, cx| {
233                let element = element.downcast_mut::<AnyElement<V>>().unwrap();
234                element.paint(state, cx);
235            });
236        });
237    }
238}
239
240#[derive(Clone)]
241pub struct AnyView(Arc<dyn ViewObject>);
242
243impl AnyView {
244    pub(crate) fn draw(&self, available_space: Size<AvailableSpace>, cx: &mut WindowContext) {
245        let mut rendered_element = self.0.initialize(cx);
246        let layout_id = self.0.layout(&mut rendered_element, cx);
247        cx.window
248            .layout_engine
249            .compute_layout(layout_id, available_space);
250        let bounds = cx.window.layout_engine.layout_bounds(layout_id);
251        self.0.paint(bounds, &mut rendered_element, cx);
252    }
253}
254
255impl<ParentV: 'static> Component<ParentV> for AnyView {
256    fn render(self) -> AnyElement<ParentV> {
257        AnyElement::new(EraseAnyViewState {
258            view: self,
259            parent_view_state_type: PhantomData,
260        })
261    }
262}
263
264impl Element<()> for AnyView {
265    type ElementState = AnyBox;
266
267    fn id(&self) -> Option<crate::ElementId> {
268        Some(ElementId::View(self.0.entity_id()))
269    }
270
271    fn initialize(
272        &mut self,
273        _: &mut (),
274        _: Option<Self::ElementState>,
275        cx: &mut ViewContext<()>,
276    ) -> Self::ElementState {
277        self.0.initialize(cx)
278    }
279
280    fn layout(
281        &mut self,
282        _: &mut (),
283        element: &mut Self::ElementState,
284        cx: &mut ViewContext<()>,
285    ) -> LayoutId {
286        self.0.layout(element, cx)
287    }
288
289    fn paint(
290        &mut self,
291        bounds: Bounds<Pixels>,
292        _: &mut (),
293        element: &mut AnyBox,
294        cx: &mut ViewContext<()>,
295    ) {
296        self.0.paint(bounds, element, cx)
297    }
298}
299
300struct EraseAnyViewState<ParentViewState> {
301    view: AnyView,
302    parent_view_state_type: PhantomData<ParentViewState>,
303}
304
305unsafe impl<ParentV> Send for EraseAnyViewState<ParentV> {}
306
307impl<ParentV: 'static> Component<ParentV> for EraseAnyViewState<ParentV> {
308    fn render(self) -> AnyElement<ParentV> {
309        AnyElement::new(self)
310    }
311}
312
313impl<ParentV: 'static> Element<ParentV> for EraseAnyViewState<ParentV> {
314    type ElementState = AnyBox;
315
316    fn id(&self) -> Option<crate::ElementId> {
317        Element::id(&self.view)
318    }
319
320    fn initialize(
321        &mut self,
322        _: &mut ParentV,
323        _: Option<Self::ElementState>,
324        cx: &mut ViewContext<ParentV>,
325    ) -> Self::ElementState {
326        self.view.0.initialize(cx)
327    }
328
329    fn layout(
330        &mut self,
331        _: &mut ParentV,
332        element: &mut Self::ElementState,
333        cx: &mut ViewContext<ParentV>,
334    ) -> LayoutId {
335        self.view.0.layout(element, cx)
336    }
337
338    fn paint(
339        &mut self,
340        bounds: Bounds<Pixels>,
341        _: &mut ParentV,
342        element: &mut Self::ElementState,
343        cx: &mut ViewContext<ParentV>,
344    ) {
345        self.view.0.paint(bounds, element, cx)
346    }
347}