Class: Tuile::VerticalScrollBar

Inherits:
Object
  • Object
show all
Defined in:
lib/tuile/vertical_scroll_bar.rb,
sig/tuile.rbs

Overview

Which glyph to draw at each row of a scrollbar. Built fresh per repaint from the viewport height and the content's scroll state, then asked row by row — the caller styles what comes back:

bar = VerticalScrollBar.new(10, row_count: 20, scroll_top_row: 0)
bar.scrollbar_char(0)   # => "█"  the handle: 20 rows of content, 10 shown
bar.scrollbar_char(9)   # => "░"  the track below it
StyledString.styled(bar.scrollbar_char(row), fg: screen.theme.scrollbar_color)

No arrows — the full height is the track — and no color of its own, so this class reaches no Screen. VerticalScrollBar.handle_char= / VerticalScrollBar.track_char= swap the two glyphs app-wide.

No handle is drawn when the content fits. A handle covering the whole track is a solid column carrying no information, so row_count <= height paints track at every row — while #handle_height / #handle_start / #handle_end still report the covering handle. Ink only: the caller's bar keeps its column and its content width (design/decisions.md D_scrollbar_ink).

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(height, row_count:, scroll_top_row:) ⇒ VerticalScrollBar

@param height — number of rows in the scrollbar (== viewport height).

@param row_count — total number of content rows.

@param scroll_top_row — index of the first visible content row.

Parameters:

  • height (Integer)
  • row_count: (Integer)
  • scroll_top_row: (Integer)


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/tuile/vertical_scroll_bar.rb', line 93

def initialize(height, row_count:, scroll_top_row:)
  @height = height
  @scrollable = row_count > height

  return unless height >= 1

  if @scrollable
    @handle_height = [(height * height / row_count.to_f).ceil, 1].max
    @handle_start  = (height * scroll_top_row / row_count.to_f).floor
    @handle_end    = @handle_start + @handle_height - 1
  else
    @handle_height = height
    @handle_start  = 0
    @handle_end    = height - 1
  end
end

Class Attribute Details

.handle_charString

The glyph drawn where the handle covers a row, by default. Set the pair at startup for a lazygit-style bar:

Tuile::VerticalScrollBar.handle_char = "▐"
Tuile::VerticalScrollBar.track_char  = "│"

Process-global, and assigning invalidates nothing — a change after the first paint shows up only where something repaints anyway.

Returns:

  • (String)


33
34
35
# File 'lib/tuile/vertical_scroll_bar.rb', line 33

def handle_char
  @handle_char
end

.track_charString

The glyph drawn on the rows the handle doesn't cover, by default — and on every row when the content fits, see the class docs.

Returns:

  • (String)


38
39
40
# File 'lib/tuile/vertical_scroll_bar.rb', line 38

def track_char
  @track_char
end

Instance Attribute Details

#handle_endInteger (readonly)

@return — 0-based row where the handle ends (height >= 1 only).

Returns:

  • (Integer)


87
88
89
# File 'lib/tuile/vertical_scroll_bar.rb', line 87

def handle_end
  @handle_end
end

#handle_heightInteger (readonly)

@return — number of track rows the handle occupies (height >= 1 only).

Returns:

  • (Integer)


83
84
85
# File 'lib/tuile/vertical_scroll_bar.rb', line 83

def handle_height
  @handle_height
end

#handle_startInteger (readonly)

@return — 0-based row where the handle starts (height >= 1 only).

Returns:

  • (Integer)


85
86
87
# File 'lib/tuile/vertical_scroll_bar.rb', line 85

def handle_start
  @handle_start
end

Instance Method Details

#scrollbar_char(row_in_viewport) ⇒ String

The glyph for one viewport row: handle_char where the handle covers it, track_char elsewhere — and at every row when the content fits (see the class docs).

@param row_in_viewport — 0-based row index within the viewport.

@return — single scrollbar character.

Parameters:

  • row_in_viewport (Integer)

Returns:

  • (String)


115
116
117
118
119
120
# File 'lib/tuile/vertical_scroll_bar.rb', line 115

def scrollbar_char(row_in_viewport)
  return self.class.track_char unless @scrollable

  on_handle = row_in_viewport >= @handle_start && row_in_viewport <= @handle_end
  on_handle ? self.class.handle_char : self.class.track_char
end