Class: Tuile::Component::TextField
- Inherits:
-
Tuile::Component
- Object
- Tuile::Component
- Tuile::Component::TextField
- Defined in:
- lib/tuile/component/text_field.rb
Overview
A single-line text input field with hardware-cursor caret.
The field does not scroll. Any keystroke that would make #text longer than ‘rect.width - 1` (the last column is reserved for the caret past the last char) is rejected.
The caret is a logical index in ‘0..text.length`. The hardware cursor is positioned by Screen after each repaint cycle when this component is focused; see #cursor_position.
Constant Summary collapse
- ACTIVE_BG_SGR =
256-color SGR for the focused-button highlight (matches what ‘Rainbow(…).bg(:darkslategray)` emits, which is what Button#repaint uses for its focused state).
"\e[48;5;59m"- INACTIVE_BG_SGR =
256-color SGR for the unfocused field’s “well”: index 238 sits in the grayscale ramp (~#444444), bright enough to stand out against non-pure-black terminal themes (Gruvbox/Solarized/OneDark base backgrounds sit in the #1d–#2d range), and still distinctly darker than the active highlight at index 59 (~#5f5f5f). Rainbow’s RGB-to-256 mapping snaps everything dark to palette index 16 (terminal black), so we emit the escape directly to reach the ramp.
"\e[48;5;238m"- SGR_RESET =
SGR reset.
"\e[0m"
Instance Attribute Summary collapse
-
#caret ⇒ Integer
Caret index in ‘0..text.length`.
-
#on_change ⇒ Proc, ...
Optional callback fired whenever #text changes.
-
#on_enter ⇒ Proc, ...
Optional callback fired when ENTER is pressed.
-
#on_escape ⇒ Proc, ...
Optional callback fired when ESC is pressed.
-
#on_key_down ⇒ Proc, ...
Optional callback fired when the DOWN arrow key is pressed.
-
#on_key_up ⇒ Proc, ...
Optional callback fired when the UP arrow key is pressed.
-
#text ⇒ String
Current text contents.
Attributes inherited from Tuile::Component
Instance Method Summary collapse
- #cursor_position ⇒ Point?
- #focusable? ⇒ Boolean
- #handle_key(key) ⇒ Boolean
- #handle_mouse(event) ⇒ void
-
#initialize ⇒ TextField
constructor
A new instance of TextField.
- #repaint ⇒ void
- #tab_stop? ⇒ Boolean
Methods inherited from Tuile::Component
#active=, #active?, #attached?, #children, #content_size, #depth, #find_shortcut_component, #focus, #keyboard_hint, #on_child_removed, #on_focus, #on_tree, #root, #screen
Constructor Details
#initialize ⇒ TextField
Returns a new instance of TextField.
15 16 17 18 19 20 21 22 23 24 |
# File 'lib/tuile/component/text_field.rb', line 15 def initialize super @text = +"" @caret = 0 @on_escape = nil @on_change = nil @on_key_up = nil @on_key_down = nil @on_enter = nil end |
Instance Attribute Details
#caret ⇒ Integer
Returns caret index in ‘0..text.length`.
30 31 32 |
# File 'lib/tuile/component/text_field.rb', line 30 def caret @caret end |
#on_change ⇒ Proc, ...
42 43 44 |
# File 'lib/tuile/component/text_field.rb', line 42 def on_change @on_change end |
#on_enter ⇒ Proc, ...
Optional callback fired when ENTER is pressed. When set, ENTER is consumed by the field; when nil, ENTER falls through to the parent (default behavior).
62 63 64 |
# File 'lib/tuile/component/text_field.rb', line 62 def on_enter @on_enter end |
#on_escape ⇒ Proc, ...
Optional callback fired when ESC is pressed. When set, ESC is consumed by the field; when nil, ESC falls through to the parent (default behavior).
36 37 38 |
# File 'lib/tuile/component/text_field.rb', line 36 def on_escape @on_escape end |
#on_key_down ⇒ Proc, ...
Optional callback fired when the DOWN arrow key is pressed. When set, DOWN is consumed by the field; when nil, DOWN falls through to the parent (default behavior). Only triggered by Keys::DOWN_ARROW, not by ‘j`, since `j` is a printable character inserted into #text.
56 57 58 |
# File 'lib/tuile/component/text_field.rb', line 56 def on_key_down @on_key_down end |
#on_key_up ⇒ Proc, ...
Optional callback fired when the UP arrow key is pressed. When set, UP is consumed by the field; when nil, UP falls through to the parent (default behavior). Only triggered by Keys::UP_ARROW, not by ‘k`, since `k` is a printable character inserted into #text.
49 50 51 |
# File 'lib/tuile/component/text_field.rb', line 49 def on_key_up @on_key_up end |
#text ⇒ String
Returns current text contents.
27 28 29 |
# File 'lib/tuile/component/text_field.rb', line 27 def text @text end |
Instance Method Details
#cursor_position ⇒ Point?
93 94 95 96 97 |
# File 'lib/tuile/component/text_field.rb', line 93 def cursor_position return nil unless rect.width.positive? Point.new(rect.left + @caret, rect.top) end |
#focusable? ⇒ Boolean
88 |
# File 'lib/tuile/component/text_field.rb', line 88 def focusable? = true |
#handle_key(key) ⇒ Boolean
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/tuile/component/text_field.rb', line 101 def handle_key(key) return false unless active? return true if super case key when Keys::LEFT_ARROW then self.caret = @caret - 1 when Keys::RIGHT_ARROW then self.caret = @caret + 1 when Keys::CTRL_LEFT_ARROW then self.caret = word_left when Keys::CTRL_RIGHT_ARROW then self.caret = word_right when *Keys::HOMES then self.caret = 0 when *Keys::ENDS_ then self.caret = @text.length when *Keys::BACKSPACES then delete_before_caret when Keys::DELETE then delete_at_caret when Keys::ESC return false if @on_escape.nil? @on_escape.call when Keys::UP_ARROW return false if @on_key_up.nil? @on_key_up.call when Keys::DOWN_ARROW return false if @on_key_down.nil? @on_key_down.call when Keys::ENTER return false if @on_enter.nil? @on_enter.call else return insert(key) if printable?(key) return false end true end |
#handle_mouse(event) ⇒ void
This method returns an undefined value.
140 141 142 143 144 145 |
# File 'lib/tuile/component/text_field.rb', line 140 def handle_mouse(event) super return unless event. == :left && rect.contains?(event.point) self.caret = (event.x - rect.left).clamp(0, @text.length) end |
#repaint ⇒ void
This method returns an undefined value.
166 167 168 169 170 171 172 |
# File 'lib/tuile/component/text_field.rb', line 166 def repaint return if rect.empty? bg = active? ? ACTIVE_BG_SGR : INACTIVE_BG_SGR padded = @text + (" " * (rect.width - @text.length)) screen.print TTY::Cursor.move_to(rect.left, rect.top), bg, padded, SGR_RESET end |
#tab_stop? ⇒ Boolean
90 |
# File 'lib/tuile/component/text_field.rb', line 90 def tab_stop? = true |