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::event::{self, Event};
9use crate::layout;
10use crate::mouse;
11use crate::renderer;
12use crate::widget::{Operation, Tree};
13use crate::{Clipboard, 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 an [`crate::widget::Operation`] to the [`Overlay`].
39    fn operate(
40        &mut self,
41        _layout: Layout<'_>,
42        _renderer: &Renderer,
43        _operation: &mut dyn 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 on_event(
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    ) -> event::Status {
68        event::Status::Ignored
69    }
70
71    /// Returns the current [`mouse::Interaction`] of the [`Overlay`].
72    ///
73    /// By default, it returns [`mouse::Interaction::Idle`].
74    fn mouse_interaction(
75        &self,
76        _layout: Layout<'_>,
77        _cursor: mouse::Cursor,
78        _viewport: &Rectangle,
79        _renderer: &Renderer,
80    ) -> mouse::Interaction {
81        mouse::Interaction::None
82    }
83
84    /// Returns true if the cursor is over the [`Overlay`].
85    ///
86    /// By default, it returns true if the bounds of the `layout` contain
87    /// the `cursor_position`.
88    fn is_over(
89        &self,
90        layout: Layout<'_>,
91        _renderer: &Renderer,
92        cursor_position: Point,
93    ) -> bool {
94        layout.bounds().contains(cursor_position)
95    }
96
97    /// Returns the nested overlay of the [`Overlay`], if there is any.
98    fn overlay<'a>(
99        &'a mut self,
100        _layout: Layout<'_>,
101        _renderer: &Renderer,
102    ) -> Option<Element<'a, Message, Theme, Renderer>> {
103        None
104    }
105}
106
107/// Returns a [`Group`] of overlay [`Element`] children.
108///
109/// This method will generally only be used by advanced users that are
110/// implementing the [`Widget`](crate::Widget) trait.
111pub fn from_children<'a, Message, Theme, Renderer>(
112    children: &'a mut [crate::Element<'_, Message, Theme, Renderer>],
113    tree: &'a mut Tree,
114    layout: Layout<'_>,
115    renderer: &Renderer,
116    translation: Vector,
117) -> Option<Element<'a, Message, Theme, Renderer>>
118where
119    Renderer: crate::Renderer,
120{
121    let children = children
122        .iter_mut()
123        .zip(&mut tree.children)
124        .zip(layout.children())
125        .filter_map(|((child, state), c_layout)| {
126            child.as_widget_mut().overlay(
127                state,
128                c_layout.with_virtual_offset(layout.virtual_offset()),
129                renderer,
130                translation,
131            )
132        })
133        .collect::<Vec<_>>();
134
135    (!children.is_empty()).then(|| Group::with_children(children).overlay())
136}