feat(misc): make builder fn const (#275) (#275)

This allows the following types to be used in a constant context:
- `Layout`
- `Rect`
- `Style`
- `BorderType`
- `Padding`
- `Block`

Also adds several missing `new()` functions to the above types.

Blocks can now be used in the following way:
```
const DEFAULT_BLOCK: Block = Block::new()
    .title_style(Style::new())
    .title_alignment(Alignment::Left)
    .title_position(Position::Top)
    .borders(Borders::ALL)
    .border_style(Style::new())
    .style(Style::reset())
    .padding(Padding::uniform(1));

```

Layouts can now be used in the following way:
``
const DEFAULT_LAYOUT: Layout = Layout::new()
    .direction(Direction::Horizontal)
    .margin(1)
    .expand_to_fill(false);
```

Rects can now be used in the following way:
```
const RECT: Rect = Rect {
    x: 0,
    y: 0,
    width: 10,
    height: 10,
};
```
This commit is contained in:
a-kenji 2023-06-26 02:09:51 +02:00 committed by GitHub
parent bfcc5504bb
commit 7a6c3d9db1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 107 additions and 38 deletions

View file

@ -86,6 +86,12 @@ thread_local! {
impl Default for Layout {
fn default() -> Layout {
Layout::new()
}
}
impl Layout {
pub const fn new() -> Layout {
Layout {
direction: Direction::Vertical,
margin: Margin {
@ -96,9 +102,7 @@ impl Default for Layout {
expand_to_fill: true,
}
}
}
impl Layout {
pub fn constraints<C>(mut self, constraints: C) -> Layout
where
C: Into<Vec<Constraint>>,
@ -107,7 +111,7 @@ impl Layout {
self
}
pub fn margin(mut self, margin: u16) -> Layout {
pub const fn margin(mut self, margin: u16) -> Layout {
self.margin = Margin {
horizontal: margin,
vertical: margin,
@ -115,22 +119,22 @@ impl Layout {
self
}
pub fn horizontal_margin(mut self, horizontal: u16) -> Layout {
pub const fn horizontal_margin(mut self, horizontal: u16) -> Layout {
self.margin.horizontal = horizontal;
self
}
pub fn vertical_margin(mut self, vertical: u16) -> Layout {
pub const fn vertical_margin(mut self, vertical: u16) -> Layout {
self.margin.vertical = vertical;
self
}
pub fn direction(mut self, direction: Direction) -> Layout {
pub const fn direction(mut self, direction: Direction) -> Layout {
self.direction = direction;
self
}
pub(crate) fn expand_to_fill(mut self, expand_to_fill: bool) -> Layout {
pub(crate) const fn expand_to_fill(mut self, expand_to_fill: bool) -> Layout {
self.expand_to_fill = expand_to_fill;
self
}
@ -422,23 +426,23 @@ impl Rect {
}
}
pub fn area(self) -> u16 {
pub const fn area(self) -> u16 {
self.width * self.height
}
pub fn left(self) -> u16 {
pub const fn left(self) -> u16 {
self.x
}
pub fn right(self) -> u16 {
pub const fn right(self) -> u16 {
self.x.saturating_add(self.width)
}
pub fn top(self) -> u16 {
pub const fn top(self) -> u16 {
self.y
}
pub fn bottom(self) -> u16 {
pub const fn bottom(self) -> u16 {
self.y.saturating_add(self.height)
}
@ -481,7 +485,7 @@ impl Rect {
}
}
pub fn intersects(self, other: Rect) -> bool {
pub const fn intersects(self, other: Rect) -> bool {
self.x < other.x + other.width
&& self.x + self.width > other.x
&& self.y < other.y + other.height
@ -598,4 +602,31 @@ mod tests {
assert_eq!(Constraint::Min(200).apply(100), 200);
assert_eq!(Constraint::Min(u16::MAX).apply(100), u16::MAX);
}
#[test]
fn rect_can_be_const() {
const RECT: Rect = Rect {
x: 0,
y: 0,
width: 10,
height: 10,
};
const _AREA: u16 = RECT.area();
const _LEFT: u16 = RECT.left();
const _RIGHT: u16 = RECT.right();
const _TOP: u16 = RECT.top();
const _BOTTOM: u16 = RECT.bottom();
assert!(RECT.intersects(RECT));
}
#[test]
fn layout_can_be_const() {
const _LAYOUT: Layout = Layout::new();
const _DEFAULT_LAYOUT: Layout = Layout::new()
.direction(Direction::Horizontal)
.margin(1)
.expand_to_fill(false);
const _HORIZONTAL_LAYOUT: Layout = Layout::new().horizontal_margin(1);
const _VERTICAL_LAYOUT: Layout = Layout::new().vertical_margin(1);
}
}

View file

@ -469,4 +469,9 @@ mod tests {
);
}
}
#[test]
fn style_can_be_const() {
const _DEFAULT_STYLE: Style = Style::new().fg(Color::Red).bg(Color::Black);
const _RESET: Style = Style::reset();
}
}

View file

@ -19,7 +19,7 @@ pub enum BorderType {
}
impl BorderType {
pub fn line_symbols(border_type: BorderType) -> line::Set {
pub const fn line_symbols(border_type: BorderType) -> line::Set {
match border_type {
BorderType::Plain => line::NORMAL,
BorderType::Rounded => line::ROUNDED,
@ -38,7 +38,7 @@ pub struct Padding {
}
impl Padding {
pub fn new(left: u16, right: u16, top: u16, bottom: u16) -> Self {
pub const fn new(left: u16, right: u16, top: u16, bottom: u16) -> Self {
Padding {
left,
right,
@ -47,7 +47,7 @@ impl Padding {
}
}
pub fn zero() -> Self {
pub const fn zero() -> Self {
Padding {
left: 0,
right: 0,
@ -56,7 +56,7 @@ impl Padding {
}
}
pub fn horizontal(value: u16) -> Self {
pub const fn horizontal(value: u16) -> Self {
Padding {
left: value,
right: value,
@ -65,7 +65,7 @@ impl Padding {
}
}
pub fn vertical(value: u16) -> Self {
pub const fn vertical(value: u16) -> Self {
Padding {
left: 0,
right: 0,
@ -74,7 +74,7 @@ impl Padding {
}
}
pub fn uniform(value: u16) -> Self {
pub const fn uniform(value: u16) -> Self {
Padding {
left: value,
right: value,
@ -139,21 +139,24 @@ pub struct Block<'a> {
impl<'a> Default for Block<'a> {
fn default() -> Block<'a> {
Block {
titles: Vec::new(),
titles_style: Style::default(),
titles_alignment: Alignment::Left,
titles_position: Position::default(),
borders: Borders::NONE,
border_style: Style::default(),
border_type: BorderType::Plain,
style: Style::default(),
padding: Padding::zero(),
}
Block::new()
}
}
impl<'a> Block<'a> {
pub const fn new() -> Self {
Self {
titles: Vec::new(),
titles_style: Style::new(),
titles_alignment: Alignment::Left,
titles_position: Position::Top,
borders: Borders::NONE,
border_style: Style::new(),
border_type: BorderType::Plain,
style: Style::new(),
padding: Padding::zero(),
}
}
/// # Example
/// ```
/// # use ratatui::widgets::{Block, block::title::Title};
@ -192,7 +195,7 @@ impl<'a> Block<'a> {
}
/// Applies the style to all titles. If a title already has a style, it will add on top of it.
pub fn title_style(mut self, style: Style) -> Block<'a> {
pub const fn title_style(mut self, style: Style) -> Block<'a> {
self.titles_style = style;
self
}
@ -210,7 +213,7 @@ impl<'a> Block<'a> {
/// .title("bar")
/// .title_alignment(Alignment::Center);
/// ```
pub fn title_alignment(mut self, alignment: Alignment) -> Block<'a> {
pub const fn title_alignment(mut self, alignment: Alignment) -> Block<'a> {
self.titles_alignment = alignment;
self
}
@ -233,27 +236,27 @@ impl<'a> Block<'a> {
/// .title("bar")
/// .title_position(Position::Bottom);
/// ```
pub fn title_position(mut self, position: Position) -> Block<'a> {
pub const fn title_position(mut self, position: Position) -> Block<'a> {
self.titles_position = position;
self
}
pub fn border_style(mut self, style: Style) -> Block<'a> {
pub const fn border_style(mut self, style: Style) -> Block<'a> {
self.border_style = style;
self
}
pub fn style(mut self, style: Style) -> Block<'a> {
pub const fn style(mut self, style: Style) -> Block<'a> {
self.style = style;
self
}
pub fn borders(mut self, flag: Borders) -> Block<'a> {
pub const fn borders(mut self, flag: Borders) -> Block<'a> {
self.borders = flag;
self
}
pub fn border_type(mut self, border_type: BorderType) -> Block<'a> {
pub const fn border_type(mut self, border_type: BorderType) -> Block<'a> {
self.border_type = border_type;
self
}
@ -317,7 +320,7 @@ impl<'a> Block<'a> {
inner
}
pub fn padding(mut self, padding: Padding) -> Block<'a> {
pub const fn padding(mut self, padding: Padding) -> Block<'a> {
self.padding = padding;
self
}
@ -827,4 +830,34 @@ mod tests {
},
);
}
#[test]
fn border_type_can_be_const() {
const _PLAIN: line::Set = BorderType::line_symbols(BorderType::Plain);
}
#[test]
fn padding_can_be_const() {
const PADDING: Padding = Padding::new(1, 1, 1, 1);
const UNI_PADDING: Padding = Padding::uniform(1);
assert_eq!(PADDING, UNI_PADDING);
const _NO_PADDING: Padding = Padding::zero();
const _HORIZONTAL: Padding = Padding::horizontal(1);
const _VERTICAL: Padding = Padding::vertical(1);
}
#[test]
fn block_can_be_const() {
const _DEFAULT_STYLE: Style = Style::new();
const _DEFAULT_PADDING: Padding = Padding::uniform(1);
const _DEFAULT_BLOCK: Block = Block::new()
.title_style(_DEFAULT_STYLE)
.title_alignment(Alignment::Left)
.title_position(Position::Top)
.borders(Borders::ALL)
.border_style(_DEFAULT_STYLE)
.style(_DEFAULT_STYLE)
.padding(_DEFAULT_PADDING);
}
}