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