diff options
author | Clement Tsang <34804052+ClementTsang@users.noreply.github.com> | 2024-01-02 01:13:02 -0500 |
---|---|---|
committer | Clement Tsang <34804052+ClementTsang@users.noreply.github.com> | 2024-01-02 01:13:02 -0500 |
commit | c730048c7a0a5ab2eb657fee2649d7b22e73652d (patch) | |
tree | e75b7e0e03f64e797bcc5a85195a2ffe8728cdb7 /src/tuine/constraints.rs | |
parent | dbadbb996cb8d55d842b9632126c031f39596453 (diff) |
temp worktuine_yet_again
Diffstat (limited to 'src/tuine/constraints.rs')
-rw-r--r-- | src/tuine/constraints.rs | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/tuine/constraints.rs b/src/tuine/constraints.rs new file mode 100644 index 00000000..a05462be --- /dev/null +++ b/src/tuine/constraints.rs @@ -0,0 +1,154 @@ +use tui::layout::{Direction, Rect}; + +use crate::canvas::LayoutConstraint; + +pub(super) fn get_constraints( + direction: Direction, constraints: &[LayoutConstraint], area: Rect, +) -> Vec<Rect> { + // Order of operations: + // - Ratios first + canvas-handled (which is just zero) + // - Then any flex-grows to take up remaining space; divide amongst remaining + // hand out any remaining space + + #[derive(Debug, Default, Clone, Copy)] + struct Size { + width: u16, + height: u16, + } + + impl Size { + fn shrink_width(&mut self, amount: u16) { + self.width -= amount; + } + + fn shrink_height(&mut self, amount: u16) { + self.height -= amount; + } + } + + let mut bounds = Size { + width: area.width, + height: area.height, + }; + let mut sizes = vec![Size::default(); constraints.len()]; + let mut grow = vec![]; + let mut num_non_ch = 0; + + for (itx, (constraint, size)) in constraints.iter().zip(sizes.iter_mut()).enumerate() { + match constraint { + LayoutConstraint::Ratio(a, b) => { + match direction { + Direction::Horizontal => { + let amount = (((area.width as u32) * (*a)) / (*b)) as u16; + bounds.shrink_width(amount); + size.width = amount; + size.height = area.height; + } + Direction::Vertical => { + let amount = (((area.height as u32) * (*a)) / (*b)) as u16; + bounds.shrink_height(amount); + size.width = area.width; + size.height = amount; + } + } + num_non_ch += 1; + } + LayoutConstraint::Grow => { + // Mark it as grow in the vector and handle in second pass. + grow.push(itx); + num_non_ch += 1; + } + LayoutConstraint::CanvasHandled => { + // Do nothing in this case. It's already 0. + } + } + } + + if !grow.is_empty() { + match direction { + Direction::Horizontal => { + let width = bounds.width / grow.len() as u16; + bounds.shrink_width(width * grow.len() as u16); + for g in grow { + sizes[g] = Size { + width, + height: area.height, + }; + } + } + Direction::Vertical => { + let height = bounds.height / grow.len() as u16; + bounds.shrink_height(height * grow.len() as u16); + for g in grow { + sizes[g] = Size { + width: area.width, + height, + }; + } + } + } + } + + if num_non_ch > 0 { + match direction { + Direction::Horizontal => { + let per_item = bounds.width / num_non_ch; + let mut remaining_width = bounds.width % num_non_ch; + for (size, constraint) in sizes.iter_mut().zip(constraints) { + match constraint { + LayoutConstraint::CanvasHandled => {} + LayoutConstraint::Grow | LayoutConstraint::Ratio(_, _) => { + if remaining_width > 0 { + size.width += per_item + 1; + remaining_width -= 1; + } else { + size.width += per_item; + } + } + } + } + } + Direction::Vertical => { + let per_item = bounds.height / num_non_ch; + let mut remaining_height = bounds.height % num_non_ch; + for (size, constraint) in sizes.iter_mut().zip(constraints) { + match constraint { + LayoutConstraint::CanvasHandled => {} + LayoutConstraint::Grow | LayoutConstraint::Ratio(_, _) => { + if remaining_height > 0 { + size.height += per_item + 1; + remaining_height -= 1; + } else { + size.height += per_item; + } + } + } + } + } + } + } + + let mut curr_x = area.x; + let mut curr_y = area.y; + sizes + .into_iter() + .map(|size| { + let rect = Rect::new(curr_x, curr_y, size.width, size.height); + match direction { + Direction::Horizontal => { + curr_x += size.width; + } + Direction::Vertical => { + curr_y += size.height; + } + } + + rect + }) + .collect() +} + +#[cfg(test)] +mod test { + // TODO: Add some tests. +} |