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