aetna_core/tree/
layout_modifiers.rs1use crate::layout::{LayoutCtx, LayoutFn};
4use crate::metrics::{ComponentSize, MetricsRole};
5
6use super::geometry::{Rect, Sides};
7use super::layout_types::{Align, Axis, Justify, Size};
8use super::node::El;
9
10impl El {
11 pub fn width(mut self, w: Size) -> Self {
13 self.width = w;
14 self.explicit_width = true;
15 self
16 }
17
18 pub fn height(mut self, h: Size) -> Self {
19 self.height = h;
20 self.explicit_height = true;
21 self
22 }
23
24 pub fn hug(mut self) -> Self {
25 self.width = Size::Hug;
26 self.height = Size::Hug;
27 self.explicit_width = true;
28 self.explicit_height = true;
29 self
30 }
31
32 pub fn fill_size(mut self) -> Self {
33 self.width = Size::Fill(1.0);
34 self.height = Size::Fill(1.0);
35 self.explicit_width = true;
36 self.explicit_height = true;
37 self
38 }
39
40 pub fn size(mut self, size: ComponentSize) -> Self {
42 self.component_size = Some(size);
43 self
44 }
45
46 pub fn medium(self) -> Self {
47 self.size(ComponentSize::Md)
48 }
49
50 pub fn large(self) -> Self {
51 self.size(ComponentSize::Lg)
52 }
53
54 pub fn metrics_role(mut self, role: MetricsRole) -> Self {
56 self.metrics_role = Some(role);
57 self
58 }
59
60 pub fn padding(mut self, p: impl Into<Sides>) -> Self {
62 self.padding = p.into();
63 self.explicit_padding = true;
64 self
65 }
66
67 pub fn pt(mut self, v: f32) -> Self {
73 self.padding.top = v;
74 self.explicit_padding = true;
75 self
76 }
77
78 pub fn pb(mut self, v: f32) -> Self {
81 self.padding.bottom = v;
82 self.explicit_padding = true;
83 self
84 }
85
86 pub fn pl(mut self, v: f32) -> Self {
89 self.padding.left = v;
90 self.explicit_padding = true;
91 self
92 }
93
94 pub fn pr(mut self, v: f32) -> Self {
97 self.padding.right = v;
98 self.explicit_padding = true;
99 self
100 }
101
102 pub fn px(mut self, v: f32) -> Self {
106 self.padding.left = v;
107 self.padding.right = v;
108 self.explicit_padding = true;
109 self
110 }
111
112 pub fn py(mut self, v: f32) -> Self {
116 self.padding.top = v;
117 self.padding.bottom = v;
118 self.explicit_padding = true;
119 self
120 }
121
122 pub fn gap(mut self, g: f32) -> Self {
123 self.gap = g;
124 self.explicit_gap = true;
125 self
126 }
127
128 pub fn align(mut self, a: Align) -> Self {
129 self.align = a;
130 self
131 }
132
133 pub fn justify(mut self, j: Justify) -> Self {
134 self.justify = j;
135 self
136 }
137
138 pub fn clip(mut self) -> Self {
139 self.clip = true;
140 self
141 }
142
143 pub fn scrollable(mut self) -> Self {
144 self.scrollable = true;
145 self
146 }
147
148 pub fn scrollbar(mut self) -> Self {
151 self.scrollbar = true;
152 self
153 }
154
155 pub fn no_scrollbar(mut self) -> Self {
157 self.scrollbar = false;
158 self
159 }
160
161 pub fn pin_end(mut self) -> Self {
174 self.pin_end = true;
175 self
176 }
177
178 pub fn arrow_nav_siblings(mut self) -> Self {
181 self.arrow_nav_siblings = true;
182 self
183 }
184
185 pub fn layout<F>(mut self, f: F) -> Self
188 where
189 F: Fn(LayoutCtx) -> Vec<Rect> + Send + Sync + 'static,
190 {
191 self.layout_override = Some(LayoutFn::new(f));
192 self
193 }
194
195 pub fn child(mut self, c: impl Into<El>) -> Self {
197 self.children.push(c.into());
198 self
199 }
200
201 pub fn children<I, E>(mut self, cs: I) -> Self
202 where
203 I: IntoIterator<Item = E>,
204 E: Into<El>,
205 {
206 self.children.extend(cs.into_iter().map(Into::into));
207 self
208 }
209
210 pub fn axis(mut self, a: Axis) -> Self {
212 self.axis = a;
213 self
214 }
215
216 pub(crate) fn default_width(mut self, w: Size) -> Self {
218 self.width = w;
219 self.explicit_width = false;
220 self
221 }
222
223 pub(crate) fn default_height(mut self, h: Size) -> Self {
224 self.height = h;
225 self.explicit_height = false;
226 self
227 }
228
229 pub(crate) fn default_padding(mut self, p: impl Into<Sides>) -> Self {
230 self.padding = p.into();
231 self.explicit_padding = false;
232 self
233 }
234
235 pub(crate) fn default_gap(mut self, g: f32) -> Self {
236 self.gap = g;
237 self.explicit_gap = false;
238 self
239 }
240}
241
242#[cfg(test)]
243mod tests {
244 use super::*;
245 use crate::tree::Kind;
246
247 fn fresh() -> El {
248 El::new(Kind::Group)
249 }
250
251 #[test]
252 fn pt_sets_only_top_and_marks_explicit() {
253 let el = fresh().pt(7.0);
254 assert_eq!(
255 el.padding,
256 Sides {
257 left: 0.0,
258 right: 0.0,
259 top: 7.0,
260 bottom: 0.0
261 }
262 );
263 assert!(el.explicit_padding);
264 }
265
266 #[test]
267 fn px_py_set_only_their_axis() {
268 let el = fresh().px(4.0).py(2.0);
269 assert_eq!(
270 el.padding,
271 Sides {
272 left: 4.0,
273 right: 4.0,
274 top: 2.0,
275 bottom: 2.0
276 }
277 );
278 assert!(el.explicit_padding);
279 }
280
281 #[test]
282 fn pt_overrides_only_top_when_following_padding() {
283 let el = fresh().padding(4.0).pt(0.0);
285 assert_eq!(
286 el.padding,
287 Sides {
288 left: 4.0,
289 right: 4.0,
290 top: 0.0,
291 bottom: 4.0
292 }
293 );
294 assert!(el.explicit_padding);
295 }
296
297 #[test]
298 fn pt_after_default_padding_preserves_other_sides_and_marks_explicit() {
299 let el = fresh().default_padding(4.0).pt(0.0);
303 assert_eq!(
304 el.padding,
305 Sides {
306 left: 4.0,
307 right: 4.0,
308 top: 0.0,
309 bottom: 4.0
310 }
311 );
312 assert!(el.explicit_padding);
313 }
314
315 #[test]
316 fn per_side_chainables_compose() {
317 let el = fresh().pl(1.0).pr(2.0).pt(3.0).pb(4.0);
318 assert_eq!(
319 el.padding,
320 Sides {
321 left: 1.0,
322 right: 2.0,
323 top: 3.0,
324 bottom: 4.0
325 }
326 );
327 assert!(el.explicit_padding);
328 }
329
330 #[test]
331 fn sides_x_and_y_constructors_only_populate_one_axis() {
332 assert_eq!(
333 Sides::x(5.0),
334 Sides {
335 left: 5.0,
336 right: 5.0,
337 top: 0.0,
338 bottom: 0.0
339 }
340 );
341 assert_eq!(
342 Sides::y(5.0),
343 Sides {
344 left: 0.0,
345 right: 0.0,
346 top: 5.0,
347 bottom: 5.0
348 }
349 );
350 }
351}