iced_core/
overlay.rs

1//! Display interactive elements on top of other widgets.
2mod element;
3mod group;
4
5pub use element::Element;
6pub use group::Group;
7
8use crate::layout;
9use crate::mouse;
10use crate::renderer;
11use crate::widget;
12use crate::widget::Tree;
13use crate::{Clipboard, Event, Layout, Point, Rectangle, Shell, Size, Vector};
14
15/// An interactive component that can be displayed on top of other widgets.
16pub trait Overlay<Message, Theme, Renderer>
17where
18    Renderer: crate::Renderer,
19{
20    /// Returns the layout [`Node`] of the [`Overlay`].
21    ///
22    /// This [`Node`] is used by the runtime to compute the [`Layout`] of the
23    /// user interface.
24    ///
25    /// [`Node`]: layout::Node
26    fn layout(&mut self, renderer: &Renderer, bounds: Size) -> layout::Node;
27
28    /// Draws the [`Overlay`] using the associated `Renderer`.
29    fn draw(
30        &self,
31        renderer: &mut Renderer,
32        theme: &Theme,
33        style: &renderer::Style,
34        layout: Layout<'_>,
35        cursor: mouse::Cursor,
36    );
37
38    /// Applies a [`widget::Operation`] to the [`Overlay`].
39    fn operate(
40        &mut self,
41        _layout: Layout<'_>,
42        _renderer: &Renderer,
43        _operation: &mut dyn widget::Operation,
44    ) {
45    }
46
47    /// Processes a runtime [`Event`].
48    ///
49    /// It receives:
50    ///   * an [`Event`] describing user interaction
51    ///   * the computed [`Layout`] of the [`Overlay`]
52    ///   * the current cursor position
53    ///   * a mutable `Message` list, allowing the [`Overlay`] to produce
54    ///     new messages based on user interaction.
55    ///   * the `Renderer`
56    ///   * a [`Clipboard`], if available
57    ///
58    /// By default, it does nothing.
59    fn update(
60        &mut self,
61        _event: &Event,
62        _layout: Layout<'_>,
63        _cursor: mouse::Cursor,
64        _renderer: &Renderer,
65        _clipboard: &mut dyn Clipboard,
66        _shell: &mut Shell<'_, Message>,
67    ) {
68    }
69
70    /// Returns the current [`mouse::Interaction`] of the [`Overlay`].
71    ///
72    /// By default, it returns [`mouse::Interaction::Idle`].
73    fn mouse_interaction(
74        &self,
75        _layout: Layout<'_>,
76        _cursor: mouse::Cursor,
77        _viewport: &Rectangle,
78        _renderer: &Renderer,
79    ) -> mouse::Interaction {
80        mouse::Interaction::None
81    }
82
83    /// Returns true if the cursor is over the [`Overlay`].
84    ///
85    /// By default, it returns true if the bounds of the `layout` contain
86    /// the `cursor_position`.
87    fn is_over(
88        &self,
89        layout: Layout<'_>,
90        _renderer: &Renderer,
91        cursor_position: Point,
92    ) -> bool {
93        layout.bounds().contains(cursor_position)
94    }
95
96    /// Returns the nested overlay of the [`Overlay`], if there is any.
97    fn overlay<'a>(
98        &'a mut self,
99        _layout: Layout<'_>,
100        _renderer: &Renderer,
101    ) -> Option<Element<'a, Message, Theme, Renderer>> {
102        None
103    }
104
105    /// The index of the overlay.
106    ///
107    /// Overlays with a higher index will be rendered on top of overlays with
108    /// a lower index.
109    ///
110    /// By default, it returns `1.0`.
111    fn index(&self) -> f32 {
112        1.0
113    }
114}
115
116/// Returns a [`Group`] of overlay [`Element`] children.
117///
118/// This method will generally only be used by advanced users that are
119/// implementing the [`Widget`](crate::Widget) trait.
120pub fn from_children<'a, Message, Theme, Renderer>(
121    children: &'a mut [crate::Element<'_, Message, Theme, Renderer>],
122    tree: &'a mut Tree,
123    layout: Layout<'_>,
124    renderer: &Renderer,
125    viewport: &Rectangle,
126    translation: Vector,
127) -> Option<Element<'a, Message, Theme, Renderer>>
128where
129    Renderer: crate::Renderer,
130{
131    let children = children
132        .iter_mut()
133        .zip(&mut tree.children)
134        .zip(layout.children())
135        .filter_map(|((child, state), layout)| {
136            child.as_widget_mut().overlay(
137                state,
138                layout,
139                renderer,
140                viewport,
141                translation,
142            )
143        })
144        .collect::<Vec<_>>();
145
146    (!children.is_empty()).then(|| Group::with_children(children).overlay())
147}