mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-10 07:04:17 +00:00
feat(layout): allow configuring layout fill (#633)
The layout split will generally fill the remaining area when `split()` is called. This change allows the caller to configure how any extra space is allocated to the `Rect`s. This is useful for cases where the caller wants to have a fixed size for one of the `Rect`s, and have the other `Rect`s fill the remaining space. For now, the method and enum are marked as unstable because the exact name is still being bikeshedded. To enable this functionality, add the `unstable-segment-size` feature flag in your `Cargo.toml`. To configure the layout to fill the remaining space evenly, use `Layout::segment_size(SegmentSize::EvenDistribution)`. The default behavior is `SegmentSize::LastTakesRemainder`, which gives the last segment the remaining space. `SegmentSize::None` will disable this behavior. See the docs for `Layout::segment_size()` and `layout::SegmentSize` for more information. Fixes https://github.com/ratatui-org/ratatui/issues/536
This commit is contained in:
parent
211160ca16
commit
753e246531
3 changed files with 54 additions and 5 deletions
10
Cargo.toml
10
Cargo.toml
|
@ -39,6 +39,7 @@ unicode-segmentation = "1.10"
|
|||
unicode-width = "0.1"
|
||||
document-features = { version = "0.2.7", optional = true }
|
||||
lru = "0.12.0"
|
||||
stability = "0.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0.71"
|
||||
|
@ -89,6 +90,15 @@ widget-calendar = ["dep:time"]
|
|||
## enables the backend code that sets the underline color.
|
||||
underline-color = ["dep:crossterm"]
|
||||
|
||||
#! The following features are unstable and may change in the future:
|
||||
|
||||
## Enable all unstable features.
|
||||
unstable = ["unstable-segment-size"]
|
||||
|
||||
## Enables the [`Layout::segment_size`](crate::layout::Layout::segment_size) method which is experimental and may change in the
|
||||
## future. See [Issue #536](https://github.com/ratatui-org/ratatui/issues/536) for more details.
|
||||
unstable-segment-size = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
# see https://doc.rust-lang.org/nightly/rustdoc/scraped-examples.html
|
||||
|
|
|
@ -11,7 +11,7 @@ ALL_FEATURES = "all-widgets,macros,serde"
|
|||
# sets of flags, one for Windows and one for other platforms.
|
||||
# Windows: --features=all-widgets,macros,serde,crossterm,termwiz,underline-color
|
||||
# Other: --features=all-widgets,macros,serde,crossterm,termion,termwiz,underline-color
|
||||
ALL_FEATURES_FLAG = { source = "${CARGO_MAKE_RUST_TARGET_OS}", default_value = "--features=all-widgets,macros,serde,crossterm,termion,termwiz", mapping = { "windows" = "--features=all-widgets,macros,serde,crossterm,termwiz" } }
|
||||
ALL_FEATURES_FLAG = { source = "${CARGO_MAKE_RUST_TARGET_OS}", default_value = "--features=all-widgets,macros,serde,crossterm,termion,termwiz,unstable", mapping = { "windows" = "--features=all-widgets,macros,serde,crossterm,termwiz,unstable" } }
|
||||
|
||||
[tasks.default]
|
||||
alias = "ci"
|
||||
|
|
|
@ -160,11 +160,32 @@ pub enum Alignment {
|
|||
Right,
|
||||
}
|
||||
|
||||
/// Option for segment size preferences
|
||||
///
|
||||
/// This controls how the space is distributed when the constraints are satisfied. By default, the
|
||||
/// last chunk is expanded to fill the remaining space, but this can be changed to prefer equal
|
||||
/// chunks or to not distribute extra space at all (which is the default used for laying out the
|
||||
/// columns for [`Table`] widgets).
|
||||
///
|
||||
/// Note: If you're using this feature please help us come up with a good name. See [Issue
|
||||
/// #536](https://github.com/ratatui-org/ratatui/issues/536) for more information.
|
||||
///
|
||||
/// [`Table`]: crate::widgets::Table
|
||||
#[stability::unstable(
|
||||
feature = "segment-size",
|
||||
reason = "The name for this feature is not final and may change in the future",
|
||||
issue = "https://github.com/ratatui-org/ratatui/issues/536"
|
||||
)]
|
||||
#[derive(Debug, Default, Display, EnumString, Clone, Eq, PartialEq, Hash)]
|
||||
pub(crate) enum SegmentSize {
|
||||
pub enum SegmentSize {
|
||||
/// prefer equal chunks if other constraints are all satisfied
|
||||
EvenDistribution,
|
||||
|
||||
/// the last chunk is expanded to fill the remaining space
|
||||
#[default]
|
||||
LastTakesRemainder,
|
||||
|
||||
/// extra space is not distributed
|
||||
None,
|
||||
}
|
||||
|
||||
|
@ -176,6 +197,7 @@ pub(crate) enum SegmentSize {
|
|||
/// - a set of constraints (length, ratio, percentage, min, max)
|
||||
/// - a margin (horizontal and vertical), the space between the edge of the main area and the split
|
||||
/// areas
|
||||
/// - extra options for segment size preferences
|
||||
///
|
||||
/// The algorithm used to compute the layout is based on the [`cassowary-rs`] solver. It is a simple
|
||||
/// linear solver that can be used to solve linear equations and inequalities. In our case, we
|
||||
|
@ -184,7 +206,9 @@ pub(crate) enum SegmentSize {
|
|||
/// many of the constraints as possible.
|
||||
///
|
||||
/// By default, the last chunk of the computed layout is expanded to fill the remaining space. To
|
||||
/// avoid this behavior, add an unused `Constraint::Min(0)` as the last constraint.
|
||||
/// avoid this behavior, add an unused `Constraint::Min(0)` as the last constraint. There is also
|
||||
/// an unstable API to prefer equal chunks if other constraints are all satisfied, see
|
||||
/// [`SegmentSize`] for more info.
|
||||
///
|
||||
/// When the layout is computed, the result is cached in a thread-local cache, so that subsequent
|
||||
/// calls with the same parameters are faster. The cache is a simple HashMap, and grows
|
||||
|
@ -371,7 +395,22 @@ impl Layout {
|
|||
}
|
||||
|
||||
/// Builder method to set whether chunks should be of equal size.
|
||||
pub(crate) const fn segment_size(mut self, segment_size: SegmentSize) -> Layout {
|
||||
///
|
||||
/// This determines how the space is distributed when the constraints are satisfied. By default,
|
||||
/// the last chunk is expanded to fill the remaining space, but this can be changed to prefer
|
||||
/// equal chunks or to not distribute extra space at all (which is the default used for laying
|
||||
/// out the columns for [`Table`] widgets).
|
||||
///
|
||||
/// Note: If you're using this feature please help us come up with a good name. See [Issue
|
||||
/// #536](https://github.com/ratatui-org/ratatui/issues/536) for more information.
|
||||
///
|
||||
/// [`Table`]: crate::widgets::Table
|
||||
#[stability::unstable(
|
||||
feature = "segment-size",
|
||||
reason = "The name for this feature is not final and may change in the future",
|
||||
issue = "https://github.com/ratatui-org/ratatui/issues/536"
|
||||
)]
|
||||
pub const fn segment_size(mut self, segment_size: SegmentSize) -> Layout {
|
||||
self.segment_size = segment_size;
|
||||
self
|
||||
}
|
||||
|
@ -477,8 +516,8 @@ fn try_split(area: Rect, layout: &Layout) -> Result<Rc<[Rect]>, AddConstraintErr
|
|||
if let Some(first) = elements.first() {
|
||||
solver.add_constraint(first.start | EQ(REQUIRED) | area_start)?;
|
||||
}
|
||||
// ensure the last element touches the right/bottom edge of the area
|
||||
if layout.segment_size != SegmentSize::None {
|
||||
// ensure the last element touches the right/bottom edge of the area
|
||||
if let Some(last) = elements.last() {
|
||||
solver.add_constraint(last.end | EQ(REQUIRED) | area_end)?;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue