class RatatuiRuby::Layout::Rect
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
area = Layout::Rect.new(x: 0, y: 0, width: 80, height: 24) puts area.width # => 80
Attributes
Height in characters (Integer, coerced via to_int or to_i).
Width in characters (Integer, coerced via to_int or to_i).
X coordinate (column) of the top-left corner (Integer, coerced via to_int or to_i).
Y coordinate (row) of the top-left corner (Integer, coerced via to_int or to_i).
Public Class Methods
Source
# 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
Public Instance Methods
Source
# File lib/ratatui_ruby/layout/rect.rb, line 286 def area width * height end
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
rect = Layout::Rect.new(x: 0, y: 0, width: 10, height: 5) rect.area # => 50
Source
# File lib/ratatui_ruby/layout/rect.rb, line 263 def bottom y + height end
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
rect = Layout::Rect.new(x: 10, y: 5, width: 80, height: 24) rect.bottom # => 29
Source
# File lib/ratatui_ruby/layout/rect.rb, line 430 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
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
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)
Source
# File lib/ratatui_ruby/layout/rect.rb, line 483 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
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
rect = Layout::Rect.new(x: 0, y: 0, width: 5, height: 3) rect.columns.map { |c| c.x } # => [0, 1, 2, 3, 4]
Source
# File lib/ratatui_ruby/layout/rect.rb, line 96 def contains?(px, py) px >= x && px < x + width && py >= y && py < y + height end
Tests whether a point is inside this rectangle.
Essential for hit testing mouse clicks against layout regions.
area = Layout::Rect.new(x: 10, y: 5, width: 20, height: 10) area.contains?(15, 8) # => true area.contains?(5, 8) # => false
- px
-
X coordinate to test (column).
- py
-
Y coordinate to test (row).
Returns true if the point (px, py) is within the rectangle bounds.
Source
# File lib/ratatui_ruby/layout/rect.rb, line 309 def empty? width.zero? || height.zero? end
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
Layout::Rect.new(width: 0, height: 10).empty? # => true Layout::Rect.new(width: 10, height: 5).empty? # => false
Source
# 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
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
rect = Layout::Rect.new(x: 0, y: 0, width: 20, height: 10) rect.inner(2) # => Rect(x: 2, y: 2, width: 16, height: 6)
Source
# 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
Returns the overlapping area between this rectangle and another.
Essential for calculating visible portions of widgets inside scroll views.
viewport = Layout::Rect.new(x: 0, y: 0, width: 80, height: 24) widget = Layout::Rect.new(x: 70, y: 20, width: 20, height: 10) visible = viewport.intersection(widget) # => Rect(x: 70, y: 20, width: 10, height: 4)
- other
-
Another
Rectto intersect with.
Returns a new Rect representing the intersection, or nil if no overlap.
Source
# 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
Tests whether this rectangle overlaps with another.
Essential for determining if a widget is visible within a viewport or clipping area.
viewport = Layout::Rect.new(x: 0, y: 0, width: 80, height: 24) widget = Layout::Rect.new(x: 70, y: 20, width: 20, height: 10) viewport.intersects?(widget) # => true (partial overlap)
- other
-
Another
Rectto test against.
Returns true if the rectangles overlap.
Source
# File lib/ratatui_ruby/layout/rect.rb, line 194 def left x end
Source
# File lib/ratatui_ruby/layout/rect.rb, line 404 def offset(dx, dy) Rect.new(x: x + dx, y: y + dy, width:, height:) end
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
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)
Source
# File lib/ratatui_ruby/layout/rect.rb, line 510 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
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
rect = Layout::Rect.new(x: 0, y: 0, width: 2, height: 2) rect.positions.to_a # => [[0, 0], [1, 0], [0, 1], [1, 1]]
Source
# File lib/ratatui_ruby/layout/rect.rb, line 217 def right x + width end
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
rect = Layout::Rect.new(x: 10, y: 5, width: 80, height: 24) rect.right # => 90
Source
# File lib/ratatui_ruby/layout/rect.rb, line 457 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
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
rect = Layout::Rect.new(x: 0, y: 0, width: 5, height: 3) rect.rows.map { |r| r.y } # => [0, 1, 2]
Source
# File lib/ratatui_ruby/layout/rect.rb, line 240 def top y end
Source
# 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
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
-
Rectto merge.
Example
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)