egui/egui_dynamic_grid/src/sizing.rs

91 lines
2.9 KiB
Rust
Raw Normal View History

2021-12-17 14:33:29 +00:00
#[derive(Clone, Debug)]
pub enum Size {
/// in points
Absolute(f32),
/// 0.0 to 1.0
Relative(f32),
RelativeMinimum {
/// 0.0 to 1.0
relative: f32,
/// in points
minimum: f32,
},
/// multiple remainders get each the same space
Remainder,
/// multiple remainders get each the same space, at least the minimum
RemainderMinimum(f32),
}
pub struct Sizing {
length: f32,
inner_padding: f32,
sizes: Vec<Size>,
}
impl Sizing {
pub fn new(length: f32, inner_padding: f32) -> Self {
Self {
length,
inner_padding,
sizes: vec![],
}
}
pub fn add_size(&mut self, size: Size) {
self.sizes.push(size);
}
pub fn into_lengths(self) -> Vec<f32> {
let mut remainders = 0;
let length = self.length;
let sum_non_remainder = self
.sizes
.iter()
.map(|size| match size {
Size::Absolute(absolute) => *absolute,
Size::Relative(relative) => {
assert!(*relative > 0.0, "Below 0.0 is not allowed.");
assert!(*relative <= 1.0, "Above 1.0 is not allowed.");
length * relative
}
Size::RelativeMinimum { relative, minimum } => {
assert!(*relative > 0.0, "Below 0.0 is not allowed.");
assert!(*relative <= 1.0, "Above 1.0 is not allowed.");
minimum.max(length * relative)
}
Size::Remainder | Size::RemainderMinimum(..) => {
remainders += 1;
0.0
}
})
.sum::<f32>()
+ self.inner_padding * (self.sizes.len() + 1) as f32;
let avg_remainder_length = if remainders == 0 {
0.0
} else {
let mut remainder_length = length - sum_non_remainder;
let avg_remainder_length = 0.0f32.max(remainder_length / remainders as f32);
self.sizes.iter().for_each(|size| {
if let Size::RemainderMinimum(minimum) = size {
if *minimum > avg_remainder_length {
remainder_length -= minimum - avg_remainder_length;
}
}
});
0.0f32.max(remainder_length / remainders as f32)
};
self.sizes
.into_iter()
.map(|size| match size {
Size::Absolute(absolute) => absolute,
Size::Relative(relative) => length * relative,
Size::RelativeMinimum { relative, minimum } => minimum.max(length * relative),
Size::Remainder => avg_remainder_length,
Size::RemainderMinimum(minimum) => minimum.max(avg_remainder_length),
})
.collect()
}
}