veloren_voxygen/ui/ice/widget/
stack.rs1use iced::{Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, layout};
3use std::hash::Hash;
4
5pub struct Stack<'a, M, R> {
7 children: Vec<Element<'a, M, R>>,
8}
9
10impl<'a, M, R> Stack<'a, M, R>
11where
12 R: Renderer,
13{
14 pub fn with_children(children: Vec<Element<'a, M, R>>) -> Self { Self { children } }
15}
16
17impl<M, R> Widget<M, R> for Stack<'_, M, R>
18where
19 R: Renderer,
20{
21 fn width(&self) -> Length { Length::Fill }
22
23 fn height(&self) -> Length { Length::Fill }
24
25 fn layout(&self, renderer: &R, limits: &layout::Limits) -> layout::Node {
26 let limits = limits.width(Length::Fill).height(Length::Fill);
27
28 let loosed_limits = limits.loose();
29
30 let (max_size, nodes) = self.children.iter().fold(
31 (Size::ZERO, Vec::with_capacity(self.children.len())),
32 |(mut max_size, mut nodes), child| {
33 let node = child.layout(renderer, &loosed_limits);
34 let size = node.size();
35 nodes.push(node);
36 max_size.width = max_size.width.max(size.width);
37 max_size.height = max_size.height.max(size.height);
38 (max_size, nodes)
39 },
40 );
41
42 let size = limits.resolve(max_size);
43
44 layout::Node::with_children(size, nodes)
45 }
46
47 fn draw(
48 &self,
49 renderer: &mut R,
50 defaults: &R::Defaults,
51 layout: Layout<'_>,
52 cursor_position: Point,
53 viewport: &Rectangle,
54 ) -> R::Output {
55 renderer.draw(defaults, &self.children, layout, cursor_position, viewport)
56 }
57
58 fn hash_layout(&self, state: &mut Hasher) {
59 struct Marker;
60 std::any::TypeId::of::<Marker>().hash(state);
61
62 self.children
63 .iter()
64 .for_each(|child| child.hash_layout(state));
65 }
66
67 fn overlay(&mut self, layout: Layout<'_>) -> Option<iced::overlay::Element<'_, M, R>> {
68 self.children
69 .iter_mut()
70 .zip(layout.children())
71 .filter_map(|(child, layout)| child.overlay(layout))
72 .next()
73 }
74}
75
76pub trait Renderer: iced::Renderer {
77 fn draw<M>(
78 &mut self,
79 defaults: &Self::Defaults,
80 children: &[Element<'_, M, Self>],
81 layout: Layout<'_>,
82 cursor_position: Point,
83 viewport: &Rectangle,
84 ) -> Self::Output;
85}
86
87impl<'a, M, R> From<Stack<'a, M, R>> for Element<'a, M, R>
88where
89 R: 'a + Renderer,
90 M: 'a,
91{
92 fn from(stack: Stack<'a, M, R>) -> Element<'a, M, R> { Element::new(stack) }
93}