ncumbra 0.1.1 → 0.1.2
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/CHANGELOG +6 -0
- data/README.md +712 -6
- data/examples/ex1.rb +2 -3
- data/examples/ex3.rb +2 -3
- data/examples/ex4.rb +1 -2
- data/examples/ex5.rb +4 -3
- data/examples/exbox.rb +1 -1
- data/examples/extab3.rb +1 -2
- data/lib/umbra.rb +2 -0
- data/lib/umbra/box.rb +23 -9
- data/lib/umbra/button.rb +13 -14
- data/lib/umbra/checkbox.rb +3 -3
- data/lib/umbra/eventhandler.rb +2 -3
- data/lib/umbra/field.rb +23 -12
- data/lib/umbra/form.rb +19 -109
- data/lib/umbra/listbox.rb +26 -20
- data/lib/umbra/menu.rb +2 -2
- data/lib/umbra/messagebox.rb +2 -2
- data/lib/umbra/multiline.rb +95 -32
- data/lib/umbra/pad.rb +5 -3
- data/lib/umbra/radiobutton.rb +2 -2
- data/lib/umbra/tabular.rb +5 -2
- data/lib/umbra/textbox.rb +14 -153
- data/lib/umbra/togglebutton.rb +75 -112
- data/lib/umbra/version.rb +1 -1
- data/lib/umbra/widget.rb +9 -14
- data/lib/umbra/window.rb +8 -2
- data/tut/field.rb +72 -0
- data/tut/hello.rb +17 -0
- data/tut/label_hello.rb +28 -0
- data/tut/labfield.rb +63 -0
- metadata +6 -2
data/examples/ex1.rb
CHANGED
@@ -70,18 +70,17 @@ begin
|
|
70
70
|
when FFI::NCurses::KEY_UP
|
71
71
|
when FFI::NCurses::KEY_DOWN
|
72
72
|
end
|
73
|
-
#FIXME after scrolling, pointer is showing wrong file here
|
74
73
|
statusline(win, "Pressed #{ch} on ", 70)
|
75
74
|
win.wrefresh
|
76
75
|
end
|
77
76
|
|
78
77
|
rescue Object => e
|
79
|
-
|
78
|
+
win.destroy if win
|
80
79
|
FFI::NCurses.endwin
|
81
80
|
puts e
|
82
81
|
puts e.backtrace.join("\n")
|
83
82
|
ensure
|
84
|
-
|
83
|
+
win.destroy if win
|
85
84
|
FFI::NCurses.endwin
|
86
85
|
puts
|
87
86
|
end
|
data/examples/ex3.rb
CHANGED
@@ -84,18 +84,17 @@ begin
|
|
84
84
|
message_label.text = "UNToggle button was pressed"
|
85
85
|
end
|
86
86
|
# we need this since we have done away with dsl_property
|
87
|
-
message_label.repaint_required = true
|
87
|
+
#message_label.repaint_required = true
|
88
88
|
end
|
89
89
|
form.add_widget togglebutton
|
90
90
|
|
91
|
-
check =
|
91
|
+
check = Checkbox.new text: "No Frames", value: true, row: row+1, col: col, mnemonic: "N"
|
92
92
|
check1 = Checkbox.new text: "Use https", value: false, row: row+2, col: col, mnemonic: "U"
|
93
93
|
row += 2
|
94
94
|
form.add_widget check, check1
|
95
95
|
[ check, check1 ].each do |cb|
|
96
96
|
cb.command do
|
97
97
|
message_label.text = "#{cb.text} is now #{cb.value}"
|
98
|
-
message_label.repaint_required = true
|
99
98
|
end
|
100
99
|
end
|
101
100
|
|
data/examples/ex4.rb
CHANGED
@@ -66,7 +66,6 @@ begin
|
|
66
66
|
#lb.border false
|
67
67
|
box.title = "Untoggled"
|
68
68
|
end
|
69
|
-
box.repaint_required = true
|
70
69
|
end
|
71
70
|
# bind the most common event for a listbox which is ENTER_ROW
|
72
71
|
lb.command do |ix|
|
@@ -105,7 +104,7 @@ begin
|
|
105
104
|
end
|
106
105
|
# bind to another event of listbox
|
107
106
|
lb.bind_event(:LEAVE_ROW) { |ix| statusline(win, "LEFT ROW #{ix.first}", 50) }
|
108
|
-
lb.bind_event(:
|
107
|
+
lb.bind_event(:SELECT_ROW) { |w| alert("You selected row #{w.selected_index || "none"} ") }
|
109
108
|
form.add_widget box, lb
|
110
109
|
form.add_widget tb
|
111
110
|
form.add_widget ab
|
data/examples/ex5.rb
CHANGED
@@ -62,10 +62,11 @@ begin
|
|
62
62
|
else
|
63
63
|
box.justify = :left
|
64
64
|
end
|
65
|
-
box.repaint_required = true
|
65
|
+
#box.repaint_required = true
|
66
66
|
end
|
67
|
-
lb.bind_event(:CURSOR_MOVE) {|arr|
|
68
|
-
|
67
|
+
#lb.bind_event(:CURSOR_MOVE) {|arr|
|
68
|
+
lb.bind_event(:CURSOR_MOVE) {|lb|
|
69
|
+
col_offset , current_index, curpos, pcol = lb.col_offset, lb.current_index, lb.curpos, lb.panned_cols
|
69
70
|
blen = lb.current_row().size
|
70
71
|
statusline(win, "offset: #{col_offset} , curpos: #{curpos} , currind: #{current_index} , pcol #{pcol}, len:#{blen}.....", 20)
|
71
72
|
}
|
data/examples/exbox.rb
CHANGED
@@ -104,7 +104,7 @@ begin
|
|
104
104
|
end
|
105
105
|
# bind to another event of listbox
|
106
106
|
lb.bind_event(:LEAVE_ROW) { |ix| statusline(win, "LEFT ROW #{ix.first}", 50) }
|
107
|
-
lb.bind_event(:
|
107
|
+
lb.bind_event(:SELECT_ROW) { |w| alert("You selected row #{w.selected_index || "none"} ") }
|
108
108
|
form.add_widget lb, lb2
|
109
109
|
form.add_widget tb
|
110
110
|
form.add_widget ab
|
data/examples/extab3.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
# Author: j kepler http://github.com/mare-imbrium/umbra/
|
6
6
|
# Date: 2018-05-11
|
7
7
|
# License: MIT
|
8
|
-
# Last update: 2018-
|
8
|
+
# Last update: 2018-06-01 12:26
|
9
9
|
# ----------------------------------------------------------------------------- #
|
10
10
|
# extab3.rb Copyright (C) 2018 j kepler
|
11
11
|
require 'umbra'
|
@@ -127,7 +127,6 @@ def _filter_table(lb, columns, fields)
|
|
127
127
|
$log.debug " ibv: #{bind_vars.join ', '} "
|
128
128
|
alist = @db.execute( sql, bind_vars)
|
129
129
|
if alist #and !alist.empty?
|
130
|
-
#lb.list = alist ## results in error, FIXME
|
131
130
|
lb.data = alist
|
132
131
|
else
|
133
132
|
#alert "No rows returned. Check your query"
|
data/lib/umbra.rb
CHANGED
@@ -65,6 +65,7 @@ module Umbra
|
|
65
65
|
end
|
66
66
|
|
67
67
|
## create a logger instance given a path, return the logger
|
68
|
+
## NOTE: Ideally would like to set $log here to this, but what if user creates multiple.
|
68
69
|
def create_logger path, config={}
|
69
70
|
require 'logger'
|
70
71
|
_path = File.open(path, File::WRONLY|File::TRUNC|File::CREAT)
|
@@ -86,6 +87,7 @@ module Umbra
|
|
86
87
|
while true
|
87
88
|
catch :close do
|
88
89
|
while( ch = win.getkey) != 999
|
90
|
+
next if ch == -1 ## should we put this here ???
|
89
91
|
begin
|
90
92
|
if ch == curses::KEY_CTRL_Q
|
91
93
|
stopping = true
|
data/lib/umbra/box.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Author: j kepler http://github.com/mare-imbrium/canis/
|
5
5
|
# Date: 2018-04-07
|
6
6
|
# License: MIT
|
7
|
-
# Last update: 2018-05-
|
7
|
+
# Last update: 2018-05-27 16:14
|
8
8
|
# ----------------------------------------------------------------------------- #
|
9
9
|
# box.rb Copyright (C) 2018 j kepler
|
10
10
|
module Umbra
|
@@ -33,7 +33,7 @@ module Umbra
|
|
33
33
|
#@int_width = @width - 2
|
34
34
|
@int_width = self.width - 2
|
35
35
|
@hlines = []
|
36
|
-
|
36
|
+
#@vlines = [] # UNUSED. TODO ???
|
37
37
|
end
|
38
38
|
def repaint
|
39
39
|
return unless @visible
|
@@ -44,9 +44,10 @@ module Umbra
|
|
44
44
|
end
|
45
45
|
# what about asking for painting of widgets
|
46
46
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
|
48
|
+
##
|
49
|
+
## Add a variable list of components to a box, which are stacked horizontally by the box.
|
50
|
+
## @param comma separated list of widgets
|
50
51
|
def add *w
|
51
52
|
@widgets = w
|
52
53
|
num = w.size
|
@@ -65,8 +66,14 @@ module Umbra
|
|
65
66
|
# FIXME there will be one additional hline in the end.
|
66
67
|
w[-1].height -= (num-1)
|
67
68
|
end
|
68
|
-
|
69
|
-
|
69
|
+
alias :stack :add
|
70
|
+
|
71
|
+
|
72
|
+
##
|
73
|
+
## Horizontally place an array of widgets
|
74
|
+
## @param comma separated list of widgets
|
75
|
+
## NOTE: this is best used for widgets that can be resized.
|
76
|
+
# Prefer not to use for buttons since the looks gets messed (inconsistency between button and highlight).
|
70
77
|
# Therefore now, button calculates its own width which means that this program cannot determine what the width is
|
71
78
|
# and thus cannot center it.
|
72
79
|
def flow *w
|
@@ -90,7 +97,11 @@ module Umbra
|
|
90
97
|
# we added 1 to the scol each time, so decrement
|
91
98
|
w[-1].width -= (num-1)
|
92
99
|
end
|
93
|
-
|
100
|
+
|
101
|
+
|
102
|
+
## Fill out a single widget into the entire box leaving an inset of 1.
|
103
|
+
## @param [Widget]
|
104
|
+
# NOTE: use if only one widget will expand into this box
|
94
105
|
def fill w
|
95
106
|
# should have been nice if I could add widget to form, but then order might get wrong
|
96
107
|
w.row = self.row + 1
|
@@ -111,6 +122,10 @@ module Umbra
|
|
111
122
|
end
|
112
123
|
@widget = w
|
113
124
|
end
|
125
|
+
|
126
|
+
## paint a horizontal line, as a separator between widgets
|
127
|
+
## param [Integer] row - row
|
128
|
+
## param [Integer] col - column
|
114
129
|
def hline row, col
|
115
130
|
return if row >= self.row + self.height
|
116
131
|
$log.debug " hline: #{row} ... #{@row} #{@height} "
|
@@ -118,7 +133,6 @@ module Umbra
|
|
118
133
|
end
|
119
134
|
|
120
135
|
# print a title over the box on zeroth row
|
121
|
-
# TODO right or left or center align
|
122
136
|
private def print_title stitle
|
123
137
|
return unless stitle
|
124
138
|
stitle = "| #{stitle} |"
|
data/lib/umbra/button.rb
CHANGED
@@ -5,39 +5,43 @@
|
|
5
5
|
# Author: j kepler http://github.com/mare-imbrium/canis/
|
6
6
|
# Date: 2018-03-16
|
7
7
|
# License: MIT
|
8
|
-
# Last update: 2018-
|
8
|
+
# Last update: 2018-06-01 12:37
|
9
9
|
# ----------------------------------------------------------------------------- #
|
10
10
|
# button.rb Copyright (C) 2012-2018 j kepler
|
11
|
-
# ==
|
11
|
+
# == Todo
|
12
12
|
# - mnemonics with highlighting
|
13
13
|
# - default button
|
14
14
|
require 'umbra/widget'
|
15
15
|
# ----------------
|
16
16
|
module Umbra
|
17
|
+
|
18
|
+
|
17
19
|
class Button < Widget
|
18
20
|
attr_accessor :surround_chars # characters to use to surround the button, def is square brackets
|
21
|
+
|
19
22
|
# char to be underlined, and bound to Alt-char
|
20
23
|
attr_accessor :mnemonic
|
24
|
+
|
25
|
+
|
21
26
|
def initialize config={}, &block
|
22
27
|
@focusable = true
|
23
28
|
@editable = false
|
24
29
|
@highlight_attr = REVERSE
|
25
|
-
|
26
|
-
#@hotkey = config.delete(:hotkey) 2018-03-22 -
|
27
|
-
# 2018-03-18 - FORM_ATTACHED deprecated to keep things simple
|
30
|
+
|
28
31
|
register_events([:PRESS])
|
29
|
-
@default_chars = ['> ', ' <'] # a default button is painted differently
|
32
|
+
@default_chars = ['> ', ' <'] # a default button is painted differently. UNUSED. ???
|
30
33
|
super
|
31
34
|
|
32
|
-
|
33
35
|
@surround_chars ||= ['[ ', ' ]']
|
34
36
|
@col_offset = @surround_chars[0].length
|
35
37
|
@text_offset = 0 # used to determine where underline should fall TODO ???
|
36
38
|
map_keys
|
37
39
|
end
|
40
|
+
|
41
|
+
|
38
42
|
##
|
39
43
|
# set button based on Action
|
40
|
-
# 2018-03-22 - is this still used ?
|
44
|
+
# 2018-03-22 - is this still used ? XXX
|
41
45
|
# This allows action objects to be used in multiple places such as buttons, menus, popups etc.
|
42
46
|
def action a
|
43
47
|
text a.name
|
@@ -91,16 +95,11 @@ module Umbra
|
|
91
95
|
@repaint_required = false
|
92
96
|
end
|
93
97
|
|
94
|
-
## command of button (invoked on press, hotkey, space)
|
95
|
-
# added args 2008-12-20 19:22
|
96
|
-
def command *args, &block
|
97
|
-
bind_event :PRESS, *args, &block
|
98
|
-
end
|
99
98
|
## fires PRESS event of button
|
100
99
|
def fire
|
101
|
-
#$log.debug "firing PRESS #{text}"
|
102
100
|
fire_handler :PRESS, ActionEvent.new(self, :PRESS, text)
|
103
101
|
end
|
102
|
+
|
104
103
|
# for campatibility with all buttons, will apply to radio buttons mostly
|
105
104
|
def selected?; false; end
|
106
105
|
|
data/lib/umbra/checkbox.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Author: j kepler http://github.com/mare-imbrium/canis/
|
5
5
|
# Date: 2018-04-01 - 16:08
|
6
6
|
# License: MIT
|
7
|
-
# Last update: 2018-05-
|
7
|
+
# Last update: 2018-05-28 12:06
|
8
8
|
# ----------------------------------------------------------------------------- #
|
9
9
|
# checkbox.rb Copyright (C) 2012-2018 j kepler
|
10
10
|
module Umbra
|
@@ -12,8 +12,8 @@ module Umbra
|
|
12
12
|
# A checkbox, may be selected or unselected
|
13
13
|
#
|
14
14
|
class Checkbox < ToggleButton
|
15
|
-
attr_property :align_right # the button will be on the right
|
16
|
-
|
15
|
+
attr_property :align_right # the button will be on the right of the text
|
16
|
+
|
17
17
|
def initialize config={}, &block
|
18
18
|
@surround_chars = ['[', ']'] # 2008-12-23 23:16 added space in Button so overriding
|
19
19
|
super
|
data/lib/umbra/eventhandler.rb
CHANGED
@@ -73,11 +73,10 @@ module Umbra
|
|
73
73
|
raise pve
|
74
74
|
rescue => ex
|
75
75
|
## some don't have name
|
76
|
-
# FIXME this should be displayed somewhere. It just goes into log file quietly.
|
77
76
|
$log.error "======= Error ERROR in block event #{self}: #{event}"
|
78
77
|
$log.error ex
|
79
78
|
$log.error(ex.backtrace.join("\n"))
|
80
|
-
alert ex.to_s
|
79
|
+
alert ex.to_s
|
81
80
|
FFI::NCurses.beep # doesn't do anything, maybe switched off in preferences
|
82
81
|
end
|
83
82
|
end
|
@@ -112,8 +111,8 @@ module Umbra
|
|
112
111
|
else
|
113
112
|
@pce.set( self, text, oldvalue, newvalue)
|
114
113
|
end
|
115
|
-
fire_handler :PROPERTY_CHANGE, @pce
|
116
114
|
@repaint_required = true
|
115
|
+
fire_handler :PROPERTY_CHANGE, @pce
|
117
116
|
end
|
118
117
|
|
119
118
|
## Created and sent to all listeners whenever a property is changed
|
data/lib/umbra/field.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Author: j kepler http://github.com/mare-imbrium/canis/
|
5
5
|
# Date: 2018-03
|
6
6
|
# License: MIT
|
7
|
-
# Last update: 2018-05-
|
7
|
+
# Last update: 2018-05-26 11:21
|
8
8
|
# ----------------------------------------------------------------------------- #
|
9
9
|
# field.rb Copyright (C) 2012-2018 j kepler
|
10
10
|
#
|
@@ -37,7 +37,7 @@ class InputDataEvent # {{{
|
|
37
37
|
end
|
38
38
|
end # }}}
|
39
39
|
# Text edit field
|
40
|
-
#
|
40
|
+
# Todo :
|
41
41
|
# NOTE: +width+ is the length of the display whereas +maxlen+ is the maximum size that the value
|
42
42
|
# can take. Thus, +maxlen+ can exceed +width+. Currently, +maxlen+ defaults to +width+ which
|
43
43
|
# defaults to 20.
|
@@ -45,7 +45,11 @@ end # }}}
|
|
45
45
|
# == Example
|
46
46
|
# f = Field.new text: "Some value", row: 10, col: 2
|
47
47
|
#
|
48
|
-
|
48
|
+
# Field introduces an event :CHANGE which is fired for each character deleted or inserted.
|
49
|
+
##
|
50
|
+
# ## Use the :CHANGED event handler for custom validations and throw a +FieldValidationException+ if
|
51
|
+
# ## the validation fails. This is called in the +on_leave+. You may pass a block to the +command+ method
|
52
|
+
## for the same functionality.
|
49
53
|
#
|
50
54
|
module Umbra
|
51
55
|
class Field < Widget
|
@@ -82,10 +86,10 @@ end # }}}
|
|
82
86
|
attr_accessor :overwrite_mode # true or false INSERT OVERWRITE MODE
|
83
87
|
|
84
88
|
# column on which field printed, usually the same as +col+ unless +label+ used.
|
85
|
-
# Required by +History+ to popup field history.
|
89
|
+
# Required by +History+ to popup field history. UNUSED.
|
86
90
|
attr_reader :field_col # column on which field is printed
|
87
91
|
# required due to labels. Is updated after printing
|
88
|
-
# # so can be nil if accessed early
|
92
|
+
# # so can be nil if accessed early
|
89
93
|
|
90
94
|
def initialize config={}, &block
|
91
95
|
@buffer = String.new
|
@@ -262,15 +266,12 @@ end # }}}
|
|
262
266
|
|
263
267
|
|
264
268
|
public
|
265
|
-
## Note that some older widgets like Field repaint every time the form.repaint
|
266
|
-
##+ is called, whether updated or not. I can't remember why this is, but
|
267
|
-
##+ currently I've not implemented events with these widgets. 2010-01-03 15:00
|
268
269
|
|
269
270
|
def repaint
|
270
|
-
return unless @repaint_required
|
271
|
+
return unless @repaint_required
|
271
272
|
$log.debug("repaint FIELD: #{name}, r:#{row} c:#{col},wid:#{width},maxlen: #{@maxlen},pcol:#{@pcol}, #{focusable} st: #{@state} ")
|
272
273
|
@width = 1 if width == 0
|
273
|
-
printval = getvalue_for_paint().to_s
|
274
|
+
printval = getvalue_for_paint().to_s
|
274
275
|
printval = mask()*printval.length unless @mask.nil?
|
275
276
|
if !printval.nil?
|
276
277
|
if printval.length > width # only show maxlen
|
@@ -329,8 +330,10 @@ end # }}}
|
|
329
330
|
return if @delete_buffer.nil?
|
330
331
|
#oldvalue = @buffer
|
331
332
|
@buffer.insert @curpos, @delete_buffer
|
332
|
-
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :INSERT, 0, @delete_buffer)
|
333
|
+
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :INSERT, 0, @delete_buffer)
|
333
334
|
end
|
335
|
+
|
336
|
+
|
334
337
|
##
|
335
338
|
# position cursor at start of field
|
336
339
|
def cursor_home
|
@@ -435,7 +438,7 @@ end # }}}
|
|
435
438
|
addcol -1 if adjust # move visual cursor back
|
436
439
|
@modified = true
|
437
440
|
end
|
438
|
-
#
|
441
|
+
# Upon leaving a field
|
439
442
|
# returns false if value not valid as per values or valid_regex
|
440
443
|
# 2008-12-22 12:40 if null_allowed, don't validate, but do fire_handlers
|
441
444
|
def on_leave
|
@@ -457,8 +460,13 @@ end # }}}
|
|
457
460
|
if !in_range?(val)
|
458
461
|
raise FieldValidationException, "Field not matching range #{@valid_range}, above #{@above} or below #{@below} "
|
459
462
|
end
|
463
|
+
|
464
|
+
## 2018-05-24 - seems we were not calling the :CHANGED listeners at all.
|
465
|
+
fire_handler :CHANGED, self
|
466
|
+
|
460
467
|
end
|
461
468
|
# here is where we should set the forms modified to true - 2009-01
|
469
|
+
## 2018-05-26 - what is the point of this ?
|
462
470
|
if modified?
|
463
471
|
@modified = true
|
464
472
|
end
|
@@ -488,6 +496,7 @@ end # }}}
|
|
488
496
|
end
|
489
497
|
##
|
490
498
|
# overriding widget, check for value change
|
499
|
+
# 2018-05-26 - WHAT IS THE POINT of setting @modified if we have a different logic here
|
491
500
|
def modified?
|
492
501
|
getvalue() != @original_value
|
493
502
|
end
|
@@ -495,6 +504,8 @@ end # }}}
|
|
495
504
|
def text
|
496
505
|
getvalue
|
497
506
|
end
|
507
|
+
|
508
|
+
## set default value of field
|
498
509
|
def text=(val)
|
499
510
|
return unless val # added 2010-11-17 20:11, dup will fail on nil
|
500
511
|
# will bomb on integer or float etc !!
|
data/lib/umbra/form.rb
CHANGED
@@ -41,6 +41,7 @@ class Form
|
|
41
41
|
@active_index = nil
|
42
42
|
@row = @col = 0 # 2018-03-07 - umbra
|
43
43
|
@focusables = [] # focusable components
|
44
|
+
register_events(:RESIZE)
|
44
45
|
instance_eval &block if block_given?
|
45
46
|
@name ||= "" # for debugging
|
46
47
|
|
@@ -48,6 +49,8 @@ class Form
|
|
48
49
|
#$error_message ||= Variable.new ""
|
49
50
|
|
50
51
|
map_keys unless @keys_mapped
|
52
|
+
$log ||= create_logger '/dev/null' ## FIXME temporarily adding here. If user has not
|
53
|
+
## specified a logger, create a quiet one.
|
51
54
|
end
|
52
55
|
##
|
53
56
|
# Add given widget to widget list and returns self
|
@@ -59,6 +62,7 @@ class Form
|
|
59
62
|
next if @widgets.include? w
|
60
63
|
# NOTE: if form created with nil window (messagebox), then this would have to happen later
|
61
64
|
w.graphic = @window if @window # 2018-03-19 - prevent widget from needing to call form back
|
65
|
+
$log.warn "Window is nil in form.add_widget" unless @window
|
62
66
|
w._form = self # 2018-04-20 - so that update_focusables can be called.
|
63
67
|
@widgets << w
|
64
68
|
end
|
@@ -72,12 +76,15 @@ class Form
|
|
72
76
|
@widgets.delete widget
|
73
77
|
@focusables.delete widget
|
74
78
|
end
|
79
|
+
|
80
|
+
|
75
81
|
# maintain a list of focusable objects so form can traverse between them easily.
|
76
82
|
def update_focusables
|
77
83
|
#$log.debug "1 inside update_focusables #{@focusables.count} "
|
78
84
|
@focusables = @widgets.select { |w| w.focusable }
|
79
85
|
#$log.debug "2 inside update_focusables #{@focusables.count} "
|
80
86
|
end
|
87
|
+
|
81
88
|
# Decide layout of objects. User has to call this after creating components
|
82
89
|
# More may come here.
|
83
90
|
def pack
|
@@ -117,7 +124,7 @@ class Form
|
|
117
124
|
## This ensures that whenever a widget is given focus, the on_leave of the previous widget
|
118
125
|
## is called, and the on_enter of this field is called.
|
119
126
|
## 2018-05-18 - rewrite of select_field which did not call on_leave
|
120
|
-
def
|
127
|
+
def select_widget fld
|
121
128
|
|
122
129
|
return nil unless fld ## no focusable
|
123
130
|
|
@@ -147,7 +154,7 @@ class Form
|
|
147
154
|
repaint # 2018-03-21 - handle_key calls repaint, is this for cases not involving keypress ?
|
148
155
|
@window.refresh
|
149
156
|
end
|
150
|
-
alias :select_field :
|
157
|
+
alias :select_field :select_widget
|
151
158
|
|
152
159
|
|
153
160
|
# form repaint,calls repaint on each widget which will repaint it only if it has been modified since last call.
|
@@ -175,29 +182,26 @@ class Form
|
|
175
182
|
end
|
176
183
|
@window.wrefresh
|
177
184
|
end
|
185
|
+
|
186
|
+
|
187
|
+
|
178
188
|
# @return [Widget, nil] current field, nil if no focusable field
|
179
189
|
## NOTE 2018-05-17 - this is called by form in the very beginning when no field is actually focussed
|
180
190
|
## but active_index has been set to 0, so the on_enter has not been executed, but the handle_key
|
181
191
|
## is invoked.
|
182
192
|
def get_current_field
|
183
|
-
=begin
|
184
|
-
#select_next_field if @active_index == -1
|
185
|
-
return nil if @active_index.nil? # for forms that have no focusable field 2009-01-08 12:22
|
186
|
-
@focusables[@active_index]
|
187
|
-
=end
|
188
|
-
|
189
193
|
|
190
194
|
## rewrite on 2018-05-18 - so that on_enter is called for first field
|
191
195
|
if @_focussed_widget.nil? ## when form handle_key first called
|
192
|
-
|
196
|
+
select_widget @focusables.first
|
193
197
|
end
|
194
198
|
return @_focussed_widget
|
195
199
|
|
196
200
|
end
|
197
201
|
alias :current_widget :get_current_field
|
202
|
+
|
203
|
+
|
198
204
|
# take focus to first focusable field
|
199
|
-
# we shoud not send to select_next. have a separate method to avoid bugs.
|
200
|
-
# but check current_field, in case called from anotehr field TODO FIXME
|
201
205
|
def select_first_field
|
202
206
|
select_field 0
|
203
207
|
end
|
@@ -213,31 +217,6 @@ class Form
|
|
213
217
|
|
214
218
|
|
215
219
|
|
216
|
-
##
|
217
|
-
# puts focus on the given field/widget index
|
218
|
-
# @param index of field in @widgets (or can be a Widget too)
|
219
|
-
# XXX if called externally will not run a on_leave of previous field
|
220
|
-
def OLDselect_field ix0
|
221
|
-
if ix0.is_a? Widget
|
222
|
-
ix0 = @focusables.index(ix0)
|
223
|
-
end
|
224
|
-
return if @focusables.nil? or @focusables.empty?
|
225
|
-
$log.debug "inside select_field : #{ix0} ai #{@active_index}"
|
226
|
-
f = @focusables[ix0]
|
227
|
-
return if !f.focusable
|
228
|
-
if f.focusable
|
229
|
-
@active_index = ix0
|
230
|
-
@row, @col = f.rowcol
|
231
|
-
on_enter f
|
232
|
-
# the wmove will be overwritten by repaint later, better to set row col
|
233
|
-
_setrowcol @row, @col # 2018-03-21 - maybe this should be set after the repaint
|
234
|
-
|
235
|
-
repaint # 2018-03-21 - handle_key calls repaint, is this for cases not involving keypress ?
|
236
|
-
@window.refresh
|
237
|
-
else
|
238
|
-
$log.debug "inside select field ENABLED FALSE : act #{@active_index} ix0 #{ix0}"
|
239
|
-
end
|
240
|
-
end
|
241
220
|
|
242
221
|
# put focus on next field
|
243
222
|
# will cycle by default, unless navigation policy not :CYCLICAL
|
@@ -251,30 +230,10 @@ class Form
|
|
251
230
|
end
|
252
231
|
index = index ? index+1 : 0
|
253
232
|
index = 0 if index >= @focusables.length # CYCLICAL 2018-03-11 -
|
254
|
-
|
255
|
-
=begin
|
256
|
-
return :UNHANDLED if @focusables.nil? || @focusables.empty?
|
257
|
-
if @active_index.nil? || @active_index == -1 # needs to be tested out A LOT
|
258
|
-
@active_index = 0
|
259
|
-
end
|
260
|
-
f = @focusables[@active_index]
|
261
|
-
# we need to call on_leave of this field or else state will never change back to normal
|
262
|
-
on_leave f
|
263
|
-
#index = @focusables.index(f)
|
264
|
-
index = @active_index
|
265
|
-
index = index ? index+1 : 0
|
266
|
-
#f = @focusables[index]
|
267
|
-
index = 0 if index >= @focusables.length # CYCLICAL 2018-03-11 -
|
268
|
-
f = @focusables[index]
|
269
|
-
if f
|
270
|
-
select_field f
|
271
|
-
return 0
|
272
|
-
end
|
273
|
-
#
|
274
|
-
$log.debug "inside sele nxt field : NO NEXT #{@active_index} WL:#{@widgets.length}"
|
275
|
-
return :NO_NEXT_FIELD
|
276
|
-
=end
|
233
|
+
select_widget @focusables[index]
|
277
234
|
end
|
235
|
+
|
236
|
+
|
278
237
|
##
|
279
238
|
# put focus on previous field
|
280
239
|
# will cycle by default, unless navigation policy not :CYCLICAL
|
@@ -291,27 +250,7 @@ class Form
|
|
291
250
|
end
|
292
251
|
index -= 1
|
293
252
|
index = @focusables.length-1 if index < 0 # CYCLICAL 2018-03-11 -
|
294
|
-
|
295
|
-
=begin
|
296
|
-
return :UNHANDLED if @focusables.nil? or @focusables.empty?
|
297
|
-
#$log.debug "insdie sele prev field : #{@active_index} WL:#{@widgets.length}"
|
298
|
-
if @active_index.nil?
|
299
|
-
@active_index = @focusables.length
|
300
|
-
end
|
301
|
-
|
302
|
-
f = @focusables[@active_index]
|
303
|
-
on_leave f
|
304
|
-
index = @active_index
|
305
|
-
index -= 1
|
306
|
-
index = @focusables.length-1 if index < 0 # CYCLICAL 2018-03-11 -
|
307
|
-
f = @focusables[index]
|
308
|
-
if f
|
309
|
-
select_field f
|
310
|
-
return
|
311
|
-
end
|
312
|
-
|
313
|
-
return :NO_PREV_FIELD
|
314
|
-
=end
|
253
|
+
select_widget @focusables[index]
|
315
254
|
end
|
316
255
|
|
317
256
|
private
|
@@ -366,37 +305,8 @@ class Form
|
|
366
305
|
f.on_enter if f.respond_to? :on_enter
|
367
306
|
end
|
368
307
|
|
369
|
-
def OLD_process_key keycode, object, window
|
370
|
-
return :UNHANDLED if @_key_map.nil?
|
371
|
-
blk = @_key_map[keycode]
|
372
|
-
$log.debug "XXX: _process key keycode #{keycode} #{blk.class}, #{self.class} "
|
373
|
-
return :UNHANDLED if blk.nil?
|
374
|
-
|
375
|
-
if blk.is_a? Symbol
|
376
|
-
if respond_to? blk
|
377
|
-
return send(blk, *@_key_args[keycode])
|
378
|
-
else
|
379
|
-
## 2013-03-05 - 19:50 why the hell is there an alert here, nowhere else
|
380
|
-
alert "This ( #{self.class} ) does not respond to #{blk.to_s} [PROCESS-KEY]"
|
381
|
-
# added 2013-03-05 - 19:50 so called can know
|
382
|
-
return :UNHANDLED
|
383
|
-
end
|
384
|
-
else
|
385
|
-
$log.debug "rwidget BLOCK called _process_key " if $log.debug?
|
386
|
-
return blk.call object, *@_key_args[keycode]
|
387
|
-
end
|
388
|
-
end # }}}
|
389
308
|
|
390
309
|
public
|
391
|
-
# e.g. process_key ch, self {{{
|
392
|
-
# returns UNHANDLED if no block for it
|
393
|
-
# after form handles basic keys, it gives unhandled key to current field, if current field returns
|
394
|
-
# unhandled, then it checks this map.
|
395
|
-
# Please update widget with any changes here.
|
396
|
-
|
397
|
-
def OLDprocess_key keycode, object # already there in keymappinghandler
|
398
|
-
return _process_key keycode, object, @window
|
399
|
-
end # }}}
|
400
310
|
|
401
311
|
#
|
402
312
|
# NOTE: These mappings will only trigger if the current field
|