termgui 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/termgui.rb +1 -1
- metadata +40 -107
- data/Gemfile +0 -14
- data/README.md +0 -321
- data/src/action.rb +0 -58
- data/src/box.rb +0 -90
- data/src/color.rb +0 -174
- data/src/cursor.rb +0 -69
- data/src/editor/editor_base.rb +0 -152
- data/src/editor/editor_base_handlers.rb +0 -116
- data/src/element.rb +0 -61
- data/src/element_bounds.rb +0 -111
- data/src/element_box.rb +0 -64
- data/src/element_render.rb +0 -102
- data/src/element_style.rb +0 -51
- data/src/emitter.rb +0 -102
- data/src/emitter_state.rb +0 -19
- data/src/enterable.rb +0 -93
- data/src/event.rb +0 -92
- data/src/focus.rb +0 -102
- data/src/geometry.rb +0 -53
- data/src/image.rb +0 -60
- data/src/input.rb +0 -85
- data/src/input_grab.rb +0 -17
- data/src/input_time.rb +0 -97
- data/src/key.rb +0 -114
- data/src/log.rb +0 -24
- data/src/node.rb +0 -117
- data/src/node_attributes.rb +0 -27
- data/src/node_visit.rb +0 -52
- data/src/renderer.rb +0 -119
- data/src/renderer_cursor.rb +0 -18
- data/src/renderer_draw.rb +0 -28
- data/src/renderer_image.rb +0 -31
- data/src/renderer_print.rb +0 -40
- data/src/screen.rb +0 -96
- data/src/screen_element.rb +0 -59
- data/src/screen_input.rb +0 -43
- data/src/screen_renderer.rb +0 -53
- data/src/style.rb +0 -149
- data/src/tco/colouring.rb +0 -248
- data/src/tco/config.rb +0 -57
- data/src/tco/palette.rb +0 -603
- data/src/tco/tco_termgui.rb +0 -30
- data/src/termgui.rb +0 -29
- data/src/util.rb +0 -110
- data/src/util/css.rb +0 -98
- data/src/util/css_query.rb +0 -23
- data/src/util/easing.rb +0 -364
- data/src/util/hash_object.rb +0 -131
- data/src/util/imagemagick.rb +0 -27
- data/src/util/justify.rb +0 -20
- data/src/util/unicode-categories.rb +0 -572
- data/src/util/wrap.rb +0 -102
- data/src/widget/button.rb +0 -33
- data/src/widget/checkbox.rb +0 -47
- data/src/widget/col.rb +0 -30
- data/src/widget/image.rb +0 -106
- data/src/widget/inline.rb +0 -40
- data/src/widget/input_number.rb +0 -73
- data/src/widget/inputbox.rb +0 -85
- data/src/widget/label.rb +0 -33
- data/src/widget/modal.rb +0 -69
- data/src/widget/row.rb +0 -26
- data/src/widget/selectbox.rb +0 -100
- data/src/widget/textarea.rb +0 -54
- data/src/xml/xml.rb +0 -80
- data/test/action_test.rb +0 -34
- data/test/box_test.rb +0 -15
- data/test/css_test.rb +0 -39
- data/test/editor/editor_base_test.rb +0 -201
- data/test/element_bounds_test.rb +0 -77
- data/test/element_box_test.rb +0 -8
- data/test/element_render_test.rb +0 -124
- data/test/element_style_test.rb +0 -85
- data/test/element_test.rb +0 -10
- data/test/emitter_test.rb +0 -108
- data/test/event_test.rb +0 -19
- data/test/focus_test.rb +0 -37
- data/test/geometry_test.rb +0 -12
- data/test/input_test.rb +0 -47
- data/test/key_test.rb +0 -14
- data/test/log_test.rb +0 -21
- data/test/node_test.rb +0 -105
- data/test/performance/performance1.rb +0 -48
- data/test/renderer_test.rb +0 -74
- data/test/renderer_test_rect.rb +0 -4
- data/test/screen_test.rb +0 -58
- data/test/style_test.rb +0 -18
- data/test/termgui_test.rb +0 -10
- data/test/test_all.rb +0 -30
- data/test/util_hash_object_test.rb +0 -93
- data/test/util_test.rb +0 -26
- data/test/widget/checkbox_test.rb +0 -99
- data/test/widget/col_test.rb +0 -87
- data/test/widget/inline_test.rb +0 -40
- data/test/widget/label_test.rb +0 -94
- data/test/widget/row_test.rb +0 -40
- data/test/wrap_test.rb +0 -11
- data/test/xml_test.rb +0 -77
data/src/util/wrap.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
# taken from https://github.com/pazdera/word_wrap/blob/master/lib/word_wrap/wrapper.rb
|
2
|
-
#
|
3
|
-
# Copyright (c) 2014, 2015 Radek Pazdera
|
4
|
-
# Distributed under the MIT License
|
5
|
-
#
|
6
|
-
# TODO: Refactor similar passages out of the two functions into a common one
|
7
|
-
class Wrapper
|
8
|
-
def initialize(text, width)
|
9
|
-
@text = text
|
10
|
-
@width = width
|
11
|
-
end
|
12
|
-
|
13
|
-
def fit
|
14
|
-
lines = []
|
15
|
-
next_line = ''
|
16
|
-
@text.lines do |line|
|
17
|
-
line.chomp! "\n"
|
18
|
-
if line.empty?
|
19
|
-
unless next_line.empty?
|
20
|
-
lines.push next_line
|
21
|
-
next_line = ''
|
22
|
-
end
|
23
|
-
lines.push ''
|
24
|
-
end
|
25
|
-
|
26
|
-
words = line.split ' '
|
27
|
-
|
28
|
-
words.each do |word|
|
29
|
-
word.chomp! "\n"
|
30
|
-
|
31
|
-
if next_line.length + word.length < @width
|
32
|
-
if !next_line.empty?
|
33
|
-
next_line << ' ' << word
|
34
|
-
else
|
35
|
-
next_line = word
|
36
|
-
end
|
37
|
-
else
|
38
|
-
if word.length >= @width
|
39
|
-
lines.push next_line unless next_line == ''
|
40
|
-
lines.push word
|
41
|
-
next_line = ''
|
42
|
-
else
|
43
|
-
lines.push next_line
|
44
|
-
next_line = word
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
lines.push next_line
|
51
|
-
if next_line.length <= 0
|
52
|
-
lines.join("\n")
|
53
|
-
else
|
54
|
-
lines.join("\n") + "\n"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def wrap
|
59
|
-
output = []
|
60
|
-
|
61
|
-
@text.lines do |line|
|
62
|
-
line.chomp! "\n"
|
63
|
-
if line.length > @width
|
64
|
-
new_lines = split_line(line, @width)
|
65
|
-
while new_lines.length > 1 && new_lines[1].length > @width
|
66
|
-
output.push new_lines[0]
|
67
|
-
new_lines = split_line new_lines[1], @width
|
68
|
-
end
|
69
|
-
output += new_lines
|
70
|
-
else
|
71
|
-
output.push line
|
72
|
-
end
|
73
|
-
end
|
74
|
-
output.map(&:rstrip!)
|
75
|
-
output.join("\n") + "\n"
|
76
|
-
end
|
77
|
-
|
78
|
-
def split_line(line, width)
|
79
|
-
at = line.index(/\s/)
|
80
|
-
last_at = at
|
81
|
-
|
82
|
-
while !at.nil? && at < width
|
83
|
-
last_at = at
|
84
|
-
at = line.index(/\s/, last_at + 1)
|
85
|
-
end
|
86
|
-
|
87
|
-
if last_at.nil?
|
88
|
-
[line]
|
89
|
-
else
|
90
|
-
[line[0, last_at], line[last_at + 1, line.length]]
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def wrap_text(text, width)
|
96
|
-
lines = text.split("\n")
|
97
|
-
a = lines.map do |line|
|
98
|
-
w = Wrapper.new(line, width).wrap
|
99
|
-
w.split("\n")
|
100
|
-
end
|
101
|
-
a.flatten
|
102
|
-
end
|
data/src/widget/button.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
require_relative 'label'
|
2
|
-
|
3
|
-
module TermGui
|
4
|
-
module Widget
|
5
|
-
# A button widget. Usage:
|
6
|
-
# Button.new(text: 'click me', style: {bg: 'blue'}, action: proc {|e| p 'actioned!'})
|
7
|
-
class Button < Label
|
8
|
-
def initialize(**args, &block)
|
9
|
-
super
|
10
|
-
@name = 'button'
|
11
|
-
install(:action)
|
12
|
-
set_attribute(:focusable, true)
|
13
|
-
end
|
14
|
-
|
15
|
-
def default_style
|
16
|
-
s = super
|
17
|
-
s.border = Border.new(fg: '#779966')
|
18
|
-
s.bg = '#336688'
|
19
|
-
s.fg = '#111111'
|
20
|
-
s.focus&.fg = 'red'
|
21
|
-
s.focus.bold = true
|
22
|
-
s.focus.underline = true
|
23
|
-
s.focus&.bg = 'grey'
|
24
|
-
s.focus&.border = Border.new(fg: 'green')
|
25
|
-
s.action&.bg = 'red'
|
26
|
-
s.action&.border = Border.new(fg: 'magenta', bold: true, bg: 'white')
|
27
|
-
s
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
Button = TermGui::Widget::Button
|
data/src/widget/checkbox.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require_relative 'button'
|
2
|
-
require_relative '../log'
|
3
|
-
require_relative '../util'
|
4
|
-
require_relative '../screen'
|
5
|
-
|
6
|
-
module TermGui
|
7
|
-
module Widget
|
8
|
-
# Similar to HTMLInputElement type="checkbox"
|
9
|
-
class CheckBox < Button
|
10
|
-
def initialize(**args)
|
11
|
-
super
|
12
|
-
@name = 'checkbox'
|
13
|
-
set_attribute('action-keys', %w[enter space])
|
14
|
-
set_attribute('label', text || get_attribute('label') || unique('Option'))
|
15
|
-
update_text get_attribute('value') || get_attribute('checked') || args[:value] || args[:checked] || false
|
16
|
-
on(:action) do |e|
|
17
|
-
update_text !get_attribute('value')
|
18
|
-
render
|
19
|
-
trigger(:input, TermGui::InputEvent.new(self, value, e))
|
20
|
-
trigger(:change, TermGui::ChangeEvent.new(self, value, e))
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def value
|
25
|
-
get_attribute('value')
|
26
|
-
end
|
27
|
-
|
28
|
-
def value=(v)
|
29
|
-
update_text v
|
30
|
-
end
|
31
|
-
|
32
|
-
def update_text(v = nil)
|
33
|
-
set_attribute('value', v) unless v == nil
|
34
|
-
self.text = "#{get_attribute('value') ? '[x]' : '[ ]'} #{get_attribute('label')}"
|
35
|
-
end
|
36
|
-
|
37
|
-
def default_style
|
38
|
-
s = super
|
39
|
-
s.border = nil
|
40
|
-
s.action = nil
|
41
|
-
s
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
CheckBox = TermGui::Widget::CheckBox
|
data/src/widget/col.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require_relative '../element'
|
2
|
-
module TermGui
|
3
|
-
module Widget
|
4
|
-
# Column container. A column child is rendered at the bottom of the previous child - all of them in one column.
|
5
|
-
# By default it will have height==0.999
|
6
|
-
class Col < Element
|
7
|
-
attr_accessor :gap
|
8
|
-
def initialize(**args)
|
9
|
-
# p(({height: 0.99999}.merge(args))[:height])
|
10
|
-
super({ height: 0.9999999 }.merge(args))
|
11
|
-
# p height, abs_height
|
12
|
-
@name = 'col'
|
13
|
-
@gap = args[:gap]||0
|
14
|
-
end
|
15
|
-
|
16
|
-
def layout
|
17
|
-
# init_y = abs_content_y
|
18
|
-
last_y = abs_content_y
|
19
|
-
@children.each do |c|
|
20
|
-
# last_y += 1 if c.style.border
|
21
|
-
c.abs_y = last_y
|
22
|
-
last_y += c.abs_height + @gap
|
23
|
-
# last_y += 1 if c.style.border
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
Col = TermGui::Widget::Col
|
data/src/widget/image.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
require_relative '../termgui'
|
2
|
-
|
3
|
-
module TermGui
|
4
|
-
module Widget
|
5
|
-
# analog to HTMLImageElement. Note that the image will be loaded only on render. Also it will be resized according to abs_content
|
6
|
-
# Properties:
|
7
|
-
# src: file path or TermGui::Image ot load
|
8
|
-
# transparent_color color to blend transparent pixels, by default style.bg
|
9
|
-
# ignore_alpha. if true alpha channel is ignored (could be faster)
|
10
|
-
# use_bg (true by default) will paint pixels using style.bg
|
11
|
-
# use_fg (false by default) will paint using style.fg
|
12
|
-
class Image < Element
|
13
|
-
attr_accessor :pan_x, :pan_y, :zoom
|
14
|
-
def initialize(**args)
|
15
|
-
super
|
16
|
-
@name = 'image'
|
17
|
-
@src = args[:src]
|
18
|
-
@use_bg = args[:use_bg] == nil ? true : args[:use_bg]
|
19
|
-
@use_fg = args[:use_fg] == nil ? false : args[:use_fg]
|
20
|
-
@transparent_color = args[:transparent_color]
|
21
|
-
@ignore_alpha = args[:ignore_alpha]
|
22
|
-
@zoom = args[:zoom] || 1.0
|
23
|
-
@pan_x = args[:pan_x] || 0.0
|
24
|
-
@pan_y = args[:pan_y] || 0.0
|
25
|
-
@chs = args[:chs] || [get_attribute('ch') || ' ']
|
26
|
-
@x_factor = args[:x_factor] || 2.0 # to improve non squared terminal "pixels"
|
27
|
-
@y_factor = args[:y_factor] || 1.2
|
28
|
-
end
|
29
|
-
|
30
|
-
def image
|
31
|
-
if !@image && @src
|
32
|
-
@image = @src.is_a?(String) ? TermGui::Image.new(@src) : @src
|
33
|
-
end
|
34
|
-
factor = (@image.width * 2.0 - abs_content_width) < (@image.height - abs_content_height) ?
|
35
|
-
@zoom * @x_factor * @image.width.to_f / abs_content_width.to_f :
|
36
|
-
@zoom * @y_factor * @image.height.to_f / abs_content_height.to_f
|
37
|
-
|
38
|
-
@resized_image = @image.scale(
|
39
|
-
width: (@image.width.to_f * @x_factor / factor).to_i,
|
40
|
-
height: (@image.height.to_f * @y_factor / factor).to_i
|
41
|
-
)
|
42
|
-
# root_screen.text(text: " #{[factor, @image.height, @image.width, @resized_image.width, @resized_image.height, abs_content_width,abs_content_height, abs_content_x, abs_content_y]}", y: 3, x: 55)
|
43
|
-
if @pan_x + @pan_y > 0
|
44
|
-
@resized_image = @resized_image.crop(
|
45
|
-
x: (@resized_image.width.to_f * @pan_x).to_i,
|
46
|
-
y: (@resized_image.height.to_f * @pan_y).to_i,
|
47
|
-
width: (@resized_image.width.to_f - @resized_image.width.to_f * @pan_x).to_i,
|
48
|
-
height: (@resized_image.height.to_f - @resized_image.height.to_f * @pan_y).to_i
|
49
|
-
)
|
50
|
-
end
|
51
|
-
@image
|
52
|
-
end
|
53
|
-
|
54
|
-
def chs=(v)
|
55
|
-
if @chs.join != v.join
|
56
|
-
@chs = v
|
57
|
-
self.dirty = true
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def original_image
|
62
|
-
@image
|
63
|
-
end
|
64
|
-
|
65
|
-
def current_image
|
66
|
-
@resized_image
|
67
|
-
end
|
68
|
-
|
69
|
-
def render_self(screen)
|
70
|
-
[
|
71
|
-
super,
|
72
|
-
image ? screen.image(
|
73
|
-
x: abs_content_x,
|
74
|
-
y: abs_content_y,
|
75
|
-
w: abs_content_width,
|
76
|
-
h: abs_content_height,
|
77
|
-
transparent_color: !@ignore_alpha ? TermGui.to_rgb(@transparent_color || final_style.bg || '#000000') : nil,
|
78
|
-
image: @resized_image,
|
79
|
-
bg: @use_bg,
|
80
|
-
fg: @use_fg,
|
81
|
-
style: final_style,
|
82
|
-
ch: @chs
|
83
|
-
) : ''
|
84
|
-
].join('')
|
85
|
-
end
|
86
|
-
|
87
|
-
def src=(v)
|
88
|
-
@src = v
|
89
|
-
@image = nil
|
90
|
-
refresh
|
91
|
-
end
|
92
|
-
|
93
|
-
def refresh(force_render = false)
|
94
|
-
@resized_image = nil
|
95
|
-
image
|
96
|
-
if force_render
|
97
|
-
self.dirty = true
|
98
|
-
clear
|
99
|
-
render
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
Image = TermGui::Widget::Image
|
data/src/widget/inline.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require_relative '../element'
|
2
|
-
module TermGui
|
3
|
-
module Widget
|
4
|
-
# an inline layout - similar to HTML display: inline - so I can add arbitrary elements.
|
5
|
-
# it will break when there is no more space and resize itself.
|
6
|
-
# TODO: almost there...
|
7
|
-
class Inline < Element
|
8
|
-
attr_accessor :horizontal_gap, :vertical_gap
|
9
|
-
def initialize(**args)
|
10
|
-
super({ width: 0.9999999 }.merge(args))
|
11
|
-
@name = 'inline'
|
12
|
-
@horizontal_gap = args[:horizontal_gap]||0
|
13
|
-
@vertical_gap = args[:vertical_gap]||0
|
14
|
-
end
|
15
|
-
|
16
|
-
def layout
|
17
|
-
last_y = abs_content_y
|
18
|
-
row_max_height = 1+ @vertical_gap
|
19
|
-
last_x = abs_content_x
|
20
|
-
total_height=0
|
21
|
-
@children.each do |c|
|
22
|
-
c.abs_x = last_x
|
23
|
-
c.abs_y = last_y
|
24
|
-
row_max_height = [row_max_height, c.abs_height].max
|
25
|
-
last_x += c.abs_width + @horizontal_gap
|
26
|
-
if last_x + @horizontal_gap+c.abs_width > abs_content_y + abs_content_width
|
27
|
-
last_x = abs_content_x
|
28
|
-
last_y += row_max_height + @vertical_gap
|
29
|
-
total_height+=row_max_height+@vertical_gap
|
30
|
-
row_max_height = 1+ @vertical_gap
|
31
|
-
end
|
32
|
-
end
|
33
|
-
self.height = [total_height + abs_padding.top + abs_padding.bottom + row_max_height, self.abs_height].max ##TODO borders
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
Inline = TermGui::Widget::Inline
|
40
|
-
|
data/src/widget/input_number.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
require_relative 'button'
|
2
|
-
require_relative '../enterable'
|
3
|
-
require_relative '../util'
|
4
|
-
require_relative '../screen'
|
5
|
-
|
6
|
-
module TermGui
|
7
|
-
module Widget
|
8
|
-
# analog to HTMLInputElement type="number"
|
9
|
-
class InputNumber < Button
|
10
|
-
include Enterable
|
11
|
-
def initialize(**args)
|
12
|
-
super
|
13
|
-
@name = 'input-number'
|
14
|
-
set_attribute('escape-on-blur', get_attribute('escape-on-blur') == nil ? true : get_attribute('escape-on-blur'))
|
15
|
-
set_attribute('action-on-focus', get_attribute('action-on-focus') == nil ? true : get_attribute('action-on-focus'))
|
16
|
-
end
|
17
|
-
|
18
|
-
def value
|
19
|
-
v = parse_float(text)
|
20
|
-
v == nil ? v : (v.to_i - v == 0 ? v.to_i : v)
|
21
|
-
end
|
22
|
-
|
23
|
-
def value=(v)
|
24
|
-
self.text = v.to_s
|
25
|
-
end
|
26
|
-
|
27
|
-
def handle_key(event)
|
28
|
-
if !super(event)
|
29
|
-
if event.key == 'up'
|
30
|
-
on_input value + 1, event
|
31
|
-
true
|
32
|
-
elsif event.key == 'down'
|
33
|
-
on_input value - 1, event
|
34
|
-
true
|
35
|
-
elsif numeric? event.key
|
36
|
-
self.text = text + event.key
|
37
|
-
if parse_float(text) == nil
|
38
|
-
render
|
39
|
-
else
|
40
|
-
on_input value, event
|
41
|
-
end
|
42
|
-
true
|
43
|
-
elsif event.key == 'backspace'
|
44
|
-
self.text = text.slice(0, [text.length - 1, 0].max)
|
45
|
-
if parse_float(text) == nil
|
46
|
-
render
|
47
|
-
else
|
48
|
-
on_input value, event
|
49
|
-
end
|
50
|
-
true
|
51
|
-
end
|
52
|
-
else
|
53
|
-
true
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
InputNumber = TermGui::Widget::InputNumber
|
61
|
-
|
62
|
-
# # p parse_float('9.')
|
63
|
-
|
64
|
-
# sb = nil
|
65
|
-
# s = Screen.new(children: [
|
66
|
-
# Button.new(text: 'hello', x: 0.7, y: 0.6, action: proc { |e|
|
67
|
-
# e.target.text = sb.value.to_s
|
68
|
-
# e.target.render
|
69
|
-
# }),
|
70
|
-
# (sb = InputNumber.new(x: 2, y: 1, width: 0.5, height: 0.5, value: 12))
|
71
|
-
# ])
|
72
|
-
|
73
|
-
# s.start
|
data/src/widget/inputbox.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
require_relative 'button'
|
2
|
-
require_relative '../enterable'
|
3
|
-
require_relative '../log'
|
4
|
-
require_relative '../cursor'
|
5
|
-
|
6
|
-
module TermGui
|
7
|
-
module Widget
|
8
|
-
# One line text input box, analog to HTMLInputElement
|
9
|
-
class InputBox < Button
|
10
|
-
include Enterable
|
11
|
-
def initialize(**args)
|
12
|
-
super({height: 1, text: args[:value]||args[:text] }.merge(args))
|
13
|
-
# super
|
14
|
-
@name = 'input'
|
15
|
-
if args[:dynamic_width]
|
16
|
-
on(:input) do |e|
|
17
|
-
update_width(e.value)
|
18
|
-
cursor.x = abs_content_x + e.value.length - 2
|
19
|
-
end
|
20
|
-
end
|
21
|
-
# set_attribute('escape-on-blur', get_attribute('escape-on-blur') == nil ? true : get_attribute('escape-on-blur'))
|
22
|
-
# set_attribute('action-on-focus', get_attribute('action-on-focus') == nil ? true : get_attribute('action-on-focus'))
|
23
|
-
on(:enter) do
|
24
|
-
cursor.enable
|
25
|
-
end
|
26
|
-
on(:escape) do
|
27
|
-
cursor.disable
|
28
|
-
args[:change]&.call(value)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def cursor
|
33
|
-
@cursor ||= Cursor.new(x: abs_content_x + value.length - 2, y: abs_content_y, enabled: false, screen: root_screen)
|
34
|
-
@cursor
|
35
|
-
end
|
36
|
-
|
37
|
-
def value=(value)
|
38
|
-
@text = value
|
39
|
-
end
|
40
|
-
|
41
|
-
def value
|
42
|
-
text
|
43
|
-
end
|
44
|
-
|
45
|
-
def between(v, min, max)
|
46
|
-
[[v, min].max, max].min
|
47
|
-
end
|
48
|
-
|
49
|
-
def current_x
|
50
|
-
cursor.x - abs_content_x
|
51
|
-
end
|
52
|
-
|
53
|
-
def handle_key(event)
|
54
|
-
if !super(event)
|
55
|
-
if event.key == 'backspace'
|
56
|
-
on_input value[0..between(current_x - 1, 0, value.length - 1)] + value[between(current_x + 1, 0, value.length - 1)..(value.length - 1)], event
|
57
|
-
cursor.x = [cursor.x - 1, abs_content_x - 1].max
|
58
|
-
render
|
59
|
-
true
|
60
|
-
elsif alphanumeric? event.key
|
61
|
-
on_input value[0..between(current_x, 0, value.length - 1)] + event.key + value[between(current_x + 1, 0, value.length - 1)..(value.length - 1)], event
|
62
|
-
cursor.x = cursor.x + 1
|
63
|
-
render
|
64
|
-
true
|
65
|
-
elsif ['right'].include? event.key
|
66
|
-
cursor.x = [cursor.x + 1, abs_content_x + value.length - 1].min
|
67
|
-
render
|
68
|
-
true
|
69
|
-
elsif ['left'].include? event.key
|
70
|
-
cursor.x = [cursor.x - 1, abs_content_x - 1].max
|
71
|
-
render
|
72
|
-
true
|
73
|
-
else
|
74
|
-
false
|
75
|
-
end
|
76
|
-
else
|
77
|
-
true
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
InputBox = TermGui::Widget::InputBox
|
85
|
-
|