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        children: Vec<overlay::Element<'a, Message, Theme, Renderer>>,
29    ) -> Self {
30        Group { children }
31    }
32
33    /// Adds an [`overlay::Element`] to the [`Group`].
34    pub fn push(
35        mut self,
36        child: impl Into<overlay::Element<'a, Message, Theme, Renderer>>,
37    ) -> Self {
38        self.children.push(child.into());
39        self
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.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.update(event, layout, cursor, renderer, clipboard, shell);
86        }
87    }
88
89    fn draw(
90        &self,
91        renderer: &mut Renderer,
92        theme: &Theme,
93        style: &renderer::Style,
94        layout: Layout<'_>,
95        cursor: mouse::Cursor,
96    ) {
97        for (child, layout) in self.children.iter().zip(layout.children()) {
98            child.draw(renderer, theme, style, layout, cursor);
99        }
100    }
101
102    fn mouse_interaction(
103        &self,
104        layout: Layout<'_>,
105        cursor: mouse::Cursor,
106        viewport: &Rectangle,
107        renderer: &Renderer,
108    ) -> mouse::Interaction {
109        self.children
110            .iter()
111            .zip(layout.children())
112            .map(|(child, layout)| {
113                child.mouse_interaction(layout, cursor, viewport, renderer)
114            })
115            .max()
116            .unwrap_or_default()
117    }
118
119    fn operate(
120        &mut self,
121        layout: Layout<'_>,
122        renderer: &Renderer,
123        operation: &mut dyn widget::Operation,
124    ) {
125        operation.container(None, layout.bounds(), &mut |operation| {
126            self.children.iter_mut().zip(layout.children()).for_each(
127                |(child, layout)| {
128                    child.operate(layout, renderer, operation);
129                },
130            );
131        });
132    }
133
134    fn is_over(
135        &self,
136        layout: Layout<'_>,
137        renderer: &Renderer,
138        cursor_position: Point,
139    ) -> bool {
140        self.children
141            .iter()
142            .zip(layout.children())
143            .any(|(child, layout)| {
144                child.is_over(layout, renderer, cursor_position)
145            })
146    }
147
148    fn overlay<'a>(
149        &'a mut self,
150        layout: Layout<'_>,
151        renderer: &Renderer,
152    ) -> Option<overlay::Element<'a, Message, Theme, Renderer>> {
153        let children = self
154            .children
155            .iter_mut()
156            .zip(layout.children())
157            .filter_map(|(child, layout)| child.overlay(layout, renderer))
158            .collect::<Vec<_>>();
159
160        (!children.is_empty()).then(|| Group::with_children(children).overlay())
161    }
162}
163
164impl<'a, Message, Theme, Renderer> From<Group<'a, Message, Theme, Renderer>>
165    for overlay::Element<'a, Message, Theme, Renderer>
166where
167    Message: 'a,
168    Theme: 'a,
169    Renderer: 'a + crate::Renderer,
170{
171    fn from(group: Group<'a, Message, Theme, Renderer>) -> Self {
172        group.overlay()
173    }
174}