element.rs

  1use crate::{
  2    BorrowWindow, Bounds, DispatchPhase, ElementId, FocusHandle, FocusListeners, KeyDownEvent,
  3    KeyListener, KeyMatch, LayoutId, MouseClickEvent, MouseClickListener, MouseDownEvent,
  4    MouseDownListener, MouseMoveEvent, MouseMoveListener, MouseUpEvent, MouseUpListener, Pixels,
  5    Point, ScrollWheelEvent, ScrollWheelListener, Style, StyleRefinement, ViewContext,
  6    WindowContext,
  7};
  8use derive_more::{Deref, DerefMut};
  9use parking_lot::Mutex;
 10use refineable::Refineable;
 11pub(crate) use smallvec::SmallVec;
 12use std::{any::TypeId, mem, sync::Arc};
 13
 14pub trait Element: 'static + Send + Sync + IntoAnyElement<Self::ViewState> {
 15    type ViewState: 'static + Send + Sync;
 16    type ElementState: 'static + Send + Sync;
 17
 18    fn id(&self) -> Option<ElementId>;
 19
 20    fn initialize(
 21        &mut self,
 22        view_state: &mut Self::ViewState,
 23        element_state: Option<Self::ElementState>,
 24        cx: &mut ViewContext<Self::ViewState>,
 25    ) -> Self::ElementState;
 26
 27    fn layout(
 28        &mut self,
 29        view_state: &mut Self::ViewState,
 30        element_state: &mut Self::ElementState,
 31        cx: &mut ViewContext<Self::ViewState>,
 32    ) -> LayoutId;
 33
 34    fn paint(
 35        &mut self,
 36        bounds: Bounds<Pixels>,
 37        view_state: &mut Self::ViewState,
 38        element_state: &mut Self::ElementState,
 39        cx: &mut ViewContext<Self::ViewState>,
 40    );
 41}
 42
 43#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
 44pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
 45
 46pub trait ElementInteractivity<V: 'static + Send + Sync>: 'static + Send + Sync {
 47    fn as_stateless(&self) -> &StatelessInteractivity<V>;
 48    fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V>;
 49    fn as_stateful(&self) -> Option<&StatefulInteractivity<V>>;
 50    fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>>;
 51
 52    fn paint(
 53        &mut self,
 54        bounds: Bounds<Pixels>,
 55        pending_click: Arc<Mutex<Option<MouseDownEvent>>>,
 56        cx: &mut ViewContext<V>,
 57    ) {
 58        let stateless = self.as_stateless();
 59        for listener in stateless.mouse_down_listeners.iter().cloned() {
 60            cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
 61                listener(state, event, &bounds, phase, cx);
 62            })
 63        }
 64
 65        for listener in stateless.mouse_up_listeners.iter().cloned() {
 66            cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
 67                listener(state, event, &bounds, phase, cx);
 68            })
 69        }
 70
 71        for listener in stateless.mouse_move_listeners.iter().cloned() {
 72            cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
 73                listener(state, event, &bounds, phase, cx);
 74            })
 75        }
 76
 77        for listener in stateless.scroll_wheel_listeners.iter().cloned() {
 78            cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
 79                listener(state, event, &bounds, phase, cx);
 80            })
 81        }
 82
 83        if let Some(stateful) = self.as_stateful() {
 84            let click_listeners = stateful.mouse_click_listeners.clone();
 85
 86            let mouse_down = pending_click.lock().clone();
 87            if let Some(mouse_down) = mouse_down {
 88                cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
 89                    if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
 90                        let mouse_click = MouseClickEvent {
 91                            down: mouse_down.clone(),
 92                            up: event.clone(),
 93                        };
 94                        for listener in &click_listeners {
 95                            listener(state, &mouse_click, cx);
 96                        }
 97                    }
 98
 99                    *pending_click.lock() = None;
100                });
101            } else {
102                cx.on_mouse_event(move |_state, event: &MouseDownEvent, phase, _cx| {
103                    if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
104                        *pending_click.lock() = Some(event.clone());
105                    }
106                });
107            };
108        }
109    }
110
111    fn initialize<R>(
112        &mut self,
113        cx: &mut ViewContext<V>,
114        f: impl FnOnce(&mut ViewContext<V>) -> R,
115    ) -> R {
116        if let Some(stateful) = self.as_stateful_mut() {
117            cx.with_element_id(stateful.id.clone(), |global_id, cx| {
118                stateful.key_listeners.push((
119                    TypeId::of::<KeyDownEvent>(),
120                    Arc::new(move |_, key_down, context, phase, cx| {
121                        if phase == DispatchPhase::Bubble {
122                            let key_down = key_down.downcast_ref::<KeyDownEvent>().unwrap();
123                            if let KeyMatch::Some(action) =
124                                cx.match_keystroke(&global_id, &key_down.keystroke, context)
125                            {
126                                return Some(action);
127                            }
128                        }
129
130                        None
131                    }),
132                ));
133                let result = stateful.stateless.initialize(cx, f);
134                stateful.key_listeners.pop();
135                result
136            })
137        } else {
138            cx.with_key_listeners(&self.as_stateless().key_listeners, f)
139        }
140    }
141}
142
143#[derive(Deref, DerefMut)]
144pub struct StatefulInteractivity<V: 'static + Send + Sync> {
145    pub id: ElementId,
146    #[deref]
147    #[deref_mut]
148    stateless: StatelessInteractivity<V>,
149    pub mouse_click_listeners: SmallVec<[MouseClickListener<V>; 2]>,
150}
151
152impl<V> ElementInteractivity<V> for StatefulInteractivity<V>
153where
154    V: 'static + Send + Sync,
155{
156    fn as_stateful(&self) -> Option<&StatefulInteractivity<V>> {
157        Some(self)
158    }
159
160    fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>> {
161        Some(self)
162    }
163
164    fn as_stateless(&self) -> &StatelessInteractivity<V> {
165        &self.stateless
166    }
167
168    fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V> {
169        &mut self.stateless
170    }
171}
172
173impl<V> From<ElementId> for StatefulInteractivity<V>
174where
175    V: 'static + Send + Sync,
176{
177    fn from(id: ElementId) -> Self {
178        Self {
179            id,
180            stateless: StatelessInteractivity::default(),
181            mouse_click_listeners: SmallVec::new(),
182        }
183    }
184}
185
186pub struct StatelessInteractivity<V> {
187    pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
188    pub mouse_up_listeners: SmallVec<[MouseUpListener<V>; 2]>,
189    pub mouse_move_listeners: SmallVec<[MouseMoveListener<V>; 2]>,
190    pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener<V>; 2]>,
191    pub key_listeners: SmallVec<[(TypeId, KeyListener<V>); 32]>,
192}
193
194impl<V> Default for StatelessInteractivity<V> {
195    fn default() -> Self {
196        Self {
197            mouse_down_listeners: SmallVec::new(),
198            mouse_up_listeners: SmallVec::new(),
199            mouse_move_listeners: SmallVec::new(),
200            scroll_wheel_listeners: SmallVec::new(),
201            key_listeners: SmallVec::new(),
202        }
203    }
204}
205
206impl<V> ElementInteractivity<V> for StatelessInteractivity<V>
207where
208    V: 'static + Send + Sync,
209{
210    fn as_stateful(&self) -> Option<&StatefulInteractivity<V>> {
211        None
212    }
213
214    fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>> {
215        None
216    }
217
218    fn as_stateless(&self) -> &StatelessInteractivity<V> {
219        self
220    }
221
222    fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V> {
223        self
224    }
225}
226
227pub trait ElementFocusability<V: 'static + Send + Sync>: 'static + Send + Sync {
228    fn as_focusable(&self) -> Option<&Focusable<V>>;
229
230    fn initialize<R>(
231        &self,
232        cx: &mut ViewContext<V>,
233        f: impl FnOnce(&mut ViewContext<V>) -> R,
234    ) -> R {
235        if let Some(focusable) = self.as_focusable() {
236            for listener in focusable.focus_listeners.iter().cloned() {
237                cx.on_focus_changed(move |view, event, cx| listener(view, event, cx));
238            }
239            cx.with_focus(focusable.focus_handle.clone(), |cx| f(cx))
240        } else {
241            f(cx)
242        }
243    }
244
245    fn refine_style(&self, style: &mut Style, cx: &WindowContext) {
246        if let Some(focusable) = self.as_focusable() {
247            if focusable.focus_handle.contains_focused(cx) {
248                style.refine(&focusable.focus_in_style);
249            }
250
251            if focusable.focus_handle.within_focused(cx) {
252                style.refine(&focusable.in_focus_style);
253            }
254
255            if focusable.focus_handle.is_focused(cx) {
256                style.refine(&focusable.focus_style);
257            }
258        }
259    }
260
261    fn paint(&self, bounds: Bounds<Pixels>, cx: &mut WindowContext) {
262        if let Some(focusable) = self.as_focusable() {
263            let focus_handle = focusable.focus_handle.clone();
264            cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
265                if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
266                    if !cx.default_prevented() {
267                        cx.focus(&focus_handle);
268                        cx.prevent_default();
269                    }
270                }
271            })
272        }
273    }
274}
275
276pub struct Focusable<V: 'static + Send + Sync> {
277    pub focus_handle: FocusHandle,
278    pub focus_listeners: FocusListeners<V>,
279    pub focus_style: StyleRefinement,
280    pub focus_in_style: StyleRefinement,
281    pub in_focus_style: StyleRefinement,
282}
283
284impl<V> ElementFocusability<V> for Focusable<V>
285where
286    V: 'static + Send + Sync,
287{
288    fn as_focusable(&self) -> Option<&Focusable<V>> {
289        Some(self)
290    }
291}
292
293impl<V> From<FocusHandle> for Focusable<V>
294where
295    V: 'static + Send + Sync,
296{
297    fn from(value: FocusHandle) -> Self {
298        Self {
299            focus_handle: value,
300            focus_listeners: FocusListeners::default(),
301            focus_style: StyleRefinement::default(),
302            focus_in_style: StyleRefinement::default(),
303            in_focus_style: StyleRefinement::default(),
304        }
305    }
306}
307
308pub struct NonFocusable;
309
310impl<V> ElementFocusability<V> for NonFocusable
311where
312    V: 'static + Send + Sync,
313{
314    fn as_focusable(&self) -> Option<&Focusable<V>> {
315        None
316    }
317}
318
319pub trait ParentElement: Element {
320    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]>;
321
322    fn child(mut self, child: impl IntoAnyElement<Self::ViewState>) -> Self
323    where
324        Self: Sized,
325    {
326        self.children_mut().push(child.into_any());
327        self
328    }
329
330    fn children(
331        mut self,
332        iter: impl IntoIterator<Item = impl IntoAnyElement<Self::ViewState>>,
333    ) -> Self
334    where
335        Self: Sized,
336    {
337        self.children_mut()
338            .extend(iter.into_iter().map(|item| item.into_any()));
339        self
340    }
341}
342
343trait ElementObject<V>: 'static + Send + Sync {
344    fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
345    fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
346    fn paint(&mut self, view_state: &mut V, offset: Option<Point<Pixels>>, cx: &mut ViewContext<V>);
347}
348
349struct RenderedElement<E: Element> {
350    element: E,
351    phase: ElementRenderPhase<E::ElementState>,
352}
353
354#[derive(Default)]
355enum ElementRenderPhase<V> {
356    #[default]
357    Start,
358    Initialized {
359        frame_state: Option<V>,
360    },
361    LayoutRequested {
362        layout_id: LayoutId,
363        frame_state: Option<V>,
364    },
365    Painted,
366}
367
368/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
369/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
370/// improved usability.
371impl<E: Element> RenderedElement<E> {
372    fn new(element: E) -> Self {
373        RenderedElement {
374            element,
375            phase: ElementRenderPhase::Start,
376        }
377    }
378}
379
380impl<E> ElementObject<E::ViewState> for RenderedElement<E>
381where
382    E: Element,
383{
384    fn initialize(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
385        let frame_state = if let Some(id) = self.element.id() {
386            cx.with_element_state(id, |element_state, cx| {
387                let element_state = self.element.initialize(view_state, element_state, cx);
388                ((), element_state)
389            });
390            None
391        } else {
392            let frame_state = self.element.initialize(view_state, None, cx);
393            Some(frame_state)
394        };
395
396        self.phase = ElementRenderPhase::Initialized { frame_state };
397    }
398
399    fn layout(&mut self, state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) -> LayoutId {
400        let layout_id;
401        let mut frame_state;
402        match mem::take(&mut self.phase) {
403            ElementRenderPhase::Initialized {
404                frame_state: initial_frame_state,
405            } => {
406                frame_state = initial_frame_state;
407                if let Some(id) = self.element.id() {
408                    layout_id = cx.with_element_state(id, |element_state, cx| {
409                        let mut element_state = element_state.unwrap();
410                        let layout_id = self.element.layout(state, &mut element_state, cx);
411                        (layout_id, element_state)
412                    });
413                } else {
414                    layout_id = self
415                        .element
416                        .layout(state, frame_state.as_mut().unwrap(), cx);
417                }
418            }
419            _ => panic!("must call initialize before layout"),
420        };
421
422        self.phase = ElementRenderPhase::LayoutRequested {
423            layout_id,
424            frame_state,
425        };
426        layout_id
427    }
428
429    fn paint(
430        &mut self,
431        view_state: &mut E::ViewState,
432        offset: Option<Point<Pixels>>,
433        cx: &mut ViewContext<E::ViewState>,
434    ) {
435        self.phase = match mem::take(&mut self.phase) {
436            ElementRenderPhase::LayoutRequested {
437                layout_id,
438                mut frame_state,
439            } => {
440                let mut bounds = cx.layout_bounds(layout_id);
441                offset.map(|offset| bounds.origin += offset);
442                if let Some(id) = self.element.id() {
443                    cx.with_element_state(id, |element_state, cx| {
444                        let mut element_state = element_state.unwrap();
445                        self.element
446                            .paint(bounds, view_state, &mut element_state, cx);
447                        ((), element_state)
448                    });
449                } else {
450                    self.element
451                        .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
452                }
453                ElementRenderPhase::Painted
454            }
455
456            _ => panic!("must call layout before paint"),
457        };
458    }
459}
460
461pub struct AnyElement<V>(Box<dyn ElementObject<V>>);
462
463impl<V: 'static + Send + Sync> AnyElement<V> {
464    pub fn new<E: Element<ViewState = V>>(element: E) -> Self {
465        AnyElement(Box::new(RenderedElement::new(element)))
466    }
467
468    pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
469        self.0.initialize(view_state, cx);
470    }
471
472    pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
473        self.0.layout(view_state, cx)
474    }
475
476    pub fn paint(
477        &mut self,
478        view_state: &mut V,
479        offset: Option<Point<Pixels>>,
480        cx: &mut ViewContext<V>,
481    ) {
482        self.0.paint(view_state, offset, cx)
483    }
484}
485
486pub trait IntoAnyElement<V> {
487    fn into_any(self) -> AnyElement<V>;
488}
489
490impl<V> IntoAnyElement<V> for AnyElement<V> {
491    fn into_any(self) -> AnyElement<V> {
492        self
493    }
494}