Class: RatatuiRuby::Layout::Rect
- Inherits:
-
Object
- Object
- RatatuiRuby::Layout::Rect
- Defined in:
- lib/ratatui_ruby/layout/rect.rb
Overview
Defines a rectangular area in the terminal grid.
Geometry management involves passing groups of four integers (‘x, y, width, height`) repeatedly. This is verbose and prone to parameter mismatch errors.
This class encapsulates the geometry. It provides a standard primitive for passing area definitions between layout engines and rendering functions.
Use it when manual positioning is required or when querying layout results.
Examples
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
area = Layout::Rect.new(x: 0, y: 0, width: 80, height: 24)
puts area.width # => 80
– SPDX-SnippetEnd ++
Instance Method Summary collapse
-
#area ⇒ Object
Total area in cells.
-
#as_position ⇒ Object
(also: #position)
Extracts the position (x, y) from this rect.
-
#as_size ⇒ Object
(also: #size)
Extracts the size (width, height) from this rect.
-
#bottom ⇒ Object
Bottom edge coordinate.
-
#centered(horizontal_constraint, vertical_constraint) ⇒ Object
Returns a new Rect, centered both horizontally and vertically within this rect.
-
#centered_horizontally(constraint) ⇒ Object
Returns a new Rect, centered horizontally within this rect based on the constraint.
-
#centered_vertically(constraint) ⇒ Object
Returns a new Rect, centered vertically within this rect based on the constraint.
-
#clamp(other) ⇒ Object
Constrains the rect to fit inside bounds.
-
#columns ⇒ Object
Iterates over vertical slices.
-
#contains?(px, py) ⇒ Boolean
Tests whether a point is inside this rectangle.
-
#empty? ⇒ Boolean
True when the rect has zero area.
-
#initialize(x: 0, y: 0, width: 0, height: 0) ⇒ Rect
constructor
Creates a new Rect.
-
#inner(margin) ⇒ Object
Shrinks the rect by a uniform margin on all sides.
-
#intersection(other) ⇒ Object
Returns the overlapping area between this rectangle and another.
-
#intersects?(other) ⇒ Boolean
Tests whether this rectangle overlaps with another.
-
#left ⇒ Object
Left edge coordinate.
-
#offset(dx, dy) ⇒ Object
Moves the rect without changing size.
-
#outer(margin) ⇒ Object
Expands the rect by a uniform margin on all sides.
-
#positions ⇒ Object
Iterates over every cell in row-major order.
-
#resize(new_size) ⇒ Object
Changes dimensions while preserving position.
-
#right ⇒ Object
Right edge coordinate.
-
#rows ⇒ Object
Iterates over horizontal slices.
-
#to_ary ⇒ Object
Enables array destructuring of the rectangle.
-
#top ⇒ Object
Top edge coordinate.
-
#union(other) ⇒ Object
Bounding box containing both rectangles.
Constructor Details
#initialize(x: 0, y: 0, width: 0, height: 0) ⇒ Rect
Creates a new Rect.
All parameters accept any object responding to to_int or to_i (duck-typed).
- x
-
Column index (Numeric).
- y
-
Row index (Numeric).
- width
-
Width in columns (Numeric).
- height
-
Height in rows (Numeric).
57 58 59 60 61 62 63 64 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 57 def initialize(x: 0, y: 0, width: 0, height: 0) super( x: Integer(x), y: Integer(y), width: Integer(width), height: Integer(height) ) end |
Instance Method Details
#area ⇒ Object
Total area in cells.
Size comparisons and allocation calculations need area. Computing width * height inline is noisy and error-prone.
This method does the multiplication once.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 0, y: 0, width: 10, height: 5)
rect.area # => 50
– SPDX-SnippetEnd ++
286 287 288 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 286 def area width * height end |
#as_position ⇒ Object Also known as: position
Extracts the position (x, y) from this rect.
Layout code sometimes separates position from size. Extracting x and y into multiple variables is verbose.
This method returns a Position object containing just the coordinates.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 10, y: 5, width: 80, height: 24)
rect.as_position # => Position(x: 10, y: 5)
– SPDX-SnippetEnd ++
596 597 598 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 596 def as_position Position.new(x:, y:) end |
#as_size ⇒ Object Also known as: size
Extracts the size (width, height) from this rect.
Layout code sometimes separates size from position. Extracting width and height into multiple variables is verbose.
This method returns a Size object containing just the dimensions.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 10, y: 5, width: 80, height: 24)
rect.as_size # => Size(width: 80, height: 24)
– SPDX-SnippetEnd ++
619 620 621 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 619 def as_size Size.new(width:, height:) end |
#bottom ⇒ Object
Bottom edge coordinate.
Bounds checks compare edges. Writing y + height inline clutters conditions. Errors creep in when you forget the addition.
This method computes and names the boundary. Returns the first row outside the rect.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 10, y: 5, width: 80, height: 24)
rect.bottom # => 29
– SPDX-SnippetEnd ++
263 264 265 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 263 def bottom y + height end |
#centered(horizontal_constraint, vertical_constraint) ⇒ Object
Returns a new Rect, centered both horizontally and vertically within this rect.
Modal dialogs often need exact centering on both axes. Computing both offsets manually is tedious.
This method chains centered_horizontally and centered_vertically.
- horizontal_constraint
-
Constraint defining the width of the centered area.
- vertical_constraint
-
Constraint defining the height of the centered area.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 0, y: 0, width: 100, height: 100)
rect.centered(Constraint.length(40), Constraint.length(20))
# => Rect(x: 30, y: 40, width: 40, height: 20)
– SPDX-SnippetEnd ++
700 701 702 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 700 def centered(horizontal_constraint, vertical_constraint) centered_horizontally(horizontal_constraint).centered_vertically(vertical_constraint) end |
#centered_horizontally(constraint) ⇒ Object
Returns a new Rect, centered horizontally within this rect based on the constraint.
Modal dialogs and centered content need horizontal centering. Computing the left offset manually is error-prone.
This method uses Layout to compute the centered position.
- constraint
-
Constraint defining the width of the centered area.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 0, y: 0, width: 100, height: 24)
rect.centered_horizontally(Constraint.length(40))
# => Rect(x: 30, y: 0, width: 40, height: 24)
– SPDX-SnippetEnd ++
645 646 647 648 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 645 def centered_horizontally(constraint) areas = Layout.split(self, direction: :horizontal, constraints: [constraint], flex: :center) areas.first end |
#centered_vertically(constraint) ⇒ Object
Returns a new Rect, centered vertically within this rect based on the constraint.
Modal dialogs and centered content need vertical centering. Computing the top offset manually is error-prone.
This method uses Layout to compute the centered position.
- constraint
-
Constraint defining the height of the centered area.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 0, y: 0, width: 80, height: 100)
rect.centered_vertically(Constraint.length(20))
# => Rect(x: 0, y: 40, width: 80, height: 20)
– SPDX-SnippetEnd ++
672 673 674 675 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 672 def centered_vertically(constraint) areas = Layout.split(self, direction: :vertical, constraints: [constraint], flex: :center) areas.first end |
#clamp(other) ⇒ Object
Constrains the rect to fit inside bounds.
Popups and tooltips may extend beyond screen edges. Manually clamping x, y, width, and height is verbose and error-prone.
This method repositions and shrinks the rect to stay within bounds.
- other
-
Bounding Rect.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
screen = Layout::Rect.new(x: 0, y: 0, width: 100, height: 100)
popup = Layout::Rect.new(x: 80, y: 80, width: 30, height: 30)
popup.clamp(screen) # => Rect(x: 70, y: 70, width: 30, height: 30)
– SPDX-SnippetEnd ++
487 488 489 490 491 492 493 494 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 487 def clamp(other) clamped_width = [width, other.width].min clamped_height = [height, other.height].min clamped_x = x.clamp(other.left, other.right - clamped_width) clamped_y = y.clamp(other.top, other.bottom - clamped_height) Rect.new(x: clamped_x, y: clamped_y, width: clamped_width, height: clamped_height) end |
#columns ⇒ Object
Iterates over vertical slices.
Grids render column by column. Looping width.times and constructing rects inline is noisy.
This method yields each column as a Rect with width 1. Returns an Enumerator if no block given.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 0, y: 0, width: 5, height: 3)
rect.columns.map { |c| c.x } # => [0, 1, 2, 3, 4]
– SPDX-SnippetEnd ++
540 541 542 543 544 545 546 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 540 def columns return to_enum(:columns) unless block_given? width.times do |i| yield Rect.new(x: x + i, y:, width: 1, height:) end end |
#contains?(px, py) ⇒ Boolean
Tests whether a point is inside this rectangle.
Essential for hit testing mouse clicks against layout regions.
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
area = Layout::Rect.new(x: 10, y: 5, width: 20, height: 10)
area.contains?(15, 8) # => true
area.contains?(5, 8) # => false
– SPDX-SnippetEnd ++
- px
-
X coordinate to test (column).
- py
-
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
Y coordinate to test (row).– SPDX-SnippetEnd ++ Returns true if the point (px, py) is within the rectangle bounds.
96 97 98 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 96 def contains?(px, py) px >= x && px < x + width && py >= y && py < y + height end |
#empty? ⇒ Boolean
True when the rect has zero area.
Zero-width or zero-height rects break layout math. Checking width == 0 || height == 0 inline is tedious and easy to forget.
Guard clauses call empty? to skip degenerate rects.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
Layout::Rect.new(width: 0, height: 10).empty? # => true
Layout::Rect.new(width: 10, height: 5).empty? # => false
– SPDX-SnippetEnd ++
309 310 311 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 309 def empty? width.zero? || height.zero? end |
#inner(margin) ⇒ Object
Shrinks the rect by a uniform margin on all sides.
Widgets render text inside borders. Subtracting margin from all four edges inline is verbose. Off-by-one errors happen when you forget to double the margin.
This method computes the content area. Returns a zero-area rect if margin exceeds dimensions.
- margin
-
Integer padding on all sides.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 0, y: 0, width: 20, height: 10)
rect.inner(2) # => Rect(x: 2, y: 2, width: 16, height: 6)
– SPDX-SnippetEnd ++
370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 370 def inner(margin) doubled = margin * 2 return Rect.new(x: 0, y: 0, width: 0, height: 0) if width < doubled || height < doubled Rect.new( x: x + margin, y: y + margin, width: width - doubled, height: height - doubled ) end |
#intersection(other) ⇒ Object
Returns the overlapping area between this rectangle and another.
Essential for calculating visible portions of widgets inside scroll views.
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
= Layout::Rect.new(x: 0, y: 0, width: 80, height: 24)
= Layout::Rect.new(x: 70, y: 20, width: 20, height: 10)
visible = .intersection()
# => Rect(x: 70, y: 20, width: 10, height: 4)
– SPDX-SnippetEnd ++
- other
-
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
Another Rect to intersect with.– SPDX-SnippetEnd ++ Returns a new Rect representing the intersection, or
nilif no overlap.
164 165 166 167 168 169 170 171 172 173 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 164 def intersection(other) return nil unless intersects?(other) new_x = [x, other.x].max new_y = [y, other.y].max new_right = [x + width, other.x + other.width].min new_bottom = [y + height, other.y + other.height].min Rect.new(x: new_x, y: new_y, width: new_right - new_x, height: new_bottom - new_y) end |
#intersects?(other) ⇒ Boolean
Tests whether this rectangle overlaps with another.
Essential for determining if a widget is visible within a viewport or clipping area.
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
= Layout::Rect.new(x: 0, y: 0, width: 80, height: 24)
= Layout::Rect.new(x: 70, y: 20, width: 20, height: 10)
.intersects?() # => true (partial overlap)
– SPDX-SnippetEnd ++
- other
-
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
Another Rect to test against.– SPDX-SnippetEnd ++ Returns true if the rectangles overlap.
128 129 130 131 132 133 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 128 def intersects?(other) x < other.x + other.width && x + width > other.x && y < other.y + other.height && y + height > other.y end |
#left ⇒ Object
Left edge coordinate.
Layout algorithms compute bounding boxes and check overlaps. Reading rect.x forces you to remember that x means “left.”
Call left instead. Your code reads like prose.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 10, y: 5, width: 80, height: 24)
rect.left # => 10
– SPDX-SnippetEnd ++
194 195 196 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 194 def left x end |
#offset(dx, dy) ⇒ Object
Moves the rect without changing size.
Animations and drag-and-drop shift widgets. Adding offsets to x and y inline clutters the code.
This method returns a translated copy.
- dx
-
Horizontal shift (positive moves right).
- dy
-
Vertical shift (positive moves down).
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 10, y: 5, width: 20, height: 10)
rect.offset(5, 3) # => Rect(x: 15, y: 8, width: 20, height: 10)
– SPDX-SnippetEnd ++
435 436 437 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 435 def offset(dx, dy) Rect.new(x: x + dx, y: y + dy, width:, height:) end |
#outer(margin) ⇒ Object
Expands the rect by a uniform margin on all sides.
Containers wrap content with decorations. Adding margin to all four edges inline is verbose. Off-by-one errors happen when you forget to double the margin.
This method computes the outer area. Saturates x/y at 0 when margin exceeds position. Use Rect#clamp to constrain the result if it may exceed screen bounds.
- margin
-
Integer expansion on all sides.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 10, y: 10, width: 20, height: 10)
rect.outer(5) # => Rect(x: 5, y: 5, width: 30, height: 20)
– SPDX-SnippetEnd ++
404 405 406 407 408 409 410 411 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 404 def outer(margin) new_x = [x - margin, 0].max new_y = [y - margin, 0].max new_width = right + margin - new_x new_height = bottom + margin - new_y Rect.new(x: new_x, y: new_y, width: new_width, height: new_height) end |
#positions ⇒ Object
Iterates over every cell in row-major order.
Hit testing and pixel rendering touch every position. Nested loops with manual coordinate math are verbose.
This method yields [x, y] pairs. Returns an Enumerator if no block given.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 0, y: 0, width: 2, height: 2)
rect.positions.to_a # => [[0, 0], [1, 0], [0, 1], [1, 1]]
– SPDX-SnippetEnd ++
567 568 569 570 571 572 573 574 575 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 567 def positions return to_enum(:positions) unless block_given? height.times do |row| width.times do |col| yield [x + col, y + row] end end end |
#resize(new_size) ⇒ Object
Changes dimensions while preserving position.
Window resizing and responsive layouts adjust size mid-session. Creating a new rect with the same position but different size is common.
This method returns a resized copy. Position unchanged.
- new_size
-
Size object with new dimensions.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 10, y: 5, width: 20, height: 10)
rect.resize(Size.new(width: 40, height: 20))
# => Rect(x: 10, y: 5, width: 40, height: 20)
– SPDX-SnippetEnd ++
461 462 463 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 461 def resize(new_size) Rect.new(x:, y:, width: new_size.width, height: new_size.height) end |
#right ⇒ Object
Right edge coordinate.
Bounds checks compare edges. Writing x + width inline clutters conditions. Errors creep in when you forget the addition.
This method computes and names the boundary. Returns the first column outside the rect.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 10, y: 5, width: 80, height: 24)
rect.right # => 90
– SPDX-SnippetEnd ++
217 218 219 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 217 def right x + width end |
#rows ⇒ Object
Iterates over horizontal slices.
Lists render line by line. Looping height.times and constructing rects inline is noisy.
This method yields each row as a Rect with height 1. Returns an Enumerator if no block given.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 0, y: 0, width: 5, height: 3)
rect.rows.map { |r| r.y } # => [0, 1, 2]
– SPDX-SnippetEnd ++
514 515 516 517 518 519 520 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 514 def rows return to_enum(:rows) unless block_given? height.times do |i| yield Rect.new(x:, y: y + i, width:, height: 1) end end |
#to_ary ⇒ Object
Enables array destructuring of the rectangle.
Inline viewports and layout code often need position and size together. Accessing x, y, width, height individually is verbose.
This method allows convenient array destructuring.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
area = tui.
x, y, width, height = area
# Now you can use x, y, width, height directly
– SPDX-SnippetEnd ++
724 725 726 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 724 def to_ary [x, y, width, height] end |
#top ⇒ Object
Top edge coordinate.
Layout algorithms compute bounding boxes and check overlaps. Reading rect.y forces you to remember that y means “top.”
Call top instead. Your code reads like prose.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
rect = Layout::Rect.new(x: 10, y: 5, width: 80, height: 24)
rect.top # => 5
– SPDX-SnippetEnd ++
240 241 242 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 240 def top y end |
#union(other) ⇒ Object
Bounding box containing both rectangles.
Damage tracking and hit testing combine rects. Computing min/max of all four edges inline is tedious and error-prone.
This method returns the smallest rect that encloses both.
- other
-
Rect to merge.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
r1 = Layout::Rect.new(x: 0, y: 0, width: 10, height: 10)
r2 = Layout::Rect.new(x: 5, y: 5, width: 10, height: 10)
r1.union(r2) # => Rect(x: 0, y: 0, width: 15, height: 15)
– SPDX-SnippetEnd ++
335 336 337 338 339 340 341 342 343 344 345 346 347 |
# File 'lib/ratatui_ruby/layout/rect.rb', line 335 def union(other) new_x = [left, other.left].min new_y = [top, other.top].min new_right = [right, other.right].max new_bottom = [bottom, other.bottom].max Rect.new( x: new_x, y: new_y, width: new_right - new_x, height: new_bottom - new_y ) end |