1use crate::event;
2use crate::layout;
3use crate::mouse;
4use crate::overlay;
5use crate::renderer;
6use crate::widget;
7use crate::{Event, Layout, Shell, Size};
8
9pub struct Nested<'a, Message, Theme, Renderer> {
11 children: Vec<overlay::Element<'a, Message, Theme, Renderer>>,
12}
13
14fn sort_overlays<'a, Message, Theme, Renderer>(
15 children: &mut [overlay::Element<'a, Message, Theme, Renderer>],
16) where
17 Renderer: renderer::Renderer,
18{
19 use std::cmp;
20
21 children.sort_by(|a, b| {
22 a.as_overlay()
23 .index()
24 .partial_cmp(&b.as_overlay().index())
25 .unwrap_or(cmp::Ordering::Equal)
26 });
27}
28
29impl<'a, Message, Theme, Renderer> Nested<'a, Message, Theme, Renderer>
30where
31 Renderer: renderer::Renderer,
32{
33 pub fn new(mut children: Vec<overlay::Element<'a, Message, Theme, Renderer>>) -> Self {
38 sort_overlays(&mut children);
39
40 Self { children }
41 }
42
43 pub fn layout(&mut self, renderer: &Renderer, bounds: Size) -> layout::Node {
47 fn recurse<Message, Theme, Renderer>(
48 children: &mut [overlay::Element<'_, Message, Theme, Renderer>],
49 renderer: &Renderer,
50 bounds: Size,
51 ) -> layout::Node
52 where
53 Renderer: renderer::Renderer,
54 {
55 let children = children
56 .iter_mut()
57 .map(|element| {
58 let overlay = element.as_overlay_mut();
59 let node = overlay.layout(renderer, bounds);
60
61 let mut nested = overlay.overlay(Layout::new(&node), renderer);
62
63 if nested.is_empty() {
64 drop(nested);
65
66 layout::Node::with_children(node.size(), vec![node])
67 } else {
68 sort_overlays(&mut nested);
69
70 let nested_node = recurse(&mut nested, renderer, bounds);
71 drop(nested);
72
73 layout::Node::with_children(node.size(), vec![node, nested_node])
74 }
75 })
76 .collect();
77
78 layout::Node::with_children(bounds, children)
79 }
80
81 recurse(&mut self.children, renderer, bounds)
82 }
83
84 pub fn draw(
86 &mut self,
87 renderer: &mut Renderer,
88 theme: &Theme,
89 style: &renderer::Style,
90 layout: Layout<'_>,
91 cursor: mouse::Cursor,
92 ) {
93 fn recurse<Message, Theme, Renderer>(
94 children: &mut [overlay::Element<'_, Message, Theme, Renderer>],
95 layout: Layout<'_>,
96 renderer: &mut Renderer,
97 theme: &Theme,
98 style: &renderer::Style,
99 cursor: mouse::Cursor,
100 ) where
101 Renderer: renderer::Renderer,
102 {
103 for (element, wrap_layout) in children.iter_mut().zip(layout.children()) {
104 let mut layouts = wrap_layout.children();
105
106 let Some(layout) = layouts.next() else {
107 continue;
108 };
109 let nested_layout = layouts.next();
110
111 let is_over = cursor.position().zip(nested_layout).is_some_and(
113 |(cursor_position, nested_layout)| {
114 let nested = element.as_overlay_mut().overlay(layout, renderer);
115
116 !nested.is_empty()
117 && Nested::new(nested).mouse_interaction(
118 nested_layout,
119 mouse::Cursor::Available(cursor_position),
120 renderer,
121 ) != mouse::Interaction::None
122 },
123 );
124
125 renderer.with_layer(layout.bounds(), |renderer| {
126 element.as_overlay().draw(
127 renderer,
128 theme,
129 style,
130 layout,
131 if is_over {
132 mouse::Cursor::Unavailable
133 } else {
134 cursor
135 },
136 );
137 });
138
139 if let Some(nested_layout) = nested_layout {
140 let mut nested = element.as_overlay_mut().overlay(layout, renderer);
141
142 if !nested.is_empty() {
143 sort_overlays(&mut nested);
144
145 recurse(&mut nested, nested_layout, renderer, theme, style, cursor);
146 }
147 }
148 }
149 }
150
151 recurse(&mut self.children, layout, renderer, theme, style, cursor);
152 }
153
154 pub fn operate(
156 &mut self,
157 layout: Layout<'_>,
158 renderer: &Renderer,
159 operation: &mut dyn widget::Operation,
160 ) {
161 fn recurse<Message, Theme, Renderer>(
162 children: &mut [overlay::Element<'_, Message, Theme, Renderer>],
163 layout: Layout<'_>,
164 renderer: &Renderer,
165 operation: &mut dyn widget::Operation,
166 ) where
167 Renderer: renderer::Renderer,
168 {
169 for (element, wrap_layout) in children.iter_mut().zip(layout.children()) {
170 let mut layouts = wrap_layout.children();
171
172 let Some(layout) = layouts.next() else {
173 continue;
174 };
175 let nested_layout = layouts.next();
176
177 let overlay = element.as_overlay_mut();
178
179 overlay.operate(layout, renderer, operation);
180
181 if let Some(nested_layout) = nested_layout {
182 let mut nested = overlay.overlay(layout, renderer);
183
184 if !nested.is_empty() {
185 sort_overlays(&mut nested);
186
187 recurse(&mut nested, nested_layout, renderer, operation);
188 }
189 }
190 }
191 }
192
193 recurse(&mut self.children, layout, renderer, operation);
194 }
195
196 pub fn update(
198 &mut self,
199 event: &Event,
200 layout: Layout<'_>,
201 cursor: mouse::Cursor,
202 renderer: &Renderer,
203 shell: &mut Shell<'_, Message>,
204 ) {
205 fn recurse<Message, Theme, Renderer>(
206 children: &mut [overlay::Element<'_, Message, Theme, Renderer>],
207 layout: Layout<'_>,
208 event: &Event,
209 cursor: mouse::Cursor,
210 renderer: &Renderer,
211 shell: &mut Shell<'_, Message>,
212 ) -> bool
213 where
214 Renderer: renderer::Renderer,
215 {
216 let mut is_over = false;
217
218 for (element, wrap_layout) in children.iter_mut().zip(layout.children()) {
219 if shell.event_status() != event::Status::Ignored {
220 return is_over;
221 }
222
223 let mut layouts = wrap_layout.children();
224
225 let Some(layout) = layouts.next() else {
226 continue;
227 };
228 let nested_layout = layouts.next();
229
230 let overlay = element.as_overlay_mut();
231
232 let nested = overlay.overlay(layout, renderer);
233 let nested_is_over = (!nested.is_empty())
234 .then_some(nested)
235 .zip(nested_layout)
236 .map(|(mut nested, nested_layout)| {
237 sort_overlays(&mut nested);
238
239 recurse(&mut nested, nested_layout, event, cursor, renderer, shell)
240 })
241 .unwrap_or_default();
242
243 if shell.event_status() != event::Status::Ignored {
244 return nested_is_over || is_over;
245 }
246
247 let child_is_over = nested_is_over
248 || cursor.position().is_some_and(|cursor_position| {
249 overlay.mouse_interaction(
250 layout,
251 mouse::Cursor::Available(cursor_position),
252 renderer,
253 ) != mouse::Interaction::None
254 });
255
256 overlay.update(
257 event,
258 layout,
259 if nested_is_over {
260 mouse::Cursor::Unavailable
261 } else {
262 cursor
263 },
264 renderer,
265 shell,
266 );
267
268 is_over |= child_is_over;
269 }
270
271 is_over
272 }
273
274 let _ = recurse(&mut self.children, layout, event, cursor, renderer, shell);
275 }
276
277 pub fn mouse_interaction(
279 &mut self,
280 layout: Layout<'_>,
281 cursor: mouse::Cursor,
282 renderer: &Renderer,
283 ) -> mouse::Interaction {
284 fn recurse<Message, Theme, Renderer>(
285 children: &mut [overlay::Element<'_, Message, Theme, Renderer>],
286 layout: Layout<'_>,
287 cursor: mouse::Cursor,
288 renderer: &Renderer,
289 ) -> mouse::Interaction
290 where
291 Renderer: renderer::Renderer,
292 {
293 children
294 .iter_mut()
295 .zip(layout.children())
296 .map(|(element, wrap_layout)| {
297 let mut layouts = wrap_layout.children();
298
299 let Some(layout) = layouts.next() else {
300 return mouse::Interaction::None;
301 };
302 let nested_layout = layouts.next();
303
304 let overlay = element.as_overlay_mut();
305 let interaction = overlay.mouse_interaction(layout, cursor, renderer);
306
307 let nested = overlay.overlay(layout, renderer);
308 let nested_interaction = (!nested.is_empty())
309 .then_some(nested)
310 .zip(nested_layout)
311 .map(|(mut nested, nested_layout)| {
312 sort_overlays(&mut nested);
313
314 recurse(&mut nested, nested_layout, cursor, renderer)
315 })
316 .unwrap_or_default();
317
318 nested_interaction.max(interaction)
319 })
320 .max()
321 .unwrap_or_default()
322 }
323
324 recurse(&mut self.children, layout, cursor, renderer)
325 }
326}