Class: TuiTui::Rect

Inherits:
Data
  • Object
show all
Defined in:
lib/tui_tui/rect.rb

Overview

A 1-origin screen rectangle with pure layout helpers.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#colObject (readonly)

Returns the value of attribute col

Returns:

  • (Object)

    the current value of col



5
6
7
# File 'lib/tui_tui/rect.rb', line 5

def col
  @col
end

#colsObject (readonly)

Returns the value of attribute cols

Returns:

  • (Object)

    the current value of cols



5
6
7
# File 'lib/tui_tui/rect.rb', line 5

def cols
  @cols
end

#rowObject (readonly)

Returns the value of attribute row

Returns:

  • (Object)

    the current value of row



5
6
7
# File 'lib/tui_tui/rect.rb', line 5

def row
  @row
end

#rowsObject (readonly)

Returns the value of attribute rows

Returns:

  • (Object)

    the current value of rows



5
6
7
# File 'lib/tui_tui/rect.rb', line 5

def rows
  @rows
end

Class Method Details

.centered(within, cols:, rows:) ⇒ Object



6
7
8
9
10
11
12
13
# File 'lib/tui_tui/rect.rb', line 6

def self.centered(within, cols:, rows:)
  new(
    row: [((within.rows - rows) / 2) + 1, 1].max,
    col: [((within.cols - cols) / 2) + 1, 1].max,
    rows: rows,
    cols: cols
  )
end

.of(size) ⇒ Object

The Rect covering a whole screen: row/col 1 over anything with Size-compatible rows / cols (a Size or a RenderContext).



17
18
19
# File 'lib/tui_tui/rect.rb', line 17

def self.of(size)
  new(row: 1, col: 1, rows: size.rows, cols: size.cols)
end

Instance Method Details

#hit?(mouse) ⇒ Boolean

Whether a MouseEvent's cell falls inside this rectangle.

Returns:

  • (Boolean)


81
# File 'lib/tui_tui/rect.rb', line 81

def hit?(mouse) = include?(mouse.row, mouse.col)

#include?(r, c) ⇒ Boolean

Whether a 1-origin cell (row, col) falls inside this rectangle.

Returns:

  • (Boolean)


76
77
78
# File 'lib/tui_tui/rect.rb', line 76

def include?(r, c)
  r.between?(row, row + rows - 1) && c.between?(col, col + cols - 1)
end

#shift_right(by) ⇒ Object



71
72
73
# File 'lib/tui_tui/rect.rb', line 71

def shift_right(by)
  Rect.new(row: row, col: col + by, rows: rows, cols: cols - by)
end

#split_cols(*constraints) ⇒ Object

Same as split_rows, but left to right over the columns.



62
63
64
65
66
67
68
69
# File 'lib/tui_tui/rect.rb', line 62

def split_cols(*constraints)
  left = col
  resolve_segments(constraints, cols).map do |size|
    segment = Rect.new(row: row, col: left, rows: rows, cols: size)
    left += size
    segment
  end
end

#split_gutter(width = 1) ⇒ Object

Carve width columns off the right edge for a scrollbar gutter. Returns [body, gutter]; gutter is nil when the rect is too narrow to spare them.



85
86
87
88
89
# File 'lib/tui_tui/rect.rb', line 85

def split_gutter(width = 1)
  return [self, nil] if cols <= width

  [with(cols: cols - width), Rect.new(row: row, col: col + cols - width, rows: rows, cols: width)]
end

#split_h(top_rows) ⇒ Object



21
22
23
24
25
# File 'lib/tui_tui/rect.rb', line 21

def split_h(top_rows)
  top = Rect.new(row: row, col: col, rows: top_rows, cols: cols)
  bottom = Rect.new(row: row + top_rows, col: col, rows: rows - top_rows, cols: cols)
  [top, bottom]
end

#split_ratio(ratio, min: 0, gutter: 0) ⇒ Object

Split into [left, right] by ratio of the width



34
35
36
37
38
39
40
# File 'lib/tui_tui/rect.rb', line 34

def split_ratio(ratio, min: 0, gutter: 0)
  lo = min
  hi = cols - min - gutter
  left_cols = hi < lo ? cols / 2 : (cols * ratio).round.clamp(lo, hi)
  left, right = split_v(left_cols)
  [left, right.shift_right(gutter)]
end

#split_rows(*constraints) ⇒ Object

Split into stacked Rects, top to bottom, one per constraint: an Integer is a fixed number of rows, a Float a fraction of the whole ((rows * f).round), and :rest shares whatever the fixed and fractional segments leave over (several :rest split it evenly, leading ones taking the indivisible remainder). Sizes resolve front to back, each clamped to what is still left, so an undersized rect squashes trailing segments to 0 rather than raising — the same live-and-let-live rule as split_ratio. Without a :rest, leftover space stays unassigned (no implicit stretch). Every constraint yields a Rect (possibly 0-sized), so destructuring is stable: header, body, status = rect.split_rows(2, :rest, 2).



52
53
54
55
56
57
58
59
# File 'lib/tui_tui/rect.rb', line 52

def split_rows(*constraints)
  top = row
  resolve_segments(constraints, rows).map do |size|
    segment = Rect.new(row: top, col: col, rows: size, cols: cols)
    top += size
    segment
  end
end

#split_v(left_cols) ⇒ Object



27
28
29
30
31
# File 'lib/tui_tui/rect.rb', line 27

def split_v(left_cols)
  left = Rect.new(row: row, col: col, rows: rows, cols: left_cols)
  right = Rect.new(row: row, col: col + left_cols, rows: rows, cols: cols - left_cols)
  [left, right]
end