element.rs

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