element.rs

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