Class: Charming::Components::Viewport

Inherits:
Charming::Component show all
Includes:
KeyboardHandler
Defined in:
lib/charming/presentation/components/viewport.rb,
lib/charming/presentation/components/viewport/position.rb,
lib/charming/presentation/components/viewport/line_window.rb,
lib/charming/presentation/components/viewport/content_lines.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.

Defined Under Namespace

Classes: ContentLines, LineWindow, Position

Constant Summary collapse

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 Method Summary collapse

Methods included from KeyboardHandler

#handle_key

Methods inherited from Charming::Component

#captures_text?

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.



28
29
30
31
32
33
34
35
36
37
# File 'lib/charming/presentation/components/viewport.rb', line 28

def initialize(content:, width: nil, height: nil, offset: 0, column: 0, wrap: false, keymap: :vim)
  super()
  @content = content
  @width = width
  @height = height
  @position = Position.new(offset: offset, column: column)
  @wrap = wrap
  @keymap = keymap
  position.clamp(bounds)
end

Instance Method Details

#columnObject

The current left-visible column.



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

def column
  @position.column
end

#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
# 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
    position.move_to(offset + scroll_delta, bounds)
    return :handled
  end

  return nil unless event.click?

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

  position.move_to(offset + clicked_row, bounds)
  :handled
end

#offsetObject

The current top-visible row.



45
46
47
# File 'lib/charming/presentation/components/viewport.rb', line 45

def offset
  @position.offset
end

#renderObject

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



40
41
42
# File 'lib/charming/presentation/components/viewport.rb', line 40

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