geng_ui/layout_widgets/
align.rs1use super::*;
2
3pub struct Align<T> {
4 align: vec2<f64>,
5 maintain_aspect: bool,
6 flex: vec2<Option<f64>>,
7 child: T,
8}
9
10impl<T, R: AsRef<T>> AsRef<T> for Align<R> {
11 fn as_ref(&self) -> &T {
12 self.child.as_ref()
13 }
14}
15
16impl<T, R: AsMut<T>> AsMut<T> for Align<R> {
17 fn as_mut(&mut self) -> &mut T {
18 self.child.as_mut()
19 }
20}
21
22mod ext {
23 use super::*;
24
25 pub trait WidgetExt: Widget + Sized {
26 fn align(self, align: vec2<f64>) -> Align<Self> {
27 Align {
28 align,
29 maintain_aspect: false,
30 flex: vec2(None, None),
31 child: self,
32 }
33 }
34 fn center(self) -> Align<Self> {
35 self.align(vec2(0.5, 0.5))
36 }
37 fn flex_align(self, flex: vec2<Option<f64>>, align: vec2<f64>) -> Align<Self> {
38 Align {
39 align,
40 maintain_aspect: false,
41 flex,
42 child: self,
43 }
44 }
45 fn maintain_aspect(self, align: vec2<f64>) -> Align<Self> {
46 Align {
47 align,
48 maintain_aspect: true,
49 flex: vec2(None, None),
50 child: self,
51 }
52 }
53 }
54
55 impl<T: Widget> WidgetExt for T {}
56}
57
58pub use ext::WidgetExt as _;
59
60impl<T: Widget> Widget for Align<T> {
61 fn calc_constraints(&mut self, children: &ConstraintsContext) -> Constraints {
62 let mut result = children.get_constraints(&self.child);
63 if let Some(flex) = self.flex.x {
64 result.flex.x = flex;
65 }
66 if let Some(flex) = self.flex.y {
67 result.flex.y = flex;
68 }
69 result
70 }
71 fn layout_children(&mut self, cx: &mut LayoutContext) {
72 let size = cx.position.size();
73 let child_constraints = cx.get_constraints(&self.child);
74 let mut child_size = vec2(
75 if child_constraints.flex.x == 0.0 {
76 partial_min(child_constraints.min_size.x, size.x)
77 } else {
78 size.x
79 },
80 if child_constraints.flex.y == 0.0 {
81 partial_min(child_constraints.min_size.y, size.y)
82 } else {
83 size.y
84 },
85 );
86 if self.maintain_aspect && child_constraints.min_size != vec2(0.0, 0.0) {
87 let aspect = child_constraints.min_size.x / child_constraints.min_size.y;
88 if child_size.y * aspect > child_size.x {
89 child_size.y = child_size.x / aspect;
90 }
91 if child_size.y < child_size.x / aspect {
92 child_size.x = child_size.y * aspect;
93 }
94 }
95 cx.set_position(
96 &self.child,
97 Aabb2::point(
98 cx.position.bottom_left()
99 + vec2(
100 (size.x - child_size.x) * self.align.x,
101 (size.y - child_size.y) * self.align.y,
102 ),
103 )
104 .extend_positive(child_size),
105 );
106 }
107 fn walk_children_mut<'a>(&mut self, f: &mut dyn FnMut(&mut dyn Widget)) {
108 f(&mut self.child);
109 }
110}