Class: Tuile::Component::TextField
- Defined in:
- lib/tuile/component/text_field.rb,
sig/tuile.rbs
Overview
A single-line text input field with hardware-cursor caret.
The field does not scroll. Any keystroke that would make Tuile::Component::TextInput#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.
Instance Attribute Summary collapse
-
#on_enter ⇒ Proc, ...
Optional callback fired when ENTER 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.
Attributes inherited from TextInput
#caret, #on_change, #on_escape, #on_key, #text
Instance Method Summary collapse
- #cursor_position ⇒ Point?
-
#handle_mouse(event) ⇒ void
@param
event. -
#handle_text_input_key(key) ⇒ Boolean
@param
key. -
#initialize ⇒ TextField
constructor
A new instance of TextField.
-
#insert(char) ⇒ Boolean
@param
char. -
#max_text_length ⇒ Integer
Maximum number of characters Tuile::Component::TextInput#text can hold given current width.
- #on_width_changed ⇒ void
-
#preprocess_text(new_text) ⇒ String
Truncate to fit
rect.width - 1— single-line fields can't grow past their width. - #repaint ⇒ void
Methods inherited from TextInput
#background, #default_on_escape, #delete_at_caret, #delete_before_caret, #empty?, #focusable?, #handle_key, #on_caret_mutated, #on_text_mutated, #tab_stop?, #word_left, #word_right
Constructor Details
#initialize ⇒ TextField
Returns a new instance of TextField.
15 16 17 18 19 20 |
# File 'lib/tuile/component/text_field.rb', line 15 def initialize super @on_key_up = nil @on_key_down = nil @on_enter = nil end |
Instance Attribute Details
#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).
@return — no-arg callable, or nil.
40 41 42 |
# File 'lib/tuile/component/text_field.rb', line 40 def on_enter @on_enter 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 Tuile::Component::TextInput#text.
@return — no-arg callable, or nil.
34 35 36 |
# File 'lib/tuile/component/text_field.rb', line 34 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 Tuile::Component::TextInput#text.
@return — no-arg callable, or nil.
27 28 29 |
# File 'lib/tuile/component/text_field.rb', line 27 def on_key_up @on_key_up end |
Instance Method Details
#cursor_position ⇒ Point?
43 44 45 46 47 |
# File 'lib/tuile/component/text_field.rb', line 43 def cursor_position return nil unless rect.width.positive? Point.new(rect.left + @caret, rect.top) end |
#handle_mouse(event) ⇒ void
This method returns an undefined value.
@param event
51 52 53 54 55 56 |
# File 'lib/tuile/component/text_field.rb', line 51 def handle_mouse(event) super return unless event. == :left && rect.contains?(event.point) self.caret = (event.x - rect.left).clamp(0, @text.length) end |
#handle_text_input_key(key) ⇒ Boolean
@param key
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/tuile/component/text_field.rb', line 79 def handle_text_input_key(key) case key 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::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 Keys.printable?(key) return super end true end |
#insert(char) ⇒ Boolean
@param char
123 124 125 126 127 128 129 130 |
# File 'lib/tuile/component/text_field.rb', line 123 def insert(char) return false if @text.length >= max_text_length new_text = @text.dup.insert(@caret, char) @caret += 1 self.text = new_text true end |
#max_text_length ⇒ Integer
Maximum number of characters Tuile::Component::TextInput#text can hold given current width.
119 |
# File 'lib/tuile/component/text_field.rb', line 119 def max_text_length = (rect.width - 1).clamp(0, nil) |
#on_width_changed ⇒ void
This method returns an undefined value.
106 107 108 109 110 111 112 113 |
# File 'lib/tuile/component/text_field.rb', line 106 def on_width_changed super return if @text.length <= max_text_length @text = @text[0, [max_text_length, 0].max] @caret = @caret.clamp(0, @text.length) @on_change&.call(@text) end |
#preprocess_text(new_text) ⇒ String
Truncate to fit rect.width - 1 — single-line fields can't grow past
their width.
@param new_text
72 73 74 75 |
# File 'lib/tuile/component/text_field.rb', line 72 def preprocess_text(new_text) new_text = new_text.to_s new_text.length > max_text_length ? new_text[0, max_text_length] : new_text end |
#repaint ⇒ void
This method returns an undefined value.
59 60 61 62 63 64 |
# File 'lib/tuile/component/text_field.rb', line 59 def repaint return if rect.empty? padded = @text + (" " * (rect.width - @text.length)) screen.buffer.set_line(rect.left, rect.top, background(padded)) end |