pub trait Arrangement {
fn arrange(&self, total_size: f32, sizes: &[f32], out_positions: &mut [f32]);
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LinearArrangement {
Start,
End,
Center,
SpaceBetween,
SpaceAround,
SpaceEvenly,
SpacedBy(f32),
}
impl LinearArrangement {
pub fn spaced_by(spacing: f32) -> Self {
Self::SpacedBy(spacing)
}
fn total_children_size(sizes: &[f32]) -> f32 {
sizes.iter().copied().sum()
}
fn fill_positions(start: f32, gap: f32, sizes: &[f32], out_positions: &mut [f32]) {
debug_assert_eq!(sizes.len(), out_positions.len());
let mut cursor = start;
for (index, (size, position)) in sizes.iter().zip(out_positions.iter_mut()).enumerate() {
*position = cursor;
cursor += size;
if index + 1 < sizes.len() {
cursor += gap;
}
}
}
}
impl Arrangement for LinearArrangement {
fn arrange(&self, total_size: f32, sizes: &[f32], out_positions: &mut [f32]) {
debug_assert_eq!(sizes.len(), out_positions.len());
if sizes.is_empty() {
return;
}
let children_total = Self::total_children_size(sizes);
let remaining = total_size - children_total;
match *self {
LinearArrangement::Start => Self::fill_positions(0.0, 0.0, sizes, out_positions),
LinearArrangement::End => {
let start = remaining;
Self::fill_positions(start, 0.0, sizes, out_positions);
}
LinearArrangement::Center => {
let start = remaining / 2.0;
Self::fill_positions(start, 0.0, sizes, out_positions);
}
LinearArrangement::SpaceBetween => {
let gap = if sizes.len() <= 1 {
0.0
} else {
remaining / (sizes.len() as f32 - 1.0)
};
Self::fill_positions(0.0, gap, sizes, out_positions);
}
LinearArrangement::SpaceAround => {
let gap = remaining / sizes.len() as f32;
let start = gap / 2.0;
Self::fill_positions(start, gap, sizes, out_positions);
}
LinearArrangement::SpaceEvenly => {
let gap = remaining / (sizes.len() as f32 + 1.0);
let start = gap;
Self::fill_positions(start, gap, sizes, out_positions);
}
LinearArrangement::SpacedBy(spacing) => {
Self::fill_positions(0.0, spacing, sizes, out_positions);
}
}
}
}
#[cfg(test)]
#[path = "tests/arrangement_tests.rs"]
mod tests;