ratatui/src/layout/flex.rs
Dheepak Krishnamurthy de97a1f1da
feat: Add flex to layout
This PR adds a new way to space elements in a `Layout`.

Loosely based on
[flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/), this
PR adds a `Flex` enum with the following variants:

- Start
- Center
- End
- SpaceAround
- SpaceBetween

<img width="380" alt="image" src="https://github.com/ratatui-org/ratatui/assets/1813121/b744518c-eae7-4e35-bbc4-fe3c95193cde">

It also adds two more variants, to make this backward compatible and to
make it replace `SegmentSize`:

- StretchLast (default in the `Flex` enum, also behavior matches old
  default `SegmentSize::LastTakesRemainder`)
- Stretch (behavior matches `SegmentSize::EvenDistribution`)

The `Start` variant from above matches `SegmentSize::None`.

This allows `Flex` to be a complete replacement for `SegmentSize`, hence
this PR also deprecates the `segment_size` constructor on `Layout`.
`SegmentSize` is still used in `Table` but under the hood `segment_size`
maps to `Flex` with all tests passing unchanged.

I also put together a simple example for `Flex` layouts so that I could
test it visually, shared below:

https://github.com/ratatui-org/ratatui/assets/1813121/c8716c59-493f-4631-add5-feecf4bd4e06
2024-01-13 01:56:27 -08:00

191 lines
9.5 KiB
Rust

use strum::{Display, EnumString};
/// Defines the options for layout flex justify content in a container.
///
/// This enumeration controls the distribution of space when layout constraints are met.
///
/// - `StretchLast`: Fills the available space within the container, putting excess space into the
/// last element.
/// - `Stretch`: Always fills the available space within the container.
/// - `Start`: Aligns items to the start of the container.
/// - `End`: Aligns items to the end of the container.
/// - `Center`: Centers items within the container.
/// - `SpaceBetween`: Adds excess space between each element.
/// - `SpaceAround`: Adds excess space around each element.
#[derive(Copy, Debug, Default, Display, EnumString, Clone, Eq, PartialEq, Hash)]
pub enum Flex {
/// Fills the available space within the container, putting excess space into the last element.
/// This matches the default behavior of ratatui and tui applications without [`Flex`]
///
/// # Examples
///
/// ```plain
///
/// Length(20), Length(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐┌──────────────────────────────────────────────────────────┐
/// │ 20 px ││ 60 px │
/// └──────────────────┘└──────────────────────────────────────────────────────────┘
///
/// Length(20), Fixed(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌────────────────────────────────────────────────────────────────────┐┌────────┐
/// │ 70 px ││ 10 px │
/// └────────────────────────────────────────────────────────────────────┘└────────┘
/// ```
#[default]
StretchLast,
/// Always fills the available space within the container.
///
/// # Examples
///
/// Length(40), Length(20)
///
/// ```plain
///
/// Length(20), Length(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────────────────────────┐┌──────────────────────────────────────┐
/// │ 40 px ││ 40 px │
/// └──────────────────────────────────────┘└──────────────────────────────────────┘
///
/// Length(20), Fixed(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌────────────────────────────────────────────────────────────────────┐┌────────┐
/// │ 70 px ││ 10 px │
/// └────────────────────────────────────────────────────────────────────┘└────────┘
/// ```
Stretch,
/// Aligns items to the start of the container.
///
/// # Examples
///
/// ```plain
///
/// Length(20), Length(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐┌────────┐
/// │ 20 px ││ 10 px │
/// └──────────────────┘└────────┘
///
/// Length(20), Fixed(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐┌────────┐
/// │ 20 px ││ 10 px │
/// └──────────────────┘└────────┘
/// ```
Start,
/// Aligns items to the end of the container.
///
/// # Examples
///
/// ```plain
///
/// Length(20), Length(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐┌────────┐
/// │ 20 px ││ 10 px │
/// └──────────────────┘└────────┘
///
/// Length(20), Fixed(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐┌────────┐
/// │ 20 px ││ 10 px │
/// └──────────────────┘└────────┘
/// ```
End,
/// Centers items within the container.
///
/// # Examples
///
/// ```plain
///
/// Length(20), Length(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐┌────────┐
/// │ 20 px ││ 10 px │
/// └──────────────────┘└────────┘
///
/// Length(20), Fixed(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐┌────────┐
/// │ 20 px ││ 10 px │
/// └──────────────────┘└────────┘
/// ```
Center,
/// Adds excess space between each element.
///
/// # Examples
///
/// ```plain
///
/// Length(20), Length(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐ ┌────────┐
/// │ 20 px │ │ 10 px │
/// └──────────────────┘ └────────┘
///
/// Length(20), Fixed(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐ ┌────────┐
/// │ 20 px │ │ 10 px │
/// └──────────────────┘ └────────┘
/// ```
SpaceBetween,
/// Adds excess space around each element.
///
/// # Examples
///
/// ```plain
///
/// Length(20), Length(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐ ┌────────┐
/// │ 20 px │ │ 10 px │
/// └──────────────────┘ └────────┘
///
/// Length(20), Fixed(10)
///
/// <------------------------------------80 px------------------------------------->
///
/// ┌──────────────────┐ ┌────────┐
/// │ 20 px │ │ 10 px │
/// └──────────────────┘ └────────┘
/// ```
SpaceAround,
}
#[cfg(test)]
mod tests {}