From 98bcf1c0a57a340229684345497b2d378979de04 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Fri, 5 Jan 2024 03:13:57 -0800 Subject: [PATCH] feat(layout): add Rect::split method (#729) This method splits a Rect and returns a fixed-size array of the resulting Rects. This allows the caller to use array destructuring to get the individual Rects. ```rust use Constraint::*; let layout = &Layout::vertical([Length(1), Min(0)]); let [top, main] = area.split(&layout); ``` --- src/layout/rect.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/layout/rect.rs b/src/layout/rect.rs index 6a9fea30..ecce7a96 100644 --- a/src/layout/rect.rs +++ b/src/layout/rect.rs @@ -167,6 +167,32 @@ impl Rect { && self.y < other.bottom() && self.bottom() > other.y } + + /// Split the rect into a number of sub-rects according to the given [`Layout`]`. + /// + /// An ergonomic wrapper around [`Layout::split`] that returns an array of `Rect`s instead of + /// `Rc<[Rect]>`. + /// + /// # Panics + /// + /// Panics if the number of constraints is not equal to the length of the returned array. + /// + /// # Examples + /// + /// ```rust + /// # use ratatui::prelude::*; + /// # fn render(frame: &mut Frame) { + /// let area = frame.size(); + /// let layout = Layout::vertical([Constraint::Length(1), Constraint::Min(0)]); + /// let [top, main] = area.split(&layout); + /// # } + pub fn split(self, layout: &Layout) -> [Rect; N] { + layout + .split(self) + .to_vec() + .try_into() + .expect("invalid number of rects") + } } #[cfg(test)] @@ -353,4 +379,19 @@ mod tests { const _BOTTOM: u16 = RECT.bottom(); assert!(RECT.intersects(RECT)); } + + #[test] + fn split() { + let layout = Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]); + let [a, b] = Rect::new(0, 0, 2, 1).split(&layout); + assert_eq!(a, Rect::new(0, 0, 1, 1)); + assert_eq!(b, Rect::new(1, 0, 1, 1)); + } + + #[test] + #[should_panic(expected = "invalid number of rects")] + fn split_invalid_number_of_recs() { + let layout = Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]); + let [_a, _b, _c] = Rect::new(0, 0, 2, 1).split(&layout); + } }