iced_core/overlay/
group.rs

1use crate::layout;
2use crate::mouse;
3use crate::overlay;
4use crate::renderer;
5use crate::widget;
6use crate::{Clipboard, Event, Layout, Overlay, Point, Rectangle, Shell, Size};
7
8/// An [`Overlay`] container that displays multiple overlay [`overlay::Element`]
9/// children.
10#[allow(missing_debug_implementations)]
11pub struct Group<'a, Message, Theme, Renderer> {
12    children: Vec<overlay::Element<'a, Message, Theme, Renderer>>,
13}
14
15impl<'a, Message, Theme, Renderer> Group<'a, Message, Theme, Renderer>
16where
17    Message: 'a,
18    Theme: 'a,
19    Renderer: 'a + crate::Renderer,
20{
21    /// Creates an empty [`Group`].
22    pub fn new() -> Self {
23        Self::default()
24    }
25
26    /// Creates a [`Group`] with the given elements.
27    pub fn with_children(
28        mut children: Vec<overlay::Element<'a, Message, Theme, Renderer>>,
29    ) -> Self {
30        use std::cmp;
31
32        children.sort_unstable_by(|a, b| {
33            a.as_overlay()
34                .index()
35                .partial_cmp(&b.as_overlay().index())
36                .unwrap_or(cmp::Ordering::Equal)
37        });
38
39        Group { children }
40    }
41
42    /// Turns the [`Group`] into an overlay [`overlay::Element`].
43    pub fn overlay(self) -> overlay::Element<'a, Message, Theme, Renderer> {
44        overlay::Element::new(Box::new(self))
45    }
46}
47
48impl<'a, Message, Theme, Renderer> Default
49    for Group<'a, Message, Theme, Renderer>
50where
51    Message: 'a,
52    Theme: 'a,
53    Renderer: 'a + crate::Renderer,
54{
55    fn default() -> Self {
56        Self::with_children(Vec::new())
57    }
58}
59
60impl<Message, Theme, Renderer> Overlay<Message, Theme, Renderer>
61    for Group<'_, Message, Theme, Renderer>
62where
63    Renderer: crate::Renderer,
64{
65    fn layout(&mut self, renderer: &Renderer, bounds: Size) -> layout::Node {
66        layout::Node::with_children(
67            bounds,
68            self.children
69                .iter_mut()
70                .map(|child| child.as_overlay_mut().layout(renderer, bounds))
71                .collect(),
72        )
73    }
74
75    fn update(
76        &mut self,
77        event: &Event,
78        layout: Layout<'_>,
79        cursor: mouse::Cursor,
80        renderer: &Renderer,
81        clipboard: &mut dyn Clipboard,
82        shell: &mut Shell<'_, Message>,
83    ) {
84        for (child, layout) in self.children.iter_mut().zip(layout.children()) {
85            child
86                .as_overlay_mut()
87                .update(event, layout, cursor, renderer, clipboard, shell);
88        }
89    }
90
91    fn draw(
92        &self,
93        renderer: &mut Renderer,
94        theme: &Theme,
95        style: &renderer::Style,
96        layout: Layout<'_>,
97        cursor: mouse::Cursor,
98    ) {
99        for (child, layout) in self.children.iter().zip(layout.children()) {
100            child
101                .as_overlay()
102                .draw(renderer, theme, style, layout, cursor);
103        }
104    }
105
106    fn mouse_interaction(
107        &self,
108        layout: Layout<'_>,
109        cursor: mouse::Cursor,
110        viewport: &Rectangle,
111        renderer: &Renderer,
112    ) -> mouse::Interaction {
113        self.children
114            .iter()
115            .zip(layout.children())
116            .map(|(child, layout)| {
117                child
118                    .as_overlay()
119                    .mouse_interaction(layout, cursor, viewport, renderer)
120            })
121            .max()
122            .unwrap_or_default()
123    }
124
125    fn operate(
126        &mut self,
127        layout: Layout<'_>,
128        renderer: &Renderer,
129        operation: &mut dyn widget::Operation,
130    ) {
131        operation.container(None, layout.bounds(), &mut |operation| {
132            self.children.iter_mut().zip(layout.children()).for_each(
133                |(child, layout)| {
134                    child.as_overlay_mut().operate(layout, renderer, operation);
135                },
136            );
137        });
138    }
139
140    fn is_over(
141        &self,
142        layout: Layout<'_>,
143        renderer: &Renderer,
144        cursor_position: Point,
145    ) -> bool {
146        self.children
147            .iter()
148            .zip(layout.children())
149            .any(|(child, layout)| {
150                child
151                    .as_overlay()
152                    .is_over(layout, renderer, cursor_position)
153            })
154    }
155
156    fn overlay<'a>(
157        &'a mut self,
158        layout: Layout<'_>,
159        renderer: &Renderer,
160    ) -> Option<overlay::Element<'a, Message, Theme, Renderer>> {
161        let children = self
162            .children
163            .iter_mut()
164            .zip(layout.children())
165            .filter_map(|(child, layout)| {
166                child.as_overlay_mut().overlay(layout, renderer)
167            })
168            .collect::<Vec<_>>();
169
170        (!children.is_empty()).then(|| Group::with_children(children).overlay())
171    }
172
173    fn index(&self) -> f32 {
174        self.children
175            .first()
176            .map(|child| child.as_overlay().index())
177            .unwrap_or(1.0)
178    }
179}
180
181impl<'a, Message, Theme, Renderer> From<Group<'a, Message, Theme, Renderer>>
182    for overlay::Element<'a, Message, Theme, Renderer>
183where
184    Message: 'a,
185    Theme: 'a,
186    Renderer: 'a + crate::Renderer,
187{
188    fn from(group: Group<'a, Message, Theme, Renderer>) -> Self {
189        group.overlay()
190    }
191}