element.rs

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