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 update(
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 ) {
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 ) -> 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_is_over = if let Some((mut nested, nested_layout)) =
186 element.overlay(layout, renderer).zip(layouts.next())
187 {
188 recurse(
189 &mut nested,
190 nested_layout,
191 event,
192 cursor,
193 renderer,
194 clipboard,
195 shell,
196 )
197 } else {
198 false
199 };
200
201 if shell.event_status() == event::Status::Ignored {
202 let is_over = nested_is_over
203 || cursor
204 .position()
205 .map(|cursor_position| {
206 element.is_over(
207 layout,
208 renderer,
209 cursor_position,
210 )
211 })
212 .unwrap_or_default();
213
214 element.update(
215 event,
216 layout,
217 if nested_is_over {
218 mouse::Cursor::Unavailable
219 } else {
220 cursor
221 },
222 renderer,
223 clipboard,
224 shell,
225 );
226
227 is_over
228 } else {
229 nested_is_over
230 }
231 } else {
232 false
233 }
234 }
235
236 let _ = recurse(
237 &mut self.overlay,
238 layout,
239 event,
240 cursor,
241 renderer,
242 clipboard,
243 shell,
244 );
245 }
246
247 pub fn mouse_interaction(
249 &mut self,
250 layout: Layout<'_>,
251 cursor: mouse::Cursor,
252 viewport: &Rectangle,
253 renderer: &Renderer,
254 ) -> mouse::Interaction {
255 fn recurse<Message, Theme, Renderer>(
256 element: &mut overlay::Element<'_, Message, Theme, Renderer>,
257 layout: Layout<'_>,
258 cursor: mouse::Cursor,
259 viewport: &Rectangle,
260 renderer: &Renderer,
261 ) -> Option<mouse::Interaction>
262 where
263 Renderer: renderer::Renderer,
264 {
265 let mut layouts = layout.children();
266
267 let layout = layouts.next()?;
268 let cursor_position = cursor.position()?;
269
270 if !element.is_over(layout, renderer, cursor_position) {
271 return None;
272 }
273
274 Some(
275 element
276 .overlay(layout, renderer)
277 .zip(layouts.next())
278 .and_then(|(mut overlay, layout)| {
279 recurse(
280 &mut overlay,
281 layout,
282 cursor,
283 viewport,
284 renderer,
285 )
286 })
287 .unwrap_or_else(|| {
288 element.mouse_interaction(
289 layout, cursor, viewport, renderer,
290 )
291 }),
292 )
293 }
294
295 recurse(&mut self.overlay, layout, cursor, viewport, renderer)
296 .unwrap_or_default()
297 }
298
299 pub fn is_over(
301 &mut self,
302 layout: Layout<'_>,
303 renderer: &Renderer,
304 cursor_position: Point,
305 ) -> bool {
306 fn recurse<Message, Theme, Renderer>(
307 element: &mut overlay::Element<'_, Message, Theme, Renderer>,
308 layout: Layout<'_>,
309 renderer: &Renderer,
310 cursor_position: Point,
311 ) -> bool
312 where
313 Renderer: renderer::Renderer,
314 {
315 let mut layouts = layout.children();
316
317 if let Some(layout) = layouts.next() {
318 if element.is_over(layout, renderer, cursor_position) {
319 return true;
320 }
321
322 if let Some((mut nested, nested_layout)) =
323 element.overlay(layout, renderer).zip(layouts.next())
324 {
325 recurse(
326 &mut nested,
327 nested_layout,
328 renderer,
329 cursor_position,
330 )
331 } else {
332 false
333 }
334 } else {
335 false
336 }
337 }
338
339 recurse(&mut self.overlay, layout, renderer, cursor_position)
340 }
341}