element.rs

  1use crate::{BorrowWindow, Bounds, ElementId, LayoutId, Pixels, ViewContext};
  2use derive_more::{Deref, DerefMut};
  3pub(crate) use smallvec::SmallVec;
  4use std::{any::Any, mem};
  5
  6pub trait Element<V: 'static>: IntoAnyElement<V> {
  7    type ElementState: 'static;
  8
  9    fn id(&self) -> Option<ElementId>;
 10
 11    fn initialize(
 12        &mut self,
 13        view_state: &mut V,
 14        element_state: Option<Self::ElementState>,
 15        cx: &mut ViewContext<V>,
 16    ) -> Self::ElementState;
 17    // where
 18    //     V: Any + Send + Sync;
 19
 20    fn layout(
 21        &mut self,
 22        view_state: &mut V,
 23        element_state: &mut Self::ElementState,
 24        cx: &mut ViewContext<V>,
 25    ) -> LayoutId;
 26    // where
 27    //     V: Any + Send + Sync;
 28
 29    fn paint(
 30        &mut self,
 31        bounds: Bounds<Pixels>,
 32        view_state: &mut V,
 33        element_state: &mut Self::ElementState,
 34        cx: &mut ViewContext<V>,
 35    );
 36
 37    // where
 38    //     Self::ViewState: Any + Send + Sync;
 39}
 40
 41#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
 42pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
 43
 44pub trait ParentElement<V: 'static>: Element<V> {
 45    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]>;
 46
 47    fn child(mut self, child: impl IntoAnyElement<V>) -> Self
 48    where
 49        Self: Sized,
 50    {
 51        self.children_mut().push(child.into_any());
 52        self
 53    }
 54
 55    fn children(mut self, iter: impl IntoIterator<Item = impl IntoAnyElement<V>>) -> Self
 56    where
 57        Self: Sized,
 58    {
 59        self.children_mut()
 60            .extend(iter.into_iter().map(|item| item.into_any()));
 61        self
 62    }
 63}
 64
 65trait ElementObject<V> {
 66    fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
 67    fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
 68    fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
 69}
 70
 71struct RenderedElement<V: 'static, E: Element<V>> {
 72    element: E,
 73    phase: ElementRenderPhase<E::ElementState>,
 74}
 75
 76#[derive(Default)]
 77enum ElementRenderPhase<V> {
 78    #[default]
 79    Start,
 80    Initialized {
 81        frame_state: Option<V>,
 82    },
 83    LayoutRequested {
 84        layout_id: LayoutId,
 85        frame_state: Option<V>,
 86    },
 87    Painted,
 88}
 89
 90/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
 91/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
 92/// improved usability.
 93impl<V, E: Element<V>> RenderedElement<V, E> {
 94    fn new(element: E) -> Self {
 95        RenderedElement {
 96            element,
 97            phase: ElementRenderPhase::Start,
 98        }
 99    }
100}
101
102impl<V, E> ElementObject<V> for RenderedElement<V, E>
103where
104    E: Element<V>,
105    // E::ViewState: Any + Send + Sync,
106    E::ElementState: Any + Send + Sync,
107{
108    fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
109        let frame_state = if let Some(id) = self.element.id() {
110            cx.with_element_state(id, |element_state, cx| {
111                let element_state = self.element.initialize(view_state, element_state, cx);
112                ((), element_state)
113            });
114            None
115        } else {
116            let frame_state = self.element.initialize(view_state, None, cx);
117            Some(frame_state)
118        };
119
120        self.phase = ElementRenderPhase::Initialized { frame_state };
121    }
122
123    fn layout(&mut self, state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
124        let layout_id;
125        let mut frame_state;
126        match mem::take(&mut self.phase) {
127            ElementRenderPhase::Initialized {
128                frame_state: initial_frame_state,
129            } => {
130                frame_state = initial_frame_state;
131                if let Some(id) = self.element.id() {
132                    layout_id = cx.with_element_state(id, |element_state, cx| {
133                        let mut element_state = element_state.unwrap();
134                        let layout_id = self.element.layout(state, &mut element_state, cx);
135                        (layout_id, element_state)
136                    });
137                } else {
138                    layout_id = self
139                        .element
140                        .layout(state, frame_state.as_mut().unwrap(), cx);
141                }
142            }
143            _ => panic!("must call initialize before layout"),
144        };
145
146        self.phase = ElementRenderPhase::LayoutRequested {
147            layout_id,
148            frame_state,
149        };
150        layout_id
151    }
152
153    fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
154        self.phase = match mem::take(&mut self.phase) {
155            ElementRenderPhase::LayoutRequested {
156                layout_id,
157                mut frame_state,
158            } => {
159                let bounds = cx.layout_bounds(layout_id);
160                if let Some(id) = self.element.id() {
161                    cx.with_element_state(id, |element_state, cx| {
162                        let mut element_state = element_state.unwrap();
163                        self.element
164                            .paint(bounds, view_state, &mut element_state, cx);
165                        ((), element_state)
166                    });
167                } else {
168                    self.element
169                        .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
170                }
171                ElementRenderPhase::Painted
172            }
173
174            _ => panic!("must call layout before paint"),
175        };
176    }
177}
178
179pub struct AnyElement<V>(Box<dyn ElementObject<V> + Send + Sync>);
180
181impl<V> AnyElement<V> {
182    pub fn new<E>(element: E) -> Self
183    where
184        V: 'static,
185        E: 'static + Send + Sync,
186        E: Element<V>,
187        E::ElementState: Any + Send + Sync,
188    {
189        AnyElement(Box::new(RenderedElement::new(element)))
190    }
191
192    pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
193        self.0.initialize(view_state, cx);
194    }
195
196    pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
197        self.0.layout(view_state, cx)
198    }
199
200    pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
201        self.0.paint(view_state, cx)
202    }
203}
204
205pub trait IntoAnyElement<V> {
206    fn into_any(self) -> AnyElement<V>;
207}
208
209impl<V> IntoAnyElement<V> for AnyElement<V> {
210    fn into_any(self) -> AnyElement<V> {
211        self
212    }
213}