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