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/element_style.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
require_relative 'element_bounds'
|
2
|
-
require_relative 'util'
|
3
|
-
|
4
|
-
# adds utilities around style
|
5
|
-
module ElementStyle
|
6
|
-
def style
|
7
|
-
set_attribute('style', ElementStyle.default_style) if get_attribute('style') == nil
|
8
|
-
get_attribute('style')
|
9
|
-
end
|
10
|
-
|
11
|
-
def style=(style)
|
12
|
-
s = style.instance_of?(Hash) ? Style.from_hash(style) : style
|
13
|
-
set_attribute('style', s)
|
14
|
-
self.dirty = true
|
15
|
-
end
|
16
|
-
|
17
|
-
def style_assign(style)
|
18
|
-
self.style = self.style.assign(style)
|
19
|
-
end
|
20
|
-
|
21
|
-
def get_style(name)
|
22
|
-
s = get_attribute('style')
|
23
|
-
s.get(name)
|
24
|
-
end
|
25
|
-
|
26
|
-
def default_style
|
27
|
-
Style.new
|
28
|
-
end
|
29
|
-
|
30
|
-
# while "normal" style is defined in @style, focused extra style is defined in @style.focus,
|
31
|
-
# so dependently on attributes like `focused` this method performs computation of the "final" style
|
32
|
-
def final_style
|
33
|
-
result = parent && get_attribute('style-cascade') != 'prevent' ? parent.final_style.clone .assign(style) : style.clone
|
34
|
-
result.assign(style.focus) if get_attribute('focused')
|
35
|
-
result.assign(style.enter) if get_attribute('entered')
|
36
|
-
result.assign(style.action) if get_attribute('actioned')
|
37
|
-
result
|
38
|
-
end
|
39
|
-
|
40
|
-
# computes current border style according to style, style.border, style.focus.border, etc in the right order
|
41
|
-
def border_style
|
42
|
-
s = final_style
|
43
|
-
if border
|
44
|
-
s = s.assign(border)
|
45
|
-
s.assign(style.focus&.border) if get_attribute('focused')
|
46
|
-
s.assign(style.enter&.border) if get_attribute('entered')
|
47
|
-
s.assign(style.action&.border) if get_attribute('actioned')
|
48
|
-
end
|
49
|
-
s
|
50
|
-
end
|
51
|
-
end
|
data/src/emitter.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
require_relative 'emitter_state'
|
2
|
-
require_relative 'util'
|
3
|
-
|
4
|
-
module TermGui
|
5
|
-
# Basic event emitter, similar to Node's Emitter
|
6
|
-
# adapted from https://medium.com/@kopilov.vlad/use-event-emitter-in-ruby-6b289fe2e7b4
|
7
|
-
class Emitter
|
8
|
-
include EmitterState
|
9
|
-
|
10
|
-
# turn on the event
|
11
|
-
# @param {String, Symbol, (String|Symbol)[]} event_names
|
12
|
-
# @return {nil}
|
13
|
-
def install(event_names)
|
14
|
-
to_array(event_names).each do |event_name|
|
15
|
-
events[event_name.to_sym] ||= []
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
# turn off the event
|
20
|
-
# @param {String, Symbol, (String|Symbol)[]} event_names
|
21
|
-
# @return {nil}
|
22
|
-
def uninstall(event_names)
|
23
|
-
to_array(event_names).each do |event_name|
|
24
|
-
events.delete(event_name.to_sym)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# subscribe to event
|
29
|
-
# @param {String, Symbol, (String|Symbol)[]} event_names
|
30
|
-
# @param handler_proc [Proc]
|
31
|
-
# @return {Proc}
|
32
|
-
def subscribe(event_names, handler_proc = nil, &block)
|
33
|
-
throw 'No block or handler given' if handler_proc == nil && !block_given?
|
34
|
-
handler = handler_proc == nil ? block : handler_proc
|
35
|
-
to_array(event_names).each do |event_name|
|
36
|
-
events[event_name.to_sym]&.push handler
|
37
|
-
end
|
38
|
-
handler
|
39
|
-
end
|
40
|
-
|
41
|
-
alias add_listener subscribe
|
42
|
-
alias on subscribe
|
43
|
-
|
44
|
-
# unsubscribe to event
|
45
|
-
# @param {String, Symbol, (String|Symbol)[]} event_names
|
46
|
-
# @param handler [Proc]
|
47
|
-
# @return {nil}
|
48
|
-
def unsubscribe(event_names, handler)
|
49
|
-
to_array(event_names).each do |event_name|
|
50
|
-
events[event_name.to_sym]&.reject! do |item|
|
51
|
-
item == handler
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
alias remove_listener unsubscribe
|
57
|
-
alias off unsubscribe
|
58
|
-
|
59
|
-
# emit the event
|
60
|
-
# @param {String, Symbol} event_name
|
61
|
-
# @param {Event} event
|
62
|
-
# @return {nil}
|
63
|
-
def emit(event_name, event = Event.new(event_name))
|
64
|
-
events[event_name.to_sym]&.each do |h|
|
65
|
-
h.call(event)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
alias trigger emit
|
70
|
-
|
71
|
-
# get array of existing events
|
72
|
-
# @return [Array<Symbols>]
|
73
|
-
def all_events
|
74
|
-
events.keys
|
75
|
-
end
|
76
|
-
|
77
|
-
# get array of existing events with stat
|
78
|
-
# @return [Array<Symbols, Fixnum>]
|
79
|
-
def all_events_with_stat
|
80
|
-
events
|
81
|
-
.map { |name, arr| [name, arr.size] }
|
82
|
-
.flatten
|
83
|
-
end
|
84
|
-
|
85
|
-
def once(event_name, handler_proc = nil, &block)
|
86
|
-
throw 'No block or handler given' if handler_proc == nil && !block_given?
|
87
|
-
handler = handler_proc == nil ? block : handler_proc
|
88
|
-
listener = on(event_name) do |event|
|
89
|
-
handler.call(event)
|
90
|
-
off(event_name, listener)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
def events
|
97
|
-
@events ||= {}
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
Emitter = TermGui::Emitter
|
data/src/emitter_state.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# adds save/restore event listeners state to Emitter
|
2
|
-
module EmitterState
|
3
|
-
# saves current emitter listeners state under given name
|
4
|
-
def emitter_save(name)
|
5
|
-
@emitter_state ||= {}
|
6
|
-
@emitter_state[name.to_sym] = @events
|
7
|
-
end
|
8
|
-
|
9
|
-
# loads a previously saved emitter state with given name.
|
10
|
-
# After this call this emitter will notify a different set of listeners
|
11
|
-
def emitter_load(name)
|
12
|
-
@emitter_state ||= {}
|
13
|
-
@events = @emitter_state[name.to_sym] || @events
|
14
|
-
end
|
15
|
-
|
16
|
-
def emitter_reset
|
17
|
-
@events = {}
|
18
|
-
end
|
19
|
-
end
|
data/src/enterable.rb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
require_relative 'event'
|
2
|
-
|
3
|
-
module TermGui
|
4
|
-
class InputEvent < NodeEvent
|
5
|
-
attr_accessor :value
|
6
|
-
def initialize(target, value = target.value, original_event = nil)
|
7
|
-
super 'input', target, original_event
|
8
|
-
@value = value
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class ChangeEvent < NodeEvent
|
13
|
-
attr_accessor :value
|
14
|
-
def initialize(target, value = target.value, original_event = nil)
|
15
|
-
super 'change', target, original_event
|
16
|
-
@value = value
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class EscapeEvent < NodeEvent
|
21
|
-
def initialize(target, original_event = nil)
|
22
|
-
super 'escape', target, original_event
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class EnterEvent < NodeEvent
|
27
|
-
def initialize(target, original_event = nil)
|
28
|
-
super 'enter', target, original_event
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
module Enterable
|
33
|
-
def initialize(**args)
|
34
|
-
super
|
35
|
-
self.value = args[:value] || ''
|
36
|
-
@key_listener = nil
|
37
|
-
set_attribute(:focusable, true)
|
38
|
-
set_attribute(:enterable, true)
|
39
|
-
set_attribute(:actionable, true)
|
40
|
-
install(%i[input action enter change escape focus blur])
|
41
|
-
on(:action) do |event|
|
42
|
-
return unless root_screen && get_attribute('entered')
|
43
|
-
set_attribute('entered', true)
|
44
|
-
@key_listener = proc { |e| handle_key e }
|
45
|
-
root_screen.event.add_any_key_listener @key_listener
|
46
|
-
on('change', args[:change]) if args[:change]
|
47
|
-
on('input', args[:input]) if args[:input]
|
48
|
-
on('escape', args[:escape]) if args[:escape]
|
49
|
-
trigger('enter', EnterEvent.new(self, event))
|
50
|
-
end
|
51
|
-
on(%i[blur escape change]) do
|
52
|
-
return unless root_screen
|
53
|
-
set_attribute('entered', false)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def handle_key(event)
|
58
|
-
return unless root_screen
|
59
|
-
if !get_attribute('focused')
|
60
|
-
trigger('change', ChangeEvent.new(self, value, event))
|
61
|
-
root_screen.event.remove_any_key_listener @key_listener
|
62
|
-
true
|
63
|
-
elsif to_array(get_attribute('escape-keys') || 'escape').include? event.key
|
64
|
-
trigger('escape', EscapeEvent.new(self, event))
|
65
|
-
root_screen.event.remove_any_key_listener @key_listener
|
66
|
-
true
|
67
|
-
else
|
68
|
-
false
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def value=(_value)
|
73
|
-
throw 'subclass must implementation'
|
74
|
-
end
|
75
|
-
|
76
|
-
def value
|
77
|
-
throw 'subclass must implementation'
|
78
|
-
end
|
79
|
-
|
80
|
-
protected
|
81
|
-
|
82
|
-
def on_input(value, event = nil)
|
83
|
-
return unless root_screen
|
84
|
-
self.value = value
|
85
|
-
trigger('input', InputEvent.new(self, value, event))
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
Enterable = TermGui::Enterable
|
91
|
-
InputEvent = TermGui::InputEvent
|
92
|
-
ChangeEvent = TermGui::ChangeEvent
|
93
|
-
EscapeEvent = TermGui::EscapeEvent
|
data/src/event.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
require_relative 'input'
|
2
|
-
require_relative 'util'
|
3
|
-
|
4
|
-
module TermGui
|
5
|
-
# # Base event class. Independent of Element.
|
6
|
-
# class Event
|
7
|
-
# attr_reader :name
|
8
|
-
|
9
|
-
# def initialize(name)
|
10
|
-
# @name = name
|
11
|
-
# end
|
12
|
-
# end
|
13
|
-
|
14
|
-
# Event related with a Node (`target`) and a native event (`original_event`).
|
15
|
-
class NodeEvent < Event
|
16
|
-
attr_reader :target, :original_event
|
17
|
-
|
18
|
-
def initialize(name, target, original_event = nil)
|
19
|
-
super name
|
20
|
-
@target = target
|
21
|
-
@original_event = original_event
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# Represents a keyboard event. Independent of Element.
|
26
|
-
class KeyEvent < Event
|
27
|
-
attr_reader :key, :raw
|
28
|
-
|
29
|
-
def initialize(key, raw = name_to_char(key))
|
30
|
-
super 'key'
|
31
|
-
@key = key
|
32
|
-
@raw = raw
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_s
|
36
|
-
"KeyEvent#{{ name: @name, key: @key, raw: @raw }}"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# responsible of observe/emit user input events (KeyEvent)
|
41
|
-
class EventManager
|
42
|
-
def initialize(input = Input.new)
|
43
|
-
@key_listeners = {}
|
44
|
-
@any_key_listener = []
|
45
|
-
input.add_listener('key') { |e| handle_key e }
|
46
|
-
end
|
47
|
-
|
48
|
-
def add_key_listener(keys, listener = nil, &block)
|
49
|
-
the_listener = listener == nil ? block : listener
|
50
|
-
throw 'No listener provided' if the_listener == nil
|
51
|
-
keys = (keys.is_a? String) ? [keys] : keys
|
52
|
-
keys.each do |key|
|
53
|
-
@key_listeners[key] = @key_listeners[key] || []
|
54
|
-
@key_listeners[key].push the_listener
|
55
|
-
end
|
56
|
-
the_listener
|
57
|
-
end
|
58
|
-
|
59
|
-
def remove_key_listener(key, listener)
|
60
|
-
@key_listeners[key] = @key_listeners[key] || []
|
61
|
-
@key_listeners[key].delete listener
|
62
|
-
end
|
63
|
-
|
64
|
-
def add_any_key_listener(listener = nil, &block)
|
65
|
-
the_listener = listener == nil ? block : listener
|
66
|
-
throw 'No listener provided' if the_listener == nil
|
67
|
-
@any_key_listener.push the_listener
|
68
|
-
the_listener
|
69
|
-
end
|
70
|
-
|
71
|
-
def remove_any_key_listener(listener)
|
72
|
-
@any_key_listener.delete listener
|
73
|
-
end
|
74
|
-
|
75
|
-
# can be used to programmatically simulate keypressed (useful for tests)
|
76
|
-
def handle_key(e)
|
77
|
-
key = e.key
|
78
|
-
@key_listeners[key] = @key_listeners[key] || []
|
79
|
-
@key_listeners[key].each do |listener|
|
80
|
-
listener.call(e)
|
81
|
-
end
|
82
|
-
@any_key_listener.each do |listener|
|
83
|
-
listener.call(e)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
Event = TermGui::Event
|
90
|
-
NodeEvent = TermGui::NodeEvent
|
91
|
-
KeyEvent = TermGui::KeyEvent
|
92
|
-
EventManager = TermGui::EventManager
|
data/src/focus.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
require_relative 'emitter'
|
2
|
-
require_relative 'element'
|
3
|
-
require_relative 'log'
|
4
|
-
require_relative 'event'
|
5
|
-
|
6
|
-
module TermGui
|
7
|
-
# provides support for focused, focusable attributes management and emit focus-related events
|
8
|
-
# TODO: make events extend NodeEvent
|
9
|
-
class FocusManager < Emitter
|
10
|
-
attr_reader :keys, :focused
|
11
|
-
|
12
|
-
def initialize(
|
13
|
-
root: nil, # the root element inside of which to look up for focusables
|
14
|
-
event: nil, # EventManager instance - needed for subscribe to key events
|
15
|
-
keys: { next: ['tab'], prev: ['S-tab'] }, # the keys for focusing the next and previous focusable
|
16
|
-
focus_first: true # if true will set focus (attribute focused == true) on the first focusable automatically
|
17
|
-
)
|
18
|
-
throw 'root Element and Event EventManager are required' unless root && event
|
19
|
-
install(:focus)
|
20
|
-
@root = root
|
21
|
-
@keys = keys
|
22
|
-
@event = event
|
23
|
-
@focus_first = focus_first
|
24
|
-
init
|
25
|
-
@event.add_any_key_listener { |e| handle_key e }
|
26
|
-
@root.on(:after_start) do
|
27
|
-
init
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def init
|
32
|
-
focusables.each { |n| n.set_attribute(:focused, false) }
|
33
|
-
if @focus_first
|
34
|
-
self.focused = focusables.first
|
35
|
-
@focused&.render if @focused6.is_a? Element
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def focusables
|
40
|
-
@root.query_by_attribute(:focusable, true)
|
41
|
-
end
|
42
|
-
|
43
|
-
# focus next focusable node
|
44
|
-
def focus_next
|
45
|
-
i = focusables.index(@focused) || 0
|
46
|
-
new_i = i == focusables.length - 1 ? 0 : i + 1
|
47
|
-
self.focused = focusables[new_i] if focusables[new_i]
|
48
|
-
end
|
49
|
-
|
50
|
-
# focus previous focusable node
|
51
|
-
def focus_prev
|
52
|
-
i = focusables.index(@focused) || 0
|
53
|
-
new_i = i.zero? ? focusables.length - 1 : i - 1
|
54
|
-
self.focused = focusables[new_i] if focusables[new_i]
|
55
|
-
end
|
56
|
-
|
57
|
-
def focused=(focused)
|
58
|
-
previous = @focused
|
59
|
-
@focused&.set_attribute(:focused, false)
|
60
|
-
@focused = focused
|
61
|
-
@focused&.set_attribute(:focused, true)
|
62
|
-
emit :focus, focused: @focused, previous: previous
|
63
|
-
previous&.emit :blur, BlurEvent.new(previous, @focused)
|
64
|
-
focus_event = FocusEvent.new(@focused, previous)
|
65
|
-
@focused&.emit :focus, focus_event
|
66
|
-
if @focused&.get_attribute('action-on-focus')
|
67
|
-
event = ActionEvent.new @focused, focus_event
|
68
|
-
@focused.get_attribute('action')&.call(event)
|
69
|
-
@focused.trigger event.name, event
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
protected
|
74
|
-
|
75
|
-
def handle_key(e)
|
76
|
-
return if @focused&.get_attribute('entered') && !@focused&.get_attribute('escape-on-blur')
|
77
|
-
if @keys[:next].include? e.key
|
78
|
-
focus_next
|
79
|
-
elsif @keys[:prev].include? e.key
|
80
|
-
focus_prev
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
class BlurEvent < NodeEvent
|
86
|
-
attr_accessor :focused
|
87
|
-
def initialize(target, focused, original_event = nil)
|
88
|
-
super 'blur', target, original_event
|
89
|
-
@focused = focused
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
class FocusEvent < NodeEvent
|
94
|
-
attr_accessor :previous
|
95
|
-
def initialize(target, previous, original_event = nil)
|
96
|
-
super 'focus', target, original_event
|
97
|
-
@previous = previous
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
FocusManager = TermGui::FocusManager
|