iced_core/overlay/
group.rs

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