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