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