From 783e57a9ab64b9c521d3b565f03c0050da6c575b Mon Sep 17 00:00:00 2001 From: Joscha Date: Sun, 19 Feb 2023 02:30:07 +0100 Subject: [PATCH] Allow join segments to be fixed I'm not sure if this is a good abstraction, or if I should instead re-think the algorithm. --- src/widgets/join.rs | 51 ++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/widgets/join.rs b/src/widgets/join.rs index 2a0a7b5..6e56d35 100644 --- a/src/widgets/join.rs +++ b/src/widgets/join.rs @@ -55,6 +55,7 @@ use super::{Either2, Either3, Either4, Either5, Either6, Either7}; struct Segment { size: u16, weight: f32, + fixed: bool, } impl Segment { @@ -62,6 +63,7 @@ impl Segment { Self { size: size.width, weight: segment.weight, + fixed: segment.fixed, } } @@ -69,11 +71,12 @@ impl Segment { Self { size: size.height, weight: segment.weight, + fixed: segment.fixed, } } } -fn total_size(segments: &[Segment]) -> u16 { +fn total_size(segments: &[&mut Segment]) -> u16 { let mut total = 0_u16; for segment in segments { total = total.saturating_add(segment.size); @@ -85,23 +88,31 @@ fn total_weight(segments: &[&mut Segment]) -> f32 { segments.iter().map(|s| s.weight).sum() } -fn balance(segments: &mut [Segment], available: u16) { - if segments.is_empty() { +fn balance(segments: &mut [Segment], mut available: u16) { + let mut borrowed_segments = segments.iter_mut().collect::>(); + + // Remove fixed segments + borrowed_segments.retain(|s| { + if !s.fixed { + return true; + } + available = available.saturating_sub(s.size); + false + }); + + if borrowed_segments.is_empty() || available == 0 { return; } - match total_size(segments).cmp(&available) { - Ordering::Less => grow(segments, available), - Ordering::Greater => shrink(segments, available), + match total_size(&borrowed_segments).cmp(&available) { + Ordering::Less => grow(borrowed_segments, available), + Ordering::Greater => shrink(borrowed_segments, available), Ordering::Equal => {} } - - assert!(available >= segments.iter().map(|s| s.size).sum::()); } -fn grow(segments: &mut [Segment], mut available: u16) { - assert!(available > total_size(segments)); - let mut segments = segments.iter_mut().collect::>(); +fn grow(mut segments: Vec<&mut Segment>, mut available: u16) { + assert!(available > total_size(&segments)); // Repeatedly remove all segments that do not need to grow, i. e. that are // at least as large as their allotment. @@ -158,9 +169,8 @@ fn grow(segments: &mut [Segment], mut available: u16) { } } -fn shrink(segments: &mut [Segment], mut available: u16) { - assert!(available < total_size(segments)); - let mut segments = segments.iter_mut().collect::>(); +fn shrink(mut segments: Vec<&mut Segment>, mut available: u16) { + assert!(available < total_size(&segments)); // Repeatedly remove all segments that do not need to shrink, i. e. that are // at least as small as their allotment. @@ -226,11 +236,16 @@ fn shrink(segments: &mut [Segment], mut available: u16) { pub struct JoinSegment { inner: I, weight: f32, + fixed: bool, } impl JoinSegment { pub fn new(inner: I) -> Self { - Self { inner, weight: 1.0 } + Self { + inner, + weight: 1.0, + fixed: false, + } } pub fn weight(mut self, weight: f32) -> Self { @@ -238,6 +253,11 @@ impl JoinSegment { self.weight = weight; self } + + pub fn fixed(mut self, fixed: bool) -> Self { + self.fixed = fixed; + self + } } pub struct JoinH { @@ -536,6 +556,7 @@ macro_rules! mk_join { JoinSegment { inner: $either::$constr($arg.inner), weight: $arg.weight, + fixed: $arg.fixed, }, )+ ])) }