feat: add Rect::resize() method (#2240)

Fixes: https://github.com/ratatui/ratatui/issues/1440
This commit is contained in:
Josh McKinney
2025-11-30 12:00:03 -08:00
committed by GitHub
parent 96d097ef76
commit 24e3133456

View File

@@ -46,6 +46,7 @@ use super::{Constraint, Flex, Layout};
///
/// - [`inner`](Self::inner), [`outer`](Self::outer) - Apply margins to shrink or expand
/// - [`offset`](Self::offset) - Move the rectangle by a relative amount
/// - [`resize`](Self::resize) - Change the rectangle size while keeping the bottom/right in range
/// - [`union`](Self::union) - Combine with another rectangle to create a bounding box
/// - [`intersection`](Self::intersection) - Find the overlapping area with another rectangle
/// - [`clamp`](Self::clamp) - Constrain the rectangle to fit within another
@@ -116,6 +117,16 @@ use super::{Constraint, Flex, Layout};
/// assert_eq!(moved_rect, Rect::new(6, 8, 3, 4));
/// ```
///
/// To resize a `Rect` while ensuring it stays within bounds, use [`Rect::resize`]. The size is
/// clamped so that `right()` and `bottom()` do not exceed `u16::MAX`.
///
/// ```rust
/// use ratatui_core::layout::{Rect, Size};
///
/// let rect = Rect::new(u16::MAX - 1, u16::MAX - 1, 1, 1).resize(Size::new(10, 10));
/// assert_eq!(rect, Rect::new(u16::MAX - 1, u16::MAX - 1, 1, 1));
/// ```
///
/// For comprehensive layout documentation and examples, see the [`layout`](crate::layout) module.
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
@@ -275,6 +286,20 @@ impl Rect {
self + offset
}
/// Resizes the `Rect`, clamping to keep the right and bottom within `u16::MAX`.
///
/// The position is preserved. If the requested size would push the `Rect` beyond the bounds of
/// `u16`, the width or height is reduced so that [`right`](Self::right) and
/// [`bottom`](Self::bottom) remain within range.
#[must_use = "method returns the modified value"]
pub const fn resize(self, size: Size) -> Self {
Self {
width: self.x.saturating_add(size.width).saturating_sub(self.x),
height: self.y.saturating_add(size.height).saturating_sub(self.y),
..self
}
}
/// Returns a new `Rect` that contains both the current one and the given one.
#[must_use = "method returns the modified value"]
pub fn union(self, other: Self) -> Self {
@@ -861,6 +886,18 @@ mod tests {
);
}
#[test]
fn resize_updates_size() {
let rect = Rect::new(10, 20, 5, 5).resize(Size::new(30, 40));
assert_eq!(rect, Rect::new(10, 20, 30, 40));
}
#[test]
fn resize_clamps_at_bounds() {
let rect = Rect::new(u16::MAX - 2, u16::MAX - 3, 1, 1).resize(Size::new(10, 10));
assert_eq!(rect, Rect::new(u16::MAX - 2, u16::MAX - 3, 2, 3));
}
#[test]
fn can_be_const() {
const RECT: Rect = Rect {