Skip to main content

iced_core/overlay/
group.rs

1use crate::layout;
2use crate::mouse;
3use crate::overlay;
4use crate::renderer;
5use crate::widget;
6use crate::{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        shell: &mut Shell<'_, Message>,
80    ) {
81        for (child, layout) in self.children.iter_mut().zip(layout.children()) {
82            child
83                .as_overlay_mut()
84                .update(event, layout, cursor, renderer, shell);
85        }
86    }
87
88    fn draw(
89        &self,
90        renderer: &mut Renderer,
91        theme: &Theme,
92        style: &renderer::Style,
93        layout: Layout<'_>,
94        cursor: mouse::Cursor,
95    ) {
96        for (child, layout) in self.children.iter().zip(layout.children()) {
97            child
98                .as_overlay()
99                .draw(renderer, theme, style, layout, cursor);
100        }
101    }
102
103    fn mouse_interaction(
104        &self,
105        layout: Layout<'_>,
106        cursor: mouse::Cursor,
107        renderer: &Renderer,
108    ) -> mouse::Interaction {
109        self.children
110            .iter()
111            .zip(layout.children())
112            .map(|(child, layout)| {
113                child
114                    .as_overlay()
115                    .mouse_interaction(layout, cursor, renderer)
116            })
117            .max()
118            .unwrap_or_default()
119    }
120
121    fn operate(
122        &mut self,
123        layout: Layout<'_>,
124        renderer: &Renderer,
125        operation: &mut dyn widget::Operation,
126    ) {
127        operation.traverse(&mut |operation| {
128            self.children
129                .iter_mut()
130                .zip(layout.children())
131                .for_each(|(child, layout)| {
132                    child.as_overlay_mut().operate(layout, renderer, operation);
133                });
134        });
135    }
136
137    fn overlay<'a>(
138        &'a mut self,
139        layout: Layout<'a>,
140        renderer: &Renderer,
141    ) -> Option<overlay::Element<'a, Message, Theme, Renderer>> {
142        let children = self
143            .children
144            .iter_mut()
145            .zip(layout.children())
146            .filter_map(|(child, layout)| child.as_overlay_mut().overlay(layout, renderer))
147            .collect::<Vec<_>>();
148
149        (!children.is_empty()).then(|| Group::with_children(children).overlay())
150    }
151
152    fn index(&self) -> f32 {
153        self.children
154            .first()
155            .map(|child| child.as_overlay().index())
156            .unwrap_or(1.0)
157    }
158}
159
160impl<'a, Message, Theme, Renderer> From<Group<'a, Message, Theme, Renderer>>
161    for overlay::Element<'a, Message, Theme, Renderer>
162where
163    Message: 'a,
164    Theme: 'a,
165    Renderer: 'a + crate::Renderer,
166{
167    fn from(group: Group<'a, Message, Theme, Renderer>) -> Self {
168        group.overlay()
169    }
170}