1use crate::core::layout;
3use crate::core::mouse;
4use crate::core::overlay;
5use crate::core::renderer;
6use crate::core::widget::{Operation, Tree};
7use crate::core::{
8 Clipboard, Element, Event, Layout, Length, Rectangle, Shell, Size, Vector,
9 Widget,
10};
11
12pub struct Stack<'a, Message, Theme = crate::Theme, Renderer = crate::Renderer>
21{
22 width: Length,
23 height: Length,
24 children: Vec<Element<'a, Message, Theme, Renderer>>,
25 clip: bool,
26}
27
28impl<'a, Message, Theme, Renderer> Stack<'a, Message, Theme, Renderer>
29where
30 Renderer: crate::core::Renderer,
31{
32 pub fn new() -> Self {
34 Self::from_vec(Vec::new())
35 }
36
37 pub fn with_capacity(capacity: usize) -> Self {
39 Self::from_vec(Vec::with_capacity(capacity))
40 }
41
42 pub fn with_children(
44 children: impl IntoIterator<Item = Element<'a, Message, Theme, Renderer>>,
45 ) -> Self {
46 let iterator = children.into_iter();
47
48 Self::with_capacity(iterator.size_hint().0).extend(iterator)
49 }
50
51 pub fn from_vec(
59 children: Vec<Element<'a, Message, Theme, Renderer>>,
60 ) -> Self {
61 Self {
62 width: Length::Shrink,
63 height: Length::Shrink,
64 children,
65 clip: false,
66 }
67 }
68
69 pub fn width(mut self, width: impl Into<Length>) -> Self {
71 self.width = width.into();
72 self
73 }
74
75 pub fn height(mut self, height: impl Into<Length>) -> Self {
77 self.height = height.into();
78 self
79 }
80
81 pub fn push(
83 mut self,
84 child: impl Into<Element<'a, Message, Theme, Renderer>>,
85 ) -> Self {
86 let child = child.into();
87 let child_size = child.as_widget().size_hint();
88
89 if !child_size.is_void() {
90 if self.children.is_empty() {
91 self.width = self.width.enclose(child_size.width);
92 self.height = self.height.enclose(child_size.height);
93 }
94
95 self.children.push(child);
96 }
97
98 self
99 }
100
101 pub fn extend(
103 self,
104 children: impl IntoIterator<Item = Element<'a, Message, Theme, Renderer>>,
105 ) -> Self {
106 children.into_iter().fold(self, Self::push)
107 }
108
109 pub fn clip(mut self, clip: bool) -> Self {
115 self.clip = clip;
116 self
117 }
118}
119
120impl<Message, Renderer> Default for Stack<'_, Message, Renderer>
121where
122 Renderer: crate::core::Renderer,
123{
124 fn default() -> Self {
125 Self::new()
126 }
127}
128
129impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
130 for Stack<'a, Message, Theme, Renderer>
131where
132 Renderer: crate::core::Renderer,
133{
134 fn children(&self) -> Vec<Tree> {
135 self.children.iter().map(Tree::new).collect()
136 }
137
138 fn diff(&self, tree: &mut Tree) {
139 tree.diff_children(&self.children);
140 }
141
142 fn size(&self) -> Size<Length> {
143 Size {
144 width: self.width,
145 height: self.height,
146 }
147 }
148
149 fn layout(
150 &mut self,
151 tree: &mut Tree,
152 renderer: &Renderer,
153 limits: &layout::Limits,
154 ) -> layout::Node {
155 let limits = limits.width(self.width).height(self.height);
156
157 if self.children.is_empty() {
158 return layout::Node::new(limits.resolve(
159 self.width,
160 self.height,
161 Size::ZERO,
162 ));
163 }
164
165 let base = self.children[0].as_widget_mut().layout(
166 &mut tree.children[0],
167 renderer,
168 &limits,
169 );
170
171 let size = limits.resolve(self.width, self.height, base.size());
172 let limits = layout::Limits::new(Size::ZERO, size);
173
174 let nodes = std::iter::once(base)
175 .chain(
176 self.children[1..]
177 .iter_mut()
178 .zip(&mut tree.children[1..])
179 .map(|(layer, tree)| {
180 layer.as_widget_mut().layout(tree, renderer, &limits)
181 }),
182 )
183 .collect();
184
185 layout::Node::with_children(size, nodes)
186 }
187
188 fn operate(
189 &mut self,
190 tree: &mut Tree,
191 layout: Layout<'_>,
192 renderer: &Renderer,
193 operation: &mut dyn Operation,
194 ) {
195 operation.container(None, layout.bounds());
196 operation.traverse(&mut |operation| {
197 self.children
198 .iter_mut()
199 .zip(&mut tree.children)
200 .zip(layout.children())
201 .for_each(|((child, state), layout)| {
202 child
203 .as_widget_mut()
204 .operate(state, layout, renderer, operation);
205 });
206 });
207 }
208
209 fn update(
210 &mut self,
211 tree: &mut Tree,
212 event: &Event,
213 layout: Layout<'_>,
214 mut cursor: mouse::Cursor,
215 renderer: &Renderer,
216 clipboard: &mut dyn Clipboard,
217 shell: &mut Shell<'_, Message>,
218 viewport: &Rectangle,
219 ) {
220 if self.children.is_empty() {
221 return;
222 }
223
224 let is_over = cursor.is_over(layout.bounds());
225 let end = self.children.len() - 1;
226
227 for (i, ((child, state), layout)) in self
228 .children
229 .iter_mut()
230 .rev()
231 .zip(tree.children.iter_mut().rev())
232 .zip(layout.children().rev())
233 .enumerate()
234 {
235 child.as_widget_mut().update(
236 state, event, layout, cursor, renderer, clipboard, shell,
237 viewport,
238 );
239
240 if shell.is_event_captured() {
241 return;
242 }
243
244 if i < end && is_over && !cursor.is_levitating() {
245 let interaction = child.as_widget().mouse_interaction(
246 state, layout, cursor, viewport, renderer,
247 );
248
249 if interaction != mouse::Interaction::None {
250 cursor = cursor.levitate();
251 }
252 }
253 }
254 }
255
256 fn mouse_interaction(
257 &self,
258 tree: &Tree,
259 layout: Layout<'_>,
260 cursor: mouse::Cursor,
261 viewport: &Rectangle,
262 renderer: &Renderer,
263 ) -> mouse::Interaction {
264 self.children
265 .iter()
266 .rev()
267 .zip(tree.children.iter().rev())
268 .zip(layout.children().rev())
269 .map(|((child, state), layout)| {
270 child.as_widget().mouse_interaction(
271 state, layout, cursor, viewport, renderer,
272 )
273 })
274 .find(|&interaction| interaction != mouse::Interaction::None)
275 .unwrap_or_default()
276 }
277
278 fn draw(
279 &self,
280 tree: &Tree,
281 renderer: &mut Renderer,
282 theme: &Theme,
283 style: &renderer::Style,
284 layout: Layout<'_>,
285 cursor: mouse::Cursor,
286 viewport: &Rectangle,
287 ) {
288 if let Some(clipped_viewport) = layout.bounds().intersection(viewport) {
289 let viewport = if self.clip {
290 &clipped_viewport
291 } else {
292 viewport
293 };
294
295 let layers_below = if cursor.is_over(layout.bounds()) {
296 self.children
297 .iter()
298 .rev()
299 .zip(tree.children.iter().rev())
300 .zip(layout.children().rev())
301 .position(|((layer, state), layout)| {
302 let interaction = layer.as_widget().mouse_interaction(
303 state, layout, cursor, viewport, renderer,
304 );
305
306 interaction != mouse::Interaction::None
307 })
308 .map(|i| self.children.len() - i - 1)
309 .unwrap_or_default()
310 } else {
311 0
312 };
313
314 let mut layers = self
315 .children
316 .iter()
317 .zip(&tree.children)
318 .zip(layout.children())
319 .enumerate();
320
321 let layers = layers.by_ref();
322
323 let mut draw_layer =
324 |i,
325 layer: &Element<'a, Message, Theme, Renderer>,
326 state,
327 layout,
328 cursor| {
329 if i > 0 {
330 renderer.with_layer(*viewport, |renderer| {
331 layer.as_widget().draw(
332 state, renderer, theme, style, layout, cursor,
333 viewport,
334 );
335 });
336 } else {
337 layer.as_widget().draw(
338 state, renderer, theme, style, layout, cursor,
339 viewport,
340 );
341 }
342 };
343
344 for (i, ((layer, state), layout)) in layers.take(layers_below) {
345 draw_layer(i, layer, state, layout, mouse::Cursor::Unavailable);
346 }
347
348 for (i, ((layer, state), layout)) in layers {
349 draw_layer(i, layer, state, layout, cursor);
350 }
351 }
352 }
353
354 fn overlay<'b>(
355 &'b mut self,
356 tree: &'b mut Tree,
357 layout: Layout<'b>,
358 renderer: &Renderer,
359 viewport: &Rectangle,
360 translation: Vector,
361 ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
362 overlay::from_children(
363 &mut self.children,
364 tree,
365 layout,
366 renderer,
367 viewport,
368 translation,
369 )
370 }
371}
372
373impl<'a, Message, Theme, Renderer> From<Stack<'a, Message, Theme, Renderer>>
374 for Element<'a, Message, Theme, Renderer>
375where
376 Message: 'a,
377 Theme: 'a,
378 Renderer: crate::core::Renderer + 'a,
379{
380 fn from(stack: Stack<'a, Message, Theme, Renderer>) -> Self {
381 Self::new(stack)
382 }
383}