cranpose_ui_layout/
arrangement.rs1pub trait Arrangement {
5 fn arrange(&self, total_size: f32, sizes: &[f32], out_positions: &mut [f32]);
7}
8
9#[derive(Clone, Copy, Debug, PartialEq)]
11pub enum LinearArrangement {
12 Start,
14 End,
16 Center,
18 SpaceBetween,
20 SpaceAround,
22 SpaceEvenly,
24 SpacedBy(f32),
26}
27
28impl LinearArrangement {
29 pub fn spaced_by(spacing: f32) -> Self {
31 Self::SpacedBy(spacing)
32 }
33
34 fn total_children_size(sizes: &[f32]) -> f32 {
35 sizes.iter().copied().sum()
36 }
37
38 fn fill_positions(start: f32, gap: f32, sizes: &[f32], out_positions: &mut [f32]) {
39 debug_assert_eq!(sizes.len(), out_positions.len());
40 let mut cursor = start;
41 for (index, (size, position)) in sizes.iter().zip(out_positions.iter_mut()).enumerate() {
42 *position = cursor;
43 cursor += size;
44 if index + 1 < sizes.len() {
45 cursor += gap;
46 }
47 }
48 }
49}
50
51impl Arrangement for LinearArrangement {
52 fn arrange(&self, total_size: f32, sizes: &[f32], out_positions: &mut [f32]) {
53 debug_assert_eq!(sizes.len(), out_positions.len());
54 if sizes.is_empty() {
55 return;
56 }
57
58 let children_total = Self::total_children_size(sizes);
59 let remaining = total_size - children_total;
60
61 match *self {
62 LinearArrangement::Start => Self::fill_positions(0.0, 0.0, sizes, out_positions),
63 LinearArrangement::End => {
64 let start = remaining;
65 Self::fill_positions(start, 0.0, sizes, out_positions);
66 }
67 LinearArrangement::Center => {
68 let start = remaining / 2.0;
69 Self::fill_positions(start, 0.0, sizes, out_positions);
70 }
71 LinearArrangement::SpaceBetween => {
72 let gap = if sizes.len() <= 1 {
73 0.0
74 } else {
75 remaining / (sizes.len() as f32 - 1.0)
76 };
77 Self::fill_positions(0.0, gap, sizes, out_positions);
78 }
79 LinearArrangement::SpaceAround => {
80 let gap = remaining / sizes.len() as f32;
81 let start = gap / 2.0;
82 Self::fill_positions(start, gap, sizes, out_positions);
83 }
84 LinearArrangement::SpaceEvenly => {
85 let gap = remaining / (sizes.len() as f32 + 1.0);
86 let start = gap;
87 Self::fill_positions(start, gap, sizes, out_positions);
88 }
89 LinearArrangement::SpacedBy(spacing) => {
90 Self::fill_positions(0.0, spacing, sizes, out_positions);
91 }
92 }
93 }
94}
95
96#[cfg(test)]
97#[path = "tests/arrangement_tests.rs"]
98mod tests;