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