pub struct MeasureLayout {
width: f32,
gap: f32,
total_flex: u8,
no_expand_count: u8,
no_expand_width: f32,
}
impl MeasureLayout {
pub fn new(width: f32, gap: f32) -> Self {
MeasureLayout {
width,
gap,
total_flex: 0,
no_expand_count: 0,
no_expand_width: 0.,
}
}
pub fn add_fixed(&mut self, width: f32) {
self.no_expand_count += 1;
self.no_expand_width += width;
}
pub fn add_expand(&mut self, fraction: u8) {
self.total_flex += fraction;
}
pub fn no_expand_width(&self) -> Option<f32> {
if self.no_expand_count == 0 {
None
} else {
Some(self.no_expand_width + self.gap * (self.no_expand_count - 1) as f32)
}
}
pub fn build(self) -> DrawLayout {
let remaining_width =
(self.width + self.gap - self.no_expand_width - self.gap * self.no_expand_count as f32)
.max(0.);
DrawLayout {
total_flex: self.total_flex,
gap: self.gap,
remaining_width,
}
}
}
#[derive(Copy, Clone)]
pub struct DrawLayout {
total_flex: u8,
gap: f32,
remaining_width: f32,
}
impl DrawLayout {
pub fn expand_width(&self, fraction: u8) -> f32 {
(self.remaining_width * fraction as f32 / self.total_flex as f32 - self.gap).max(0.)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_alignment() {
let mut layout = MeasureLayout::new(15., 2.);
layout.add_expand(1);
layout.add_fixed(3.);
layout.add_expand(1);
let a = layout.build();
let mut layout = MeasureLayout::new(15., 2.);
layout.add_expand(1);
layout.add_expand(1);
layout.add_fixed(3.);
layout.add_expand(2);
let b = layout.build();
assert_eq!(
a.expand_width(1),
b.expand_width(1) + 2. + b.expand_width(1),
);
assert_eq!(a.expand_width(1), 4.,);
assert_eq!(a.expand_width(1) + 2. + 3. + 2. + a.expand_width(1), 15.);
assert_eq!(
b.expand_width(1) + 2. + b.expand_width(1) + 2. + 3. + 2. + b.expand_width(2),
15.
);
}
#[test]
fn test_total_width() {
{
let mut layout = MeasureLayout::new(100., 4.);
layout.add_expand(1);
layout.add_expand(1);
layout.add_expand(1);
let draw_layout = layout.build();
assert_eq!(
draw_layout.expand_width(1)
+ draw_layout.expand_width(1)
+ draw_layout.expand_width(1)
+ 2. * 4.,
100.,
);
}
{
let mut layout = MeasureLayout::new(100., 4.);
layout.add_expand(1);
layout.add_fixed(50.);
layout.add_expand(1);
let draw_layout = layout.build();
assert_eq!(
draw_layout.expand_width(1) + 50. + draw_layout.expand_width(1) + 2. * 4.,
100.,
);
assert_eq!(draw_layout.expand_width(1), 21.);
}
{
let mut layout = MeasureLayout::new(100., 4.);
layout.add_expand(1);
layout.add_fixed(25.);
layout.add_expand(1);
layout.add_fixed(25.);
let draw_layout = layout.build();
assert_eq!(
draw_layout.expand_width(1) + 25. + draw_layout.expand_width(1) + 25. + 3. * 4.,
100.,
);
assert_eq!(draw_layout.expand_width(1), 19.);
}
{
let mut layout = MeasureLayout::new(100., 4.);
layout.add_fixed(25.);
layout.add_expand(1);
layout.add_fixed(25.);
layout.add_expand(1);
layout.add_fixed(25.);
let draw_layout = layout.build();
assert_eq!(
25. + draw_layout.expand_width(1)
+ 25.
+ draw_layout.expand_width(1)
+ 25.
+ 4. * 4.,
100.,
);
}
{
let mut layout = MeasureLayout::new(100., 3.);
layout.add_fixed(25.);
layout.add_expand(2);
layout.add_fixed(25.);
layout.add_expand(1);
layout.add_fixed(25.);
let draw_layout = layout.build();
assert_eq!(
25. + draw_layout.expand_width(2)
+ 25.
+ draw_layout.expand_width(1)
+ 25.
+ 3. * 4.,
100.,
);
}
{
let mut layout = MeasureLayout::new(100., 4.);
layout.add_fixed(25.);
layout.add_expand(2);
layout.add_fixed(25.);
layout.add_expand(1);
layout.add_fixed(25.);
let draw_layout = layout.build();
assert_eq!(
(25. + draw_layout.expand_width(2)
+ 25.
+ draw_layout.expand_width(1)
+ 25.
+ 4. * 4.),
100.,
);
}
{
let mut layout = MeasureLayout::new(22., 2.);
layout.add_expand(2);
layout.add_fixed(14.);
layout.add_expand(1);
let draw_layout = layout.build();
assert_eq!(
draw_layout.expand_width(2) + 14. + draw_layout.expand_width(1) + 2. * 2.,
22.,
);
}
}
}