iced_core/
layout.rs
1mod limits;
3mod node;
4
5pub mod flex;
6
7pub use limits::Limits;
8pub use node::Node;
9
10use crate::{Length, Padding, Point, Rectangle, Size, Vector};
11
12#[derive(Debug, Clone, Copy)]
14pub struct Layout<'a> {
15 position: Point,
16 node: &'a Node,
17}
18
19impl<'a> Layout<'a> {
20 pub fn new(node: &'a Node) -> Self {
22 Self::with_offset(Vector::new(0.0, 0.0), node)
23 }
24
25 pub fn with_offset(offset: Vector, node: &'a Node) -> Self {
28 let bounds = node.bounds();
29
30 Self {
31 position: Point::new(bounds.x, bounds.y) + offset,
32 node,
33 }
34 }
35
36 pub fn position(&self) -> Point {
38 self.position
39 }
40
41 pub fn bounds(&self) -> Rectangle {
46 let bounds = self.node.bounds();
47
48 Rectangle {
49 x: self.position.x,
50 y: self.position.y,
51 width: bounds.width,
52 height: bounds.height,
53 }
54 }
55
56 pub fn children(self) -> impl DoubleEndedIterator<Item = Layout<'a>> {
58 self.node.children().iter().map(move |node| {
59 Layout::with_offset(
60 Vector::new(self.position.x, self.position.y),
61 node,
62 )
63 })
64 }
65}
66
67pub fn next_to_each_other(
69 limits: &Limits,
70 spacing: f32,
71 left: impl FnOnce(&Limits) -> Node,
72 right: impl FnOnce(&Limits) -> Node,
73) -> Node {
74 let left_node = left(limits);
75 let left_size = left_node.size();
76
77 let right_limits = limits.shrink(Size::new(left_size.width + spacing, 0.0));
78
79 let right_node = right(&right_limits);
80 let right_size = right_node.size();
81
82 let (left_y, right_y) = if left_size.height > right_size.height {
83 (0.0, (left_size.height - right_size.height) / 2.0)
84 } else {
85 ((right_size.height - left_size.height) / 2.0, 0.0)
86 };
87
88 Node::with_children(
89 Size::new(
90 left_size.width + spacing + right_size.width,
91 left_size.height.max(right_size.height),
92 ),
93 vec![
94 left_node.move_to(Point::new(0.0, left_y)),
95 right_node.move_to(Point::new(left_size.width + spacing, right_y)),
96 ],
97 )
98}
99
100pub fn atomic(
103 limits: &Limits,
104 width: impl Into<Length>,
105 height: impl Into<Length>,
106) -> Node {
107 let width = width.into();
108 let height = height.into();
109
110 Node::new(limits.resolve(width, height, Size::ZERO))
111}
112
113pub fn sized(
117 limits: &Limits,
118 width: impl Into<Length>,
119 height: impl Into<Length>,
120 f: impl FnOnce(&Limits) -> Size,
121) -> Node {
122 let width = width.into();
123 let height = height.into();
124
125 let limits = limits.width(width).height(height);
126 let intrinsic_size = f(&limits);
127
128 Node::new(limits.resolve(width, height, intrinsic_size))
129}
130
131pub fn contained(
135 limits: &Limits,
136 width: impl Into<Length>,
137 height: impl Into<Length>,
138 f: impl FnOnce(&Limits) -> Node,
139) -> Node {
140 let width = width.into();
141 let height = height.into();
142
143 let limits = limits.width(width).height(height);
144 let content = f(&limits);
145
146 Node::with_children(
147 limits.resolve(width, height, content.size()),
148 vec![content],
149 )
150}
151
152pub fn padded(
156 limits: &Limits,
157 width: impl Into<Length>,
158 height: impl Into<Length>,
159 padding: impl Into<Padding>,
160 layout: impl FnOnce(&Limits) -> Node,
161) -> Node {
162 positioned(limits, width, height, padding, layout, |content, _| content)
163}
164
165pub fn positioned(
167 limits: &Limits,
168 width: impl Into<Length>,
169 height: impl Into<Length>,
170 padding: impl Into<Padding>,
171 layout: impl FnOnce(&Limits) -> Node,
172 position: impl FnOnce(Node, Size) -> Node,
173) -> Node {
174 let width = width.into();
175 let height = height.into();
176 let padding = padding.into();
177
178 let limits = limits.width(width).height(height);
179 let content = layout(&limits.shrink(padding));
180 let padding = padding.fit(content.size(), limits.max());
181
182 let size = limits
183 .shrink(padding)
184 .resolve(width, height, content.size());
185
186 Node::with_children(
187 size.expand(padding),
188 vec![position(content.move_to((padding.left, padding.top)), size)],
189 )
190}