Compare commits

...

3 Commits

Author SHA1 Message Date
Josh McKinney
84243c7ce8 feat: add layout helper methods 2024-01-03 20:30:30 -08:00
Josh McKinney
6a50f2085e feat: add layout helper methods 2024-01-03 20:27:36 -08:00
Josh McKinney
beaa2bf58d feat(layout): add split_array method
Layout::split_array() makes it easy to store areas in individual values.
E.g.:

```rust
let [top, main] =
    Layout::vertical([Constraint::Length(1), Constraint::Min(0)])
    .split_array(area);
```
2024-01-03 20:27:36 -08:00

View File

@@ -319,9 +319,9 @@ impl Layout {
pub fn vertical<I>(constraints: I) -> Layout
where
I: IntoIterator,
I::Item: AsRef<Constraint>,
I::Item: Into<Constraint>,
{
Layout::new(Direction::Vertical, constraints)
Layout::new(Direction::Vertical, constraints.into_iter().map(Into::into))
}
/// Creates a new horizontal layout with default values.
@@ -338,9 +338,12 @@ impl Layout {
pub fn horizontal<I>(constraints: I) -> Layout
where
I: IntoIterator,
I::Item: AsRef<Constraint>,
I::Item: Into<Constraint>,
{
Layout::new(Direction::Horizontal, constraints)
Layout::new(
Direction::Horizontal,
constraints.into_iter().map(Into::into),
)
}
/// Initialize an empty cache with a custom size. The cache is keyed on the layout and area, so
@@ -676,6 +679,29 @@ impl Layout {
.collect::<Rc<[Rect]>>();
Ok(results)
}
/// An ergonomic wrapper around [`Layout::split`] that returns an array 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 [top, main] =
/// Layout::new(Direction::Vertical,[Constraint::Length(1), Constraint::Min(0)])
/// .split_array(area);
/// # }
pub fn split_array<const N: usize>(self, area: Rect) -> [Rect; N] {
self.split(area)
.to_vec()
.try_into()
.expect("invalid number of rects")
}
}
impl Margin {
@@ -806,6 +832,67 @@ impl Constraint {
}
}
/// Helper function to create a Length constraint
///
/// Equivalent to `Constraint::Length(length)`
pub fn eq(length: u16) -> Constraint {
Constraint::Length(length)
}
/// Helper function to create a Min constraint
///
/// Equivalent to `Constraint::Min(length)`
pub fn ge(length: u16) -> Constraint {
Constraint::Min(length)
}
/// Helper function to create a Min constraint
///
/// Equivalent to `Constraint::Min(length)`
pub fn min(length: u16) -> Constraint {
Constraint::Min(length)
}
/// Helper function to create a Max constraint
///
/// Equivalent to `Constraint::Max(length)`
pub fn le(length: u16) -> Constraint {
Constraint::Max(length)
}
/// Helper function to create a Max constraint
///
/// Equivalent to `Constraint::Max(length)`
pub fn max(length: u16) -> Constraint {
Constraint::Max(length)
}
/// Helper function to create a Percentage constraint
///
/// Equivalent to `Constraint::Percentage(p)`
pub fn perc(p: u16) -> Constraint {
Constraint::Percentage(p)
}
/// Helper function to create a Ratio constraint
///
/// Equivalent to `Constraint::Ratio(numerator, denominator)`
pub fn ratio(numerator: u32, denominator: u32) -> Constraint {
Constraint::Ratio(numerator, denominator)
}
impl From<u16> for Constraint {
fn from(length: u16) -> Constraint {
Constraint::Length(length)
}
}
impl From<(u32, u32)> for Constraint {
fn from((n, d): (u32, u32)) -> Constraint {
Constraint::Ratio(n, d)
}
}
impl AsRef<Constraint> for Constraint {
fn as_ref(&self) -> &Constraint {
self
@@ -1798,5 +1885,50 @@ mod tests {
]
);
}
#[test]
fn split_array() {
let [a, b] = Layout::new(
Direction::Horizontal,
[Constraint::Percentage(50), Constraint::Percentage(50)],
)
.split_array(Rect::new(0, 0, 2, 1));
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_array_invalid_number_of_recs() {
let [_a, _b, _c] = Layout::new(
Direction::Horizontal,
[Constraint::Percentage(50), Constraint::Percentage(50)],
)
.split_array(Rect::new(0, 0, 2, 1));
}
}
/// A small test that just checks the ideas behind the layout shortcuts
#[test]
#[allow(unused_variables)]
fn constraint_helper_examples() {
let constraints = [
Constraint::Length(1),
Constraint::Min(1),
Constraint::Max(1),
Constraint::Percentage(1),
Constraint::Ratio(1, 1),
eq(1),
min(1),
ge(1),
max(1),
le(1),
perc(1),
ratio(1, 1),
];
let area = Rect::new(0, 0, 1, 1);
let [a, b, c, d] = Layout::horizontal([eq(5), ge(20), le(20), eq(5)]).split_array(area);
let [a, b, c, d] = Layout::vertical([1, 2, 3, 4]).split_array(area);
let [left, mid, right] = Layout::vertical([(1, 4), (1, 2), (1, 4)]).split_array(area);
}
}