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