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
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).
Public Instance Methods
Source
# File lib/ratatui_ruby/layout/rect.rb, line 286 def area width * height end
Source
# File lib/ratatui_ruby/layout/rect.rb, line 596 def as_position Position.new(x:, y:) end
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
rect = Layout::Rect.new(x: 10, y: 5, width: 80, height: 24) rect.as_position # => Position(x: 10, y: 5)
Source
# File lib/ratatui_ruby/layout/rect.rb, line 619 def as_size Size.new(width:, height:) end
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
rect = Layout::Rect.new(x: 10, y: 5, width: 80, height: 24) rect.as_size # => Size(width: 80, height: 24)
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 700 def centered(horizontal_constraint, vertical_constraint) centered_horizontally(horizontal_constraint).centered_vertically(vertical_constraint) end
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
-
Constraintdefining the width of the centered area. - vertical_constraint
-
Constraintdefining the height of the centered area.
Example
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)
Source
# 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
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
-
Constraintdefining the width of the centered area.
Example
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)
Source
# 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
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
-
Constraintdefining the height of the centered area.
Example
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)
Source
# 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
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 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
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 435 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 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
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
rect = Layout::Rect.new(x: 10, y: 10, width: 20, height: 10) rect.outer(5) # => Rect(x: 5, y: 5, width: 30, height: 20)
Source
# 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
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 461 def resize(new_size) Rect.new(x:, y:, width: new_size.width, height: new_size.height) end
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
-
Sizeobject with new dimensions.
Example
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)
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 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
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 724 def to_ary [x, y, width, height] end
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
area = tui.viewport_area x, y, width, height = area # Now you can use x, y, width, height directly
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)