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#[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 pub fn new() -> Self {
23 Self::default()
24 }
25
26 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 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}