ncumbra 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|