Class: Charming::Presentation::Components::Viewport

Inherits:
Charming::Presentation::Component show all
Includes:
KeyboardHandler
Defined in:
lib/charming/presentation/components/viewport.rb

Overview

Viewport is a scrollable region over multi-line content. Supports keyboard scrolling (up/down/left/right, page up/down, home/end) and mouse interactions (scroll wheel and click-to-position). Lines are clipped with ANSI awareness via ‘UI::ANSISlicer` so styled text is preserved across horizontal scrolls. When `wrap:` is true, long lines are wrapped to the configured width before scrolling.

Constant Summary collapse

ANSI_PATTERN =

Matches an ANSI SGR escape sequence (e.g., “e[31m” for red foreground).

/\e\[[0-9;]*m/
KEY_ACTIONS =

Maps scroll keys to the instance methods that perform them via KeyboardHandler.

{
  up: :scroll_up,
  down: :scroll_down,
  page_up: :page_up,
  page_down: :page_down,
  home: :scroll_home,
  end: :scroll_end,
  left: :scroll_left,
  right: :scroll_right
}.freeze

Constants included from KeyboardHandler

KeyboardHandler::VIM_KEYMAP

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from KeyboardHandler

#handle_key

Methods inherited from View

#focused?, #layout_assigns

Constructor Details

#initialize(content:, width: nil, height: nil, offset: 0, column: 0, wrap: false, keymap: :vim) ⇒ Viewport

content may be a string, an array of lines, or any object responding to ‘render`. width and height constrain the visible window; offset is the top-visible row and column is the left-visible column. wrap enables soft-wrapping of long lines.



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/charming/presentation/components/viewport.rb', line 37

def initialize(content:, width: nil, height: nil, offset: 0, column: 0, wrap: false, keymap: :vim)
  super()
  @content = content
  @width = width
  @height = height
  @offset = offset
  @column = column
  @wrap = wrap
  @keymap = keymap
  clamp_position
end

Instance Attribute Details

#columnObject (readonly)

The current top-visible row and left-visible column, respectively.



32
33
34
# File 'lib/charming/presentation/components/viewport.rb', line 32

def column
  @column
end

#offsetObject (readonly)

The current top-visible row and left-visible column, respectively.



32
33
34
# File 'lib/charming/presentation/components/viewport.rb', line 32

def offset
  @offset
end

Instance Method Details

#handle_mouse(event) ⇒ Object

Handles mouse events: scroll wheel adjusts the row offset, click moves the top visible row to the clicked position. Returns :handled on success.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/charming/presentation/components/viewport.rb', line 56

def handle_mouse(event)
  return nil unless height

  if event.scroll?
    scroll_delta = (event.button_name == :scroll_up) ? -1 : 1
    @offset += scroll_delta
    clamp_position
    return :handled
  end

  return nil unless event.click?

  clicked_row = event.y
  return nil if clicked_row < offset || clicked_row >= offset + viewport_height

  @offset = clicked_row
  clamp_position
  :handled
end

#renderObject

Renders the visible window of content as a multi-line string.



50
51
52
# File 'lib/charming/presentation/components/viewport.rb', line 50

def render
  visible_lines.map { |line| render_line(line) }.join("\n")
end