1use crate::event;
2use crate::mouse;
3use crate::overlay;
4use crate::renderer;
5use crate::widget;
6use crate::{Event, Shell};
7
8pub struct Group<'a, Message, Theme, Renderer> {
10 children: Vec<overlay::Element<'a, Message, Theme, Renderer>>,
11}
12
13fn sort_overlays<'a, Message, Theme, Renderer>(
14 children: &mut [overlay::Element<'a, Message, Theme, Renderer>],
15) where
16 Renderer: renderer::Renderer,
17{
18 use std::cmp;
19
20 children.sort_by(|a, b| {
21 a.as_overlay()
22 .index()
23 .partial_cmp(&b.as_overlay().index())
24 .unwrap_or(cmp::Ordering::Equal)
25 });
26}
27
28impl<'a, Message, Theme, Renderer> Group<'a, Message, Theme, Renderer>
29where
30 Renderer: renderer::Renderer,
31{
32 pub fn new(mut children: Vec<overlay::Element<'a, Message, Theme, Renderer>>) -> Self {
37 sort_overlays(&mut children);
38
39 Self { children }
40 }
41
42 pub fn draw(
44 &mut self,
45 renderer: &mut Renderer,
46 theme: &Theme,
47 style: &renderer::Style,
48 cursor: mouse::Cursor,
49 ) {
50 fn recurse<Message, Theme, Renderer>(
51 children: &mut [overlay::Element<'_, Message, Theme, Renderer>],
52 renderer: &mut Renderer,
53 theme: &Theme,
54 style: &renderer::Style,
55 cursor: mouse::Cursor,
56 ) where
57 Renderer: renderer::Renderer,
58 {
59 for element in children {
60 let is_over = cursor.position().is_some_and(|cursor_position| {
62 let nested = element.as_overlay_mut().overlay(renderer);
63
64 !nested.is_empty()
65 && Group::new(nested)
66 .mouse_interaction(mouse::Cursor::Available(cursor_position), renderer)
67 != mouse::Interaction::None
68 });
69
70 element.as_overlay().draw(
71 renderer,
72 theme,
73 style,
74 if is_over {
75 mouse::Cursor::Unavailable
76 } else {
77 cursor
78 },
79 );
80
81 let mut nested = element.as_overlay_mut().overlay(renderer);
82
83 if !nested.is_empty() {
84 sort_overlays(&mut nested);
85
86 recurse(&mut nested, renderer, theme, style, cursor);
87 }
88 }
89 }
90
91 recurse(&mut self.children, renderer, theme, style, cursor);
92 }
93
94 pub fn operate(&mut self, renderer: &Renderer, operation: &mut dyn widget::Operation) {
96 fn recurse<Message, Theme, Renderer>(
97 children: &mut [overlay::Element<'_, Message, Theme, Renderer>],
98 renderer: &Renderer,
99 operation: &mut dyn widget::Operation,
100 ) where
101 Renderer: renderer::Renderer,
102 {
103 for element in children {
104 let overlay = element.as_overlay_mut();
105
106 overlay.operate(renderer, operation);
107
108 let mut nested = overlay.overlay(renderer);
109
110 if !nested.is_empty() {
111 sort_overlays(&mut nested);
112
113 recurse(&mut nested, renderer, operation);
114 }
115 }
116 }
117
118 recurse(&mut self.children, renderer, operation);
119 }
120
121 pub fn update(
123 &mut self,
124 event: &Event,
125 cursor: mouse::Cursor,
126 renderer: &Renderer,
127 shell: &mut Shell<'_, Message>,
128 ) {
129 fn recurse<Message, Theme, Renderer>(
130 children: &mut [overlay::Element<'_, Message, Theme, Renderer>],
131 event: &Event,
132 cursor: mouse::Cursor,
133 renderer: &Renderer,
134 shell: &mut Shell<'_, Message>,
135 ) -> bool
136 where
137 Renderer: renderer::Renderer,
138 {
139 let mut is_over = false;
140
141 for element in children {
142 if shell.event_status() != event::Status::Ignored {
143 return is_over;
144 }
145
146 let overlay = element.as_overlay_mut();
147
148 let nested = overlay.overlay(renderer);
149 let nested_is_over = (!nested.is_empty())
150 .then_some(nested)
151 .map(|mut nested| {
152 sort_overlays(&mut nested);
153
154 recurse(&mut nested, event, cursor, renderer, shell)
155 })
156 .unwrap_or_default();
157
158 if shell.event_status() != event::Status::Ignored {
159 return nested_is_over || is_over;
160 }
161
162 let child_is_over = nested_is_over
163 || cursor.position().is_some_and(|cursor_position| {
164 overlay
165 .mouse_interaction(mouse::Cursor::Available(cursor_position), renderer)
166 != mouse::Interaction::None
167 });
168
169 overlay.update(
170 event,
171 if nested_is_over {
172 mouse::Cursor::Unavailable
173 } else {
174 cursor
175 },
176 renderer,
177 shell,
178 );
179
180 is_over |= child_is_over;
181 }
182
183 is_over
184 }
185
186 let _ = recurse(&mut self.children, event, cursor, renderer, shell);
187 }
188
189 pub fn mouse_interaction(
191 &mut self,
192 cursor: mouse::Cursor,
193 renderer: &Renderer,
194 ) -> mouse::Interaction {
195 fn recurse<Message, Theme, Renderer>(
196 children: &mut [overlay::Element<'_, Message, Theme, Renderer>],
197 cursor: mouse::Cursor,
198 renderer: &Renderer,
199 ) -> mouse::Interaction
200 where
201 Renderer: renderer::Renderer,
202 {
203 children
204 .iter_mut()
205 .map(|element| {
206 let overlay = element.as_overlay_mut();
207 let interaction = overlay.mouse_interaction(cursor, renderer);
208
209 let nested = overlay.overlay(renderer);
210 let nested_interaction = (!nested.is_empty())
211 .then_some(nested)
212 .map(|mut nested| {
213 sort_overlays(&mut nested);
214
215 recurse(&mut nested, cursor, renderer)
216 })
217 .unwrap_or_default();
218
219 nested_interaction.max(interaction)
220 })
221 .max()
222 .unwrap_or_default()
223 }
224
225 recurse(&mut self.children, cursor, renderer)
226 }
227}