Skip to content

Commit

Permalink
feat: add Rect::positions iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
joshka committed Feb 6, 2024
1 parent 30ea293 commit 2c04d99
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/layout/rect.rs
Expand Up @@ -265,6 +265,24 @@ impl Rect {
Columns::new(self)
}

/// An iterator over the positions within the `Rect`.
///
/// The positions are returned in a row-major order (left-to-right, top-to-bottom).
///
/// # Example
///
/// ```
/// # use ratatui::prelude::*;
/// fn render(area: Rect, buf: &mut Buffer) {
/// for position in area.positions() {
/// buf.get_mut(position.x, position.y).set_symbol("x");
/// }
/// }
/// ```
pub fn positions(self) -> Positions {
Positions::new(self)

Check warning on line 283 in src/layout/rect.rs

View check run for this annotation

Codecov / codecov/patch

src/layout/rect.rs#L282-L283

Added lines #L282 - L283 were not covered by tests
}

/// Returns a [`Position`] with the same coordinates as this rect.
///
/// # Examples
Expand Down
53 changes: 53 additions & 0 deletions src/layout/rect/iter.rs
@@ -1,3 +1,4 @@
use self::layout::Position;
use crate::prelude::*;

/// An iterator over rows within a `Rect`.
Expand Down Expand Up @@ -68,9 +69,50 @@ impl Iterator for Columns {
}
}

/// An iterator over positions within a `Rect`.
///
/// The iterator will yield all positions within the `Rect` in a row-major order.
pub struct Positions {
/// The `Rect` associated with the positions.
pub rect: Rect,
/// The current position within the `Rect`.
pub current_position: Position,
}

impl Positions {
/// Creates a new `Positions` iterator.
pub fn new(rect: Rect) -> Self {
Self {
rect,
current_position: Position::new(rect.x, rect.y),
}
}
}

impl Iterator for Positions {
type Item = Position;

/// Retrieves the next position within the `Rect`.
///
/// Returns `None` when there are no more positions to iterate through.
fn next(&mut self) -> Option<Self::Item> {
if self.current_position.y >= self.rect.bottom() {
return None;
}
let position = self.current_position;
self.current_position.x += 1;
if self.current_position.x >= self.rect.right() {
self.current_position.x = self.rect.x;
self.current_position.y += 1;
}
Some(position)
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::layout::Position;

#[test]
fn rows() {
Expand All @@ -89,4 +131,15 @@ mod tests {
assert_eq!(columns.next(), Some(Rect::new(1, 0, 1, 2)));
assert_eq!(columns.next(), None);
}

#[test]
fn positions() {
let rect = Rect::new(0, 0, 2, 2);
let mut positions = Positions::new(rect);
assert_eq!(positions.next(), Some(Position::new(0, 0)));
assert_eq!(positions.next(), Some(Position::new(1, 0)));
assert_eq!(positions.next(), Some(Position::new(0, 1)));
assert_eq!(positions.next(), Some(Position::new(1, 1)));
assert_eq!(positions.next(), None);
}
}

0 comments on commit 2c04d99

Please sign in to comment.