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 layer.as_widget().layout(tree, renderer, &limits)
177 },
178 ))
179 .collect();
180
181 layout::Node::with_children(size, nodes)
182 }
183
184 fn operate(
185 &self,
186 tree: &mut Tree,
187 layout: Layout<'_>,
188 renderer: &Renderer,
189 operation: &mut dyn Operation,
190 ) {
191 operation.container(None, layout.bounds(), &mut |operation| {
192 self.children
193 .iter()
194 .zip(&mut tree.children)
195 .zip(layout.children())
196 .for_each(|((child, state), layout)| {
197 child
198 .as_widget()
199 .operate(state, layout, renderer, operation);
200 });
201 });
202 }
203
204 fn update(
205 &mut self,
206 tree: &mut Tree,
207 event: &Event,
208 layout: Layout<'_>,
209 mut cursor: mouse::Cursor,
210 renderer: &Renderer,
211 clipboard: &mut dyn Clipboard,
212 shell: &mut Shell<'_, Message>,
213 viewport: &Rectangle,
214 ) {
215 let is_over = cursor.is_over(layout.bounds());
216 let end = self.children.len() - 1;
217
218 for (i, ((child, state), layout)) in self
219 .children
220 .iter_mut()
221 .rev()
222 .zip(tree.children.iter_mut().rev())
223 .zip(layout.children().rev())
224 .enumerate()
225 {
226 child.as_widget_mut().update(
227 state, event, layout, cursor, renderer, clipboard, shell,
228 viewport,
229 );
230
231 if shell.is_event_captured() {
232 return;
233 }
234
235 if i < end && is_over && !cursor.is_levitating() {
236 let interaction = child.as_widget().mouse_interaction(
237 state, layout, cursor, viewport, renderer,
238 );
239
240 if interaction != mouse::Interaction::None {
241 cursor = cursor.levitate();
242 }
243 }
244 }
245 }
246
247 fn mouse_interaction(
248 &self,
249 tree: &Tree,
250 layout: Layout<'_>,
251 cursor: mouse::Cursor,
252 viewport: &Rectangle,
253 renderer: &Renderer,
254 ) -> mouse::Interaction {
255 self.children
256 .iter()
257 .rev()
258 .zip(tree.children.iter().rev())
259 .zip(layout.children().rev())
260 .map(|((child, state), layout)| {
261 child.as_widget().mouse_interaction(
262 state, layout, cursor, viewport, renderer,
263 )
264 })
265 .find(|&interaction| interaction != mouse::Interaction::None)
266 .unwrap_or_default()
267 }
268
269 fn draw(
270 &self,
271 tree: &Tree,
272 renderer: &mut Renderer,
273 theme: &Theme,
274 style: &renderer::Style,
275 layout: Layout<'_>,
276 cursor: mouse::Cursor,
277 viewport: &Rectangle,
278 ) {
279 if let Some(clipped_viewport) = layout.bounds().intersection(viewport) {
280 let layers_below = if cursor.is_over(layout.bounds()) {
281 self.children
282 .iter()
283 .rev()
284 .zip(tree.children.iter().rev())
285 .zip(layout.children().rev())
286 .position(|((layer, state), layout)| {
287 let interaction = layer.as_widget().mouse_interaction(
288 state, layout, cursor, viewport, renderer,
289 );
290
291 interaction != mouse::Interaction::None
292 })
293 .map(|i| self.children.len() - i - 1)
294 .unwrap_or_default()
295 } else {
296 0
297 };
298
299 let mut layers = self
300 .children
301 .iter()
302 .zip(&tree.children)
303 .zip(layout.children())
304 .enumerate();
305
306 let layers = layers.by_ref();
307
308 let mut draw_layer =
309 |i,
310 layer: &Element<'a, Message, Theme, Renderer>,
311 state,
312 layout,
313 cursor| {
314 if i > 0 {
315 renderer.with_layer(clipped_viewport, |renderer| {
316 layer.as_widget().draw(
317 state,
318 renderer,
319 theme,
320 style,
321 layout,
322 cursor,
323 &clipped_viewport,
324 );
325 });
326 } else {
327 layer.as_widget().draw(
328 state,
329 renderer,
330 theme,
331 style,
332 layout,
333 cursor,
334 &clipped_viewport,
335 );
336 }
337 };
338
339 for (i, ((layer, state), layout)) in layers.take(layers_below) {
340 draw_layer(i, layer, state, layout, mouse::Cursor::Unavailable);
341 }
342
343 for (i, ((layer, state), layout)) in layers {
344 draw_layer(i, layer, state, layout, cursor);
345 }
346 }
347 }
348
349 fn overlay<'b>(
350 &'b mut self,
351 tree: &'b mut Tree,
352 layout: Layout<'b>,
353 renderer: &Renderer,
354 viewport: &Rectangle,
355 translation: Vector,
356 ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
357 overlay::from_children(
358 &mut self.children,
359 tree,
360 layout,
361 renderer,
362 viewport,
363 translation,
364 )
365 }
366}
367
368impl<'a, Message, Theme, Renderer> From<Stack<'a, Message, Theme, Renderer>>
369 for Element<'a, Message, Theme, Renderer>
370where
371 Message: 'a,
372 Theme: 'a,
373 Renderer: crate::core::Renderer + 'a,
374{
375 fn from(stack: Stack<'a, Message, Theme, Renderer>) -> Self {
376 Self::new(stack)
377 }
378}