kas_core/core/
events.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Widget and Events traits
7
8#[allow(unused)] use super::Layout;
9use super::{Tile, Widget};
10use crate::Id;
11#[allow(unused)] use crate::event::EventState;
12use crate::event::{ConfigCx, CursorIcon, Event, EventCx, IsUsed, Scroll, Unused};
13#[allow(unused)] use kas_macros as macros;
14
15/// Widget event-handling
16///
17/// This trait governs event handling as part of a [`Widget`] implementation.
18/// It is used by the [`#widget`] macro to generate hidden [`Widget`] methods.
19///
20/// The implementation of this method may be omitted where no event-handling is
21/// required. All methods have a default implementation.
22///
23/// Type [`Widget::Data`] may be specified in `impl Events { ... }` instead of
24/// in `impl Widget { ... }` (this is permitted since it allows may `#[widget]`
25/// definitions to omit `impl Widget { ... }` altogether).
26///
27/// # Widget lifecycle
28///
29/// 1.  The widget is configured ([`Events::configure`],
30///     [`Events::configure_recurse`]) and immediately updated
31///     ([`Events::update`]).
32///
33///     The widget may be re-configured at any time without expectation that
34///     the layout will be resized / set again.
35/// 2.  The widget is updated by calling [`Events::update`] immediately after
36///     it is configured and also after any update to input data (or other data
37///     which may have changed, such as that exposed by [`EventState::config`]).
38/// 3.  The widget is "sized" by calling [`Layout::size_rules`] for the
39///     horizontal axis then for the vertical axis.
40///
41///     These methods may be called again at any time without expectation that
42///     the layout will be set again.
43/// 4.  [`Layout::set_rect`] is called to "set" layout.
44///
45///     This method may be called again at any time.
46/// 5.  The widget is ready for event-handling and drawing
47///     ([`Events::handle_event`], [`Layout::try_probe`], [`Layout::draw`]).
48///
49/// Widgets are responsible for ensuring that their children may observe this
50/// lifecycle. Usually this simply involves inclusion of the child in layout
51/// operations. Steps of the lifecycle may be postponed until a widget becomes
52/// visible.
53///
54/// [`#widget`]: macros::widget
55pub trait Events: Widget + Sized {
56    /// Does this widget have a different appearance on mouse over?
57    ///
58    /// If `true`, then the mouse moving over and leaving the widget will cause
59    /// a redraw. (Note that [`Layout::draw`] can infer the mouse-over state and
60    /// start animations.)
61    const REDRAW_ON_MOUSE_OVER: bool = false;
62
63    /// The mouse cursor icon to use on mouse over
64    ///
65    /// Defaults to `None`.
66    #[inline]
67    fn mouse_over_icon(&self) -> Option<CursorIcon> {
68        None
69    }
70
71    /// Make an identifier for a child
72    ///
73    /// This is used to assign children identifiers. It may return
74    /// [`Id::default`] in order to avoid configuring the child, but in
75    /// this case the widget must configure via another means.
76    ///
77    /// If this is implemented explicitly then [`Tile::find_child_index`] must
78    /// be too.
79    ///
80    /// Default impl: `self.id_ref().make_child(index)`
81    #[inline]
82    fn make_child_id(&mut self, index: usize) -> Id {
83        self.id_ref().make_child(index)
84    }
85
86    /// Configure self
87    ///
88    /// Widgets are *configured* before sizing, drawing and event handling (see
89    /// [widget lifecycle](Widget#widget-lifecycle)).
90    ///
91    /// Configuration may be repeated at any time. If `id` changes, children
92    /// must be assigned new/updated identifiers.
93    ///
94    /// [`Self::update`] is always called immediately after this method,
95    /// followed by [`Self::configure_recurse`].
96    ///
97    /// The window's scale factor (and thus any sizes available through
98    /// [`ConfigCx::size_cx`]) may not be correct initially (some platforms
99    /// construct all windows using scale factor 1) and/or may change in the
100    /// future. Changes to the scale factor result in recalculation of
101    /// [`Layout::size_rules`] but not repeated configuration.
102    ///
103    /// The default implementation does nothing.
104    fn configure(&mut self, cx: &mut ConfigCx) {
105        let _ = cx;
106    }
107
108    /// Configure children
109    ///
110    /// This method is called after [`Self::configure`].
111    /// The default implementation configures all children.
112    ///
113    /// An explicit implementation is required in cases where not all children
114    /// should be configured immediately (for example, a stack or paged list may
115    /// choose not to configure hidden children until just before they become
116    /// visible). To configure children explicitly, generate an [`Id`] by
117    /// calling [`Events::make_child_id`] on `self` then pass this `id` to
118    /// [`ConfigCx::configure`].
119    ///
120    /// The default implementation configures children in the range
121    /// [`Tile::child_indices`]. In cases where [`Tile::child_indices`] hides
122    /// some children, a custom implementation of this method might be needed.
123    fn configure_recurse(&mut self, cx: &mut ConfigCx, data: &Self::Data) {
124        for index in self.child_indices().into_iter() {
125            let id = self.make_child_id(index);
126            if id.is_valid()
127                && let Some(node) = self.as_node(data).get_child(index)
128            {
129                cx.configure(node, id);
130            }
131        }
132    }
133
134    /// Update self using input data
135    ///
136    /// This method is called immediately after [`Self::configure`] and after
137    /// any input data is updated, before [`Layout::draw`] is called.
138    /// Typically this method is called immediately after the data is updated
139    /// but the call may be delayed until when the widget becomes visible.
140    ///
141    /// This method is called before [`Self::update_recurse`].
142    ///
143    /// The default implementation does nothing.
144    fn update(&mut self, cx: &mut ConfigCx, data: &Self::Data) {
145        let _ = (cx, data);
146    }
147
148    /// Update children
149    ///
150    /// This method is called after [`Self::update`]. It usually configures all
151    /// children. Children should be updated even if their data is `()` or is
152    /// unchanged.
153    ///
154    /// The default implementation updates children in the range
155    /// [`Tile::child_indices`]. This is usually sufficient.
156    ///
157    /// Use [`ConfigCx::update`].
158    fn update_recurse(&mut self, cx: &mut ConfigCx, data: &Self::Data) {
159        for index in self.child_indices().into_iter() {
160            if let Some(node) = self.as_node(data).get_child(index) {
161                cx.update(node);
162            }
163        }
164    }
165
166    /// Mouse focus handler
167    ///
168    /// Called when mouse moves over or leaves this widget.
169    /// (This is a low-level alternative
170    /// to [`Self::REDRAW_ON_MOUSE_OVER`] and [`Self::mouse_over_icon`].)
171    ///
172    /// `state` is true when the mouse is over this widget.
173    #[inline]
174    fn handle_mouse_over(&mut self, cx: &mut EventCx, state: bool) {
175        if Self::REDRAW_ON_MOUSE_OVER {
176            cx.redraw(&self);
177        }
178        if state && let Some(icon) = self.mouse_over_icon() {
179            cx.set_mouse_over_icon(icon);
180        }
181    }
182
183    /// Handle an [`Event`]
184    ///
185    /// This is the primary event handler (see [documentation](crate::event)).
186    ///
187    /// This method is called on the primary event target. In this case,
188    /// [`EventCx::last_child`] returns `None`.
189    ///
190    /// This method may also be called on ancestors during unwinding (if the
191    /// event remains [unused](Unused) and the event
192    /// [is reusable](Event::is_reusable)). In this case,
193    /// [`EventCx::last_child`] returns `Some(index)` with the index of the
194    /// child being unwound from.
195    ///
196    /// Default implementation of `handle_event`: do nothing; return
197    /// [`Unused`].
198    fn handle_event(&mut self, cx: &mut EventCx, data: &Self::Data, event: Event) -> IsUsed {
199        let _ = (cx, data, event);
200        Unused
201    }
202
203    /// Handler for messages from children/descendants
204    ///
205    /// This is the secondary event handler (see [documentation](crate::event)).
206    ///
207    /// It is implied that the stack contains at least one message.
208    /// Use [`EventCx::try_pop`] and/or [`EventCx::try_peek`].
209    ///
210    /// [`EventCx::last_child`] may be called to find the message's sender.
211    /// This may return [`None`] (if no child was visited, which implies that
212    /// the message was sent by `self`).
213    ///
214    /// The default implementation does nothing.
215    #[inline]
216    fn handle_messages(&mut self, cx: &mut EventCx, data: &Self::Data) {
217        let _ = (cx, data);
218    }
219
220    /// Handler for scrolling
221    ///
222    /// When, during [event handling](crate::event), a widget which is a strict
223    /// descendant of `self` (i.e. not `self`) calls [`EventCx::set_scroll`]
224    /// with a value other than [`Scroll::None`], this method is called.
225    ///
226    /// Note that [`Scroll::Rect`] values are in the child's coordinate space,
227    /// and must be translated to the widget's own coordinate space by this
228    /// method (this is not done by the default implementation since any widget
229    /// with non-zero translation very likely wants to implement this method
230    /// anyway).
231    ///
232    /// If the child is in an independent coordinate space, then this method
233    /// should call `cx.set_scroll(Scroll::None)` to avoid any reactions to
234    /// child's scroll requests.
235    ///
236    /// [`EventCx::last_child`] may be called to find the child responsible,
237    /// and should never return [`None`] (when called from this method).
238    ///
239    /// The default implementation does nothing.
240    #[inline]
241    fn handle_scroll(&mut self, cx: &mut EventCx, data: &Self::Data, scroll: Scroll) {
242        let _ = (cx, data, scroll);
243    }
244}