view.rs

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