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