mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-25 06:00:34 +00:00
feat!: add an impl of DoubleEndedIterator
for Columns
and Rows
(#1358)
BREAKING-CHANGE: The `pub` modifier has been removed from fields on the `layout::rect::Columns` and `layout::rect::Rows` iterators. These fields were not intended to be public and should not have been accessed directly. Fixes: #1357
This commit is contained in:
parent
3df685e114
commit
7bdccce3d5
2 changed files with 138 additions and 21 deletions
|
@ -10,12 +10,13 @@ GitHub with a [breaking change] label.
|
|||
|
||||
This is a quick summary of the sections below:
|
||||
|
||||
- [v0.29.0](#v0290)
|
||||
- [v0.29.0](#unreleased)
|
||||
- Removed public fields from `Rect` iterators
|
||||
- `Line` now implements `From<Cow<str>`
|
||||
- `Table::highlight_style` is now `Table::row_highlight_style`
|
||||
- `Tabs::select` now accepts `Into<Option<usize>>`
|
||||
- [v0.28.0](#v0280)
|
||||
⁻ `Backend::size` returns `Size` instead of `Rect`
|
||||
- `Backend::size` returns `Size` instead of `Rect`
|
||||
- `Backend` trait migrates to `get/set_cursor_position`
|
||||
- Ratatui now requires Crossterm 0.28.0
|
||||
- `Axis::labels` now accepts `IntoIterator<Into<Line>>`
|
||||
|
@ -69,7 +70,15 @@ This is a quick summary of the sections below:
|
|||
- MSRV is now 1.63.0
|
||||
- `List` no longer ignores empty strings
|
||||
|
||||
## v0.29.0 (Unreleased)
|
||||
## Unreleased
|
||||
|
||||
### Removed public fields from `Rect` iterators ([#1358])
|
||||
|
||||
[#1358]: https://github.com/ratatui/ratatui/pull/1358
|
||||
|
||||
The `pub` modifier has been removed from fields on the `layout::rect::Columns` and
|
||||
`layout::rect::Rows`. These fields were not intended to be public and should not have been accessed
|
||||
directly.
|
||||
|
||||
### `Rect::area()` now returns u32 instead of u16 ([#1378])
|
||||
|
||||
|
@ -117,8 +126,9 @@ The `Table::highlight_style` is now deprecated in favor of `Table::row_highlight
|
|||
|
||||
Also, the serialized output of the `TableState` will now include the "selected_column" field.
|
||||
Software that manually parse the serialized the output (with anything other than the `Serialize`
|
||||
implementation on `TableState`) may have to be refactored if the "selected_column" field is not accounted for.
|
||||
This does not affect users who rely on the `Deserialize`, or `Serialize` implementation on the state.
|
||||
implementation on `TableState`) may have to be refactored if the "selected_column" field is not
|
||||
accounted for. This does not affect users who rely on the `Deserialize`, or `Serialize`
|
||||
implementation on the state.
|
||||
|
||||
## v0.28.0
|
||||
|
||||
|
|
|
@ -3,9 +3,11 @@ use crate::layout::{Position, Rect};
|
|||
/// An iterator over rows within a `Rect`.
|
||||
pub struct Rows {
|
||||
/// The `Rect` associated with the rows.
|
||||
pub rect: Rect,
|
||||
/// The y coordinate of the row within the `Rect`.
|
||||
pub current_row: u16,
|
||||
rect: Rect,
|
||||
/// The y coordinate of the row within the `Rect` when iterating forwards.
|
||||
current_row_fwd: u16,
|
||||
/// The y coordinate of the row within the `Rect` when iterating backwards.
|
||||
current_row_back: u16,
|
||||
}
|
||||
|
||||
impl Rows {
|
||||
|
@ -13,7 +15,8 @@ impl Rows {
|
|||
pub const fn new(rect: Rect) -> Self {
|
||||
Self {
|
||||
rect,
|
||||
current_row: rect.y,
|
||||
current_row_fwd: rect.y,
|
||||
current_row_back: rect.bottom(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +28,25 @@ impl Iterator for Rows {
|
|||
///
|
||||
/// Returns `None` when there are no more rows to iterate through.
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.current_row >= self.rect.bottom() {
|
||||
if self.current_row_fwd >= self.current_row_back {
|
||||
return None;
|
||||
}
|
||||
let row = Rect::new(self.rect.x, self.current_row, self.rect.width, 1);
|
||||
self.current_row += 1;
|
||||
let row = Rect::new(self.rect.x, self.current_row_fwd, self.rect.width, 1);
|
||||
self.current_row_fwd += 1;
|
||||
Some(row)
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Rows {
|
||||
/// Retrieves the previous row within the `Rect`.
|
||||
///
|
||||
/// Returns `None` when there are no more rows to iterate through.
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if self.current_row_back <= self.current_row_fwd {
|
||||
return None;
|
||||
}
|
||||
self.current_row_back -= 1;
|
||||
let row = Rect::new(self.rect.x, self.current_row_back, self.rect.width, 1);
|
||||
Some(row)
|
||||
}
|
||||
}
|
||||
|
@ -37,9 +54,11 @@ impl Iterator for Rows {
|
|||
/// An iterator over columns within a `Rect`.
|
||||
pub struct Columns {
|
||||
/// The `Rect` associated with the columns.
|
||||
pub rect: Rect,
|
||||
/// The x coordinate of the column within the `Rect`.
|
||||
pub current_column: u16,
|
||||
rect: Rect,
|
||||
/// The x coordinate of the column within the `Rect` when iterating forwards.
|
||||
current_column_fwd: u16,
|
||||
/// The x coordinate of the column within the `Rect` when iterating backwards.
|
||||
current_column_back: u16,
|
||||
}
|
||||
|
||||
impl Columns {
|
||||
|
@ -47,7 +66,8 @@ impl Columns {
|
|||
pub const fn new(rect: Rect) -> Self {
|
||||
Self {
|
||||
rect,
|
||||
current_column: rect.x,
|
||||
current_column_fwd: rect.x,
|
||||
current_column_back: rect.right(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,11 +79,25 @@ impl Iterator for Columns {
|
|||
///
|
||||
/// Returns `None` when there are no more columns to iterate through.
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.current_column >= self.rect.right() {
|
||||
if self.current_column_fwd >= self.current_column_back {
|
||||
return None;
|
||||
}
|
||||
let column = Rect::new(self.current_column, self.rect.y, 1, self.rect.height);
|
||||
self.current_column += 1;
|
||||
let column = Rect::new(self.current_column_fwd, self.rect.y, 1, self.rect.height);
|
||||
self.current_column_fwd += 1;
|
||||
Some(column)
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Columns {
|
||||
/// Retrieves the previous column within the `Rect`.
|
||||
///
|
||||
/// Returns `None` when there are no more columns to iterate through.
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if self.current_column_back <= self.current_column_fwd {
|
||||
return None;
|
||||
}
|
||||
self.current_column_back -= 1;
|
||||
let column = Rect::new(self.current_column_back, self.rect.y, 1, self.rect.height);
|
||||
Some(column)
|
||||
}
|
||||
}
|
||||
|
@ -114,19 +148,92 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn rows() {
|
||||
let rect = Rect::new(0, 0, 2, 2);
|
||||
let rect = Rect::new(0, 0, 2, 3);
|
||||
let mut rows = Rows::new(rect);
|
||||
assert_eq!(rows.next(), Some(Rect::new(0, 0, 2, 1)));
|
||||
assert_eq!(rows.next(), Some(Rect::new(0, 1, 2, 1)));
|
||||
assert_eq!(rows.next(), Some(Rect::new(0, 2, 2, 1)));
|
||||
assert_eq!(rows.next(), None);
|
||||
assert_eq!(rows.next_back(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rows_back() {
|
||||
let rect = Rect::new(0, 0, 2, 3);
|
||||
let mut rows = Rows::new(rect);
|
||||
assert_eq!(rows.next_back(), Some(Rect::new(0, 2, 2, 1)));
|
||||
assert_eq!(rows.next_back(), Some(Rect::new(0, 1, 2, 1)));
|
||||
assert_eq!(rows.next_back(), Some(Rect::new(0, 0, 2, 1)));
|
||||
assert_eq!(rows.next_back(), None);
|
||||
assert_eq!(rows.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rows_meet_in_the_middle() {
|
||||
let rect = Rect::new(0, 0, 2, 4);
|
||||
let mut rows = Rows::new(rect);
|
||||
assert_eq!(rows.next(), Some(Rect::new(0, 0, 2, 1)));
|
||||
assert_eq!(rows.next_back(), Some(Rect::new(0, 3, 2, 1)));
|
||||
assert_eq!(rows.next(), Some(Rect::new(0, 1, 2, 1)));
|
||||
assert_eq!(rows.next_back(), Some(Rect::new(0, 2, 2, 1)));
|
||||
assert_eq!(rows.next(), None);
|
||||
assert_eq!(rows.next_back(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn columns() {
|
||||
let rect = Rect::new(0, 0, 2, 2);
|
||||
let rect = Rect::new(0, 0, 3, 2);
|
||||
let mut columns = Columns::new(rect);
|
||||
assert_eq!(columns.next(), Some(Rect::new(0, 0, 1, 2)));
|
||||
assert_eq!(columns.next(), Some(Rect::new(1, 0, 1, 2)));
|
||||
assert_eq!(columns.next(), Some(Rect::new(2, 0, 1, 2)));
|
||||
assert_eq!(columns.next(), None);
|
||||
assert_eq!(columns.next_back(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn columns_back() {
|
||||
let rect = Rect::new(0, 0, 3, 2);
|
||||
let mut columns = Columns::new(rect);
|
||||
assert_eq!(columns.next_back(), Some(Rect::new(2, 0, 1, 2)));
|
||||
assert_eq!(columns.next_back(), Some(Rect::new(1, 0, 1, 2)));
|
||||
assert_eq!(columns.next_back(), Some(Rect::new(0, 0, 1, 2)));
|
||||
assert_eq!(columns.next_back(), None);
|
||||
assert_eq!(columns.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn columns_meet_in_the_middle() {
|
||||
let rect = Rect::new(0, 0, 4, 2);
|
||||
let mut columns = Columns::new(rect);
|
||||
assert_eq!(columns.next(), Some(Rect::new(0, 0, 1, 2)));
|
||||
assert_eq!(columns.next_back(), Some(Rect::new(3, 0, 1, 2)));
|
||||
assert_eq!(columns.next(), Some(Rect::new(1, 0, 1, 2)));
|
||||
assert_eq!(columns.next_back(), Some(Rect::new(2, 0, 1, 2)));
|
||||
assert_eq!(columns.next(), None);
|
||||
assert_eq!(columns.next_back(), None);
|
||||
}
|
||||
|
||||
/// We allow a total of `65536` columns in the range `(0..=65535)`. In this test we iterate
|
||||
/// forward and skip the first `65534` columns, and expect the next column to be `65535` and
|
||||
/// the subsequent columns to be `None`.
|
||||
#[test]
|
||||
fn columns_max() {
|
||||
let rect = Rect::new(0, 0, u16::MAX, 1);
|
||||
let mut columns = Columns::new(rect).skip(usize::from(u16::MAX - 1));
|
||||
assert_eq!(columns.next(), Some(Rect::new(u16::MAX - 1, 0, 1, 1)));
|
||||
assert_eq!(columns.next(), None);
|
||||
}
|
||||
|
||||
/// We allow a total of `65536` columns in the range `(0..=65535)`. In this test we iterate
|
||||
/// backward and skip the last `65534` columns, and expect the next column to be `0` and the
|
||||
/// subsequent columns to be `None`.
|
||||
#[test]
|
||||
fn columns_min() {
|
||||
let rect = Rect::new(0, 0, u16::MAX, 1);
|
||||
let mut columns = Columns::new(rect).rev().skip(usize::from(u16::MAX - 1));
|
||||
assert_eq!(columns.next(), Some(Rect::new(0, 0, 1, 1)));
|
||||
assert_eq!(columns.next(), None);
|
||||
assert_eq!(columns.next(), None);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue