Class: Potty::Widgets::TextInput

Inherits:
Base
  • Object
show all
Defined in:
lib/potty/widgets/text_input.rb

Overview

Single-line editable text field. Shows a block cursor when focused, a dim placeholder when empty and unfocused, and scrolls horizontally when the text outgrows the field. The editing model is a LineEditor (shared with the list InputItem); this widget owns rendering + scroll.

Emits :change(text) on every edit. ASCII input only for now (matches the rest of the framework); UTF-8 entry would need multibyte getch.

Instance Attribute Summary collapse

Attributes inherited from Base

#app, #focused, #parent, #rect

Instance Method Summary collapse

Methods inherited from Base

#activate, #blur, #deactivate, #focus, #handle_escape, #hide, #layout, #on_blur, #on_focus, #on_layout, #show, #theme, #tick, #visible=, #visible?

Methods included from Events

#emit, #listeners?, #off, #on

Constructor Details

#initialize(app, text: '', placeholder: '', max_length: nil, on_change: nil) ⇒ TextInput

Returns a new instance of TextInput.



19
20
21
22
23
24
25
# File 'lib/potty/widgets/text_input.rb', line 19

def initialize(app, text: '', placeholder: '', max_length: nil, on_change: nil)
  super(app)
  @editor = LineEditor.new(text, max_length: max_length)
  @placeholder = placeholder
  @on_change = on_change
  @scroll = 0
end

Instance Attribute Details

#on_changeObject

Returns the value of attribute on_change.



17
18
19
# File 'lib/potty/widgets/text_input.rb', line 17

def on_change
  @on_change
end

#placeholderObject

Returns the value of attribute placeholder.



17
18
19
# File 'lib/potty/widgets/text_input.rb', line 17

def placeholder
  @placeholder
end

Instance Method Details

#can_focus?Boolean

Returns:

  • (Boolean)


27
28
29
# File 'lib/potty/widgets/text_input.rb', line 27

def can_focus?
  true
end

#handle_key(ch) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/potty/widgets/text_input.rb', line 52

def handle_key(ch)
  case ch
  when Keys::LEFT then @editor.left
  when Keys::RIGHT then @editor.right
  when Keys::HOME, Keys::CTRL_A then @editor.home
  when Keys::END_, Keys::CTRL_E then @editor.to_end
  when Keys::DEL_ASCII, Keys::CTRL_H, Keys::BACKSPACE then changed(@editor.backspace)
  when Keys::DELETE, Keys::CTRL_D then changed(@editor.delete_forward)
  when Keys::SPACE..(Keys::DEL_ASCII - 1) then changed(@editor.insert(ch.chr))
  else
    return false
  end
  true
end

#max_lengthObject



40
41
42
# File 'lib/potty/widgets/text_input.rb', line 40

def max_length
  @editor.max_length
end

#max_length=(value) ⇒ Object



44
45
46
# File 'lib/potty/widgets/text_input.rb', line 44

def max_length=(value)
  @editor.max_length = value
end

#preferred_height(_width) ⇒ Object



48
49
50
# File 'lib/potty/widgets/text_input.rb', line 48

def preferred_height(_width)
  1
end

#render(window) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/potty/widgets/text_input.rb', line 67

def render(window)
  return unless @visible && @rect

  width = @rect.width
  adjust_scroll(width)

  if text.empty? && !@focused
    window.setpos(@rect.y, @rect.x)
    window.attron(theme.style(:dim)) do
      window.addstr(@placeholder.to_s[0, width].to_s.ljust(width))
    end
    return
  end

  visible = (text[@scroll, width] || '').ljust(width)
  window.setpos(@rect.y, @rect.x)
  window.attron(theme.style(:normal)) { window.addstr(visible) }

  return unless @focused

  # Block cursor: reverse-video the cell under the caret.
  col = @editor.cursor - @scroll
  return if col.negative? || col >= width

  char_under = text[@editor.cursor] || ' '
  window.setpos(@rect.y, @rect.x + col)
  window.attron(theme.style(:normal, reverse: true)) do
    window.addstr(char_under)
  end
end

#textObject



31
32
33
# File 'lib/potty/widgets/text_input.rb', line 31

def text
  @editor.text
end

#text=(value) ⇒ Object



35
36
37
38
# File 'lib/potty/widgets/text_input.rb', line 35

def text=(value)
  @editor.text = value
  notify_change
end