rbhex-core 1.0.0
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 +7 -0
- data/.gitignore +20 -0
- data/CHANGELOG +2000 -0
- data/LICENSE +56 -0
- data/README.md +44 -0
- data/examples/abasiclist.rb +179 -0
- data/examples/alpmenu.rb +50 -0
- data/examples/app.sample +19 -0
- data/examples/atree.rb +100 -0
- data/examples/bline.rb +136 -0
- data/examples/common/file.rb +45 -0
- data/examples/data/README.markdown +9 -0
- data/examples/data/brew.txt +38 -0
- data/examples/data/color.2 +37 -0
- data/examples/data/gemlist.txt +60 -0
- data/examples/data/lotr.txt +12 -0
- data/examples/data/ports.txt +136 -0
- data/examples/data/table.txt +37 -0
- data/examples/data/tasks.csv +88 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/todo.txt +10 -0
- data/examples/data/todo.txt.bak +10 -0
- data/examples/data/todocsv.csv +28 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +502 -0
- data/examples/dirtree.rb +94 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +146 -0
- data/examples/tasks.rb +178 -0
- data/examples/term2.rb +84 -0
- data/examples/testbuttons.rb +296 -0
- data/examples/testcombo.rb +102 -0
- data/examples/testfields.rb +195 -0
- data/examples/testkeypress.rb +72 -0
- data/examples/testlistbox.rb +170 -0
- data/examples/testmessagebox.rb +140 -0
- data/examples/testprogress.rb +116 -0
- data/examples/testree.rb +106 -0
- data/examples/testwsshortcuts.rb +66 -0
- data/examples/testwsshortcuts2.rb +128 -0
- data/lib/rbhex.rb +6 -0
- data/lib/rbhex/core/docs/index.txt +73 -0
- data/lib/rbhex/core/include/action.rb +80 -0
- data/lib/rbhex/core/include/actionmanager.rb +49 -0
- data/lib/rbhex/core/include/appmethods.rb +214 -0
- data/lib/rbhex/core/include/bordertitle.rb +48 -0
- data/lib/rbhex/core/include/chunk.rb +203 -0
- data/lib/rbhex/core/include/io.rb +553 -0
- data/lib/rbhex/core/include/listbindings.rb +74 -0
- data/lib/rbhex/core/include/listcellrenderer.rb +140 -0
- data/lib/rbhex/core/include/listeditable.rb +317 -0
- data/lib/rbhex/core/include/listscrollable.rb +663 -0
- data/lib/rbhex/core/include/listselectable.rb +271 -0
- data/lib/rbhex/core/include/multibuffer.rb +83 -0
- data/lib/rbhex/core/include/orderedhash.rb +77 -0
- data/lib/rbhex/core/include/ractionevent.rb +73 -0
- data/lib/rbhex/core/include/rchangeevent.rb +27 -0
- data/lib/rbhex/core/include/rhistory.rb +95 -0
- data/lib/rbhex/core/include/rinputdataevent.rb +47 -0
- data/lib/rbhex/core/include/vieditable.rb +172 -0
- data/lib/rbhex/core/include/widgetmenu.rb +66 -0
- data/lib/rbhex/core/system/colormap.rb +165 -0
- data/lib/rbhex/core/system/keyboard.rb +150 -0
- data/lib/rbhex/core/system/keydefs.rb +30 -0
- data/lib/rbhex/core/system/ncurses.rb +236 -0
- data/lib/rbhex/core/system/panel.rb +162 -0
- data/lib/rbhex/core/system/window.rb +913 -0
- data/lib/rbhex/core/util/ansiparser.rb +119 -0
- data/lib/rbhex/core/util/app.rb +1228 -0
- data/lib/rbhex/core/util/basestack.rb +410 -0
- data/lib/rbhex/core/util/bottomline.rb +1859 -0
- data/lib/rbhex/core/util/colorparser.rb +77 -0
- data/lib/rbhex/core/util/focusmanager.rb +31 -0
- data/lib/rbhex/core/util/padreader.rb +192 -0
- data/lib/rbhex/core/util/rcommandwindow.rb +604 -0
- data/lib/rbhex/core/util/rdialogs.rb +574 -0
- data/lib/rbhex/core/util/viewer.rb +149 -0
- data/lib/rbhex/core/util/widgetshortcuts.rb +506 -0
- data/lib/rbhex/core/version.rb +5 -0
- data/lib/rbhex/core/widgets/applicationheader.rb +103 -0
- data/lib/rbhex/core/widgets/box.rb +58 -0
- data/lib/rbhex/core/widgets/divider.rb +310 -0
- data/lib/rbhex/core/widgets/keylabelprinter.rb +194 -0
- data/lib/rbhex/core/widgets/rcombo.rb +253 -0
- data/lib/rbhex/core/widgets/rcontainer.rb +415 -0
- data/lib/rbhex/core/widgets/rlink.rb +30 -0
- data/lib/rbhex/core/widgets/rlist.rb +696 -0
- data/lib/rbhex/core/widgets/rmenu.rb +958 -0
- data/lib/rbhex/core/widgets/rmenulink.rb +22 -0
- data/lib/rbhex/core/widgets/rmessagebox.rb +387 -0
- data/lib/rbhex/core/widgets/rprogress.rb +118 -0
- data/lib/rbhex/core/widgets/rtabbedpane.rb +634 -0
- data/lib/rbhex/core/widgets/rtabbedwindow.rb +70 -0
- data/lib/rbhex/core/widgets/rtextarea.rb +960 -0
- data/lib/rbhex/core/widgets/rtextview.rb +739 -0
- data/lib/rbhex/core/widgets/rtree.rb +768 -0
- data/lib/rbhex/core/widgets/rwidget.rb +3277 -0
- data/lib/rbhex/core/widgets/scrollbar.rb +143 -0
- data/lib/rbhex/core/widgets/statusline.rb +113 -0
- data/lib/rbhex/core/widgets/tabular.rb +264 -0
- data/lib/rbhex/core/widgets/tabularwidget.rb +1142 -0
- data/lib/rbhex/core/widgets/textpad.rb +995 -0
- data/lib/rbhex/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/rbhex/core/widgets/tree/treemodel.rb +428 -0
- data/rbhex-core.gemspec +32 -0
- metadata +172 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# ----------------------------------------------------------------------------- #
|
|
2
|
+
# File: colorparser.rb
|
|
3
|
+
# Description: Default parse for our tmux format
|
|
4
|
+
# The aim is to be able to specify parsers so different kinds
|
|
5
|
+
# of formatting or documents can be used, such as ANSI formatted
|
|
6
|
+
# manpages.
|
|
7
|
+
# Author: rkumar http://github.com/rkumar/rbcurse/
|
|
8
|
+
# Date: 07.11.11 - 13:17
|
|
9
|
+
# License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
|
10
|
+
# Last update: 2013-04-01 13:42
|
|
11
|
+
# ----------------------------------------------------------------------------- #
|
|
12
|
+
# == TODO
|
|
13
|
+
# - perhaps we can compile the regexp once and reuse
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
module RubyCurses
|
|
17
|
+
class DefaultColorParser
|
|
18
|
+
|
|
19
|
+
# NOTE: Experimental and minimal
|
|
20
|
+
# parses the formatted string and yields either an array of color, bgcolor and attrib
|
|
21
|
+
# or the text. This will be called by convert_to_chunk.
|
|
22
|
+
#
|
|
23
|
+
# Currently, assumes colors and attributes are correct. No error checking or fancy stuff.
|
|
24
|
+
# s="#[fg=green]hello there#[fg=yellow, bg=black, dim]"
|
|
25
|
+
# @since 1.4.1 2011-11-3 experimental, can change
|
|
26
|
+
# @return [nil] knows nothign about output format.
|
|
27
|
+
|
|
28
|
+
# 187compat 2013-03-20 - 19:33 not working in 187 so added ,1 in some cases for string
|
|
29
|
+
def parse_format s # yields attribs or text
|
|
30
|
+
## set default colors
|
|
31
|
+
color = :white
|
|
32
|
+
bgcolor = :black
|
|
33
|
+
attrib = FFI::NCurses::A_NORMAL
|
|
34
|
+
text = ""
|
|
35
|
+
|
|
36
|
+
## split #[...]
|
|
37
|
+
a = s.split /(#\[[^\]]*\])/
|
|
38
|
+
a.each { |e|
|
|
39
|
+
## process color or attrib portion
|
|
40
|
+
if e[0,2] == "#[" && e[-1,1] == "]"
|
|
41
|
+
# now resetting 1:20 PM November 3, 2011 , earlier we were carrying over
|
|
42
|
+
color, bgcolor, attrib = nil, nil, nil
|
|
43
|
+
catch(:done) do
|
|
44
|
+
e = e[2..-2]
|
|
45
|
+
## first split on commas to separate fg, bg and attr
|
|
46
|
+
atts = e.split /\s*,\s*/
|
|
47
|
+
atts.each { |att|
|
|
48
|
+
## next split on =
|
|
49
|
+
part = att.split /\s*=\s*/
|
|
50
|
+
case part[0]
|
|
51
|
+
when "fg"
|
|
52
|
+
color = part[1]
|
|
53
|
+
when "bg"
|
|
54
|
+
bgcolor = part[1]
|
|
55
|
+
when "/end", "end"
|
|
56
|
+
yield :endcolor if block_given?
|
|
57
|
+
#next
|
|
58
|
+
throw :done
|
|
59
|
+
else
|
|
60
|
+
# attrib
|
|
61
|
+
attrib = part[0]
|
|
62
|
+
end
|
|
63
|
+
}
|
|
64
|
+
# 2013-03-25 - 13:31 if numeric color specified
|
|
65
|
+
color = color.to_i if color =~ /^[0-9]+$/
|
|
66
|
+
bgcolor = bgcolor.to_i if bgcolor =~ /^[0-9]+$/
|
|
67
|
+
yield [color,bgcolor,attrib] if block_given?
|
|
68
|
+
end # catch
|
|
69
|
+
else
|
|
70
|
+
text = e
|
|
71
|
+
yield text if block_given?
|
|
72
|
+
end
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Allow some objects to take focus when a certain key is pressed.
|
|
2
|
+
# This is for objects like scrollbars and grabbars. We don't want these always
|
|
3
|
+
# getting focus, only sometimes when we want to resize panes.
|
|
4
|
+
# This will not only be included by Form but by containers such as Vimsplit
|
|
5
|
+
# or MasterDetail.
|
|
6
|
+
# Usage: the idea is that when you create grabbars, you would add them to the FocusManager
|
|
7
|
+
# Thus they would remain non-focusable on creation. When hte user presses (say F3) then
|
|
8
|
+
# make_focusable is called, or toggle_focusable. Now user can press TAB and access
|
|
9
|
+
# these bars. When he is done he can toggle again.
|
|
10
|
+
# TODO: we might add a Circular class here so user can traverse only these objects
|
|
11
|
+
module RubyCurses
|
|
12
|
+
module FocusManager
|
|
13
|
+
extend self
|
|
14
|
+
attr_reader :focusables
|
|
15
|
+
# add a component to this list so it can be made focusable later
|
|
16
|
+
def add component
|
|
17
|
+
@focusables ||= []
|
|
18
|
+
@focusables << component
|
|
19
|
+
self
|
|
20
|
+
end
|
|
21
|
+
def make_focusable bool=true
|
|
22
|
+
@focusing = bool
|
|
23
|
+
@focusables.each { |e| e.focusable(bool) }
|
|
24
|
+
end
|
|
25
|
+
def toggle_focusable
|
|
26
|
+
return unless @focusables
|
|
27
|
+
alert "FocusManager Making #{@focusables.length} objects #{!@focusing} "
|
|
28
|
+
make_focusable !@focusing
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
* Name: PadReader.rb
|
|
3
|
+
* Description : This is an independent file viewer that uses a Pad and traps keys
|
|
4
|
+
* Author: rkumar (http://github.com/rkumar/rbcurse/)
|
|
5
|
+
* Date: 22.10.11 - 20:35
|
|
6
|
+
* License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
|
7
|
+
* Last update: 2013-04-01 13:43
|
|
8
|
+
|
|
9
|
+
== CHANGES
|
|
10
|
+
== TODO
|
|
11
|
+
make the window configurable so we can move to a textview that is pad based, later even list ?
|
|
12
|
+
Note that cursor does not move, in real life applicatino cursor must move to bottom row
|
|
13
|
+
and only then scrolling should start.
|
|
14
|
+
NOTE: I have continued this in textpad which is a widget that uses pads to scroll.
|
|
15
|
+
This is very rough, i may work on this more later.
|
|
16
|
+
=end
|
|
17
|
+
require 'rbhex'
|
|
18
|
+
|
|
19
|
+
include RubyCurses
|
|
20
|
+
module RubyCurses
|
|
21
|
+
class PadReader
|
|
22
|
+
|
|
23
|
+
# You may pass height, width, row and col for creating a window otherwise a fullscreen window
|
|
24
|
+
# will be created. If you pass a window from caller then that window will be used.
|
|
25
|
+
# Some keys are trapped, jkhl space, pgup, pgdown, end, home, t b
|
|
26
|
+
# This is currently very minimal and was created to get me started to integrating
|
|
27
|
+
# pads into other classes such as textview.
|
|
28
|
+
def initialize config={}, &block
|
|
29
|
+
|
|
30
|
+
@config = config
|
|
31
|
+
@rows = FFI::NCurses.LINES-1
|
|
32
|
+
@cols = FFI::NCurses.COLS-1
|
|
33
|
+
@prow = @pcol = 0
|
|
34
|
+
@startrow = 0
|
|
35
|
+
@startcol = 0
|
|
36
|
+
|
|
37
|
+
h = config.fetch(:height, 0)
|
|
38
|
+
w = config.fetch(:width, 0)
|
|
39
|
+
t = config.fetch(:row, 0)
|
|
40
|
+
l = config.fetch(:col, 0)
|
|
41
|
+
@rows = h unless h == 0
|
|
42
|
+
@cols = w unless w == 0
|
|
43
|
+
@startrow = t unless t == 0
|
|
44
|
+
@startcol = l unless l == 0
|
|
45
|
+
@suppress_border = config[:suppress_border]
|
|
46
|
+
unless @suppress_border
|
|
47
|
+
@startrow += 1
|
|
48
|
+
@startcol += 1
|
|
49
|
+
@rows -=3 # 3 is since print_border_only reduces one from width, to check whether this is correct
|
|
50
|
+
@cols -=3
|
|
51
|
+
end
|
|
52
|
+
@top = t
|
|
53
|
+
@left = l
|
|
54
|
+
view_file config[:filename]
|
|
55
|
+
@window = config[:window] || VER::Window.new(:height => h, :width => w, :top => t, :left => l)
|
|
56
|
+
# print border reduces on from width for some historical reason
|
|
57
|
+
@window.print_border_only @top, @left, h-1, w, $datacolor
|
|
58
|
+
@ph = @content_rows
|
|
59
|
+
@pw = @content_cols # get max col
|
|
60
|
+
@pad = FFI::NCurses.newpad(@ph, @pw)
|
|
61
|
+
|
|
62
|
+
Ncurses::Panel.update_panels
|
|
63
|
+
@content.each_index { |ix|
|
|
64
|
+
|
|
65
|
+
FFI::NCurses.mvwaddstr(@pad,ix, 0, @content[ix])
|
|
66
|
+
}
|
|
67
|
+
@window.wrefresh
|
|
68
|
+
padrefresh
|
|
69
|
+
#FFI::NCurses.prefresh(@pad, 0,0, @startrow ,@startcol, @rows,@cols);
|
|
70
|
+
|
|
71
|
+
@window.bkgd(Ncurses.COLOR_PAIR(5));
|
|
72
|
+
FFI::NCurses.keypad(@pad, true);
|
|
73
|
+
#@form = Form.new @window
|
|
74
|
+
config[:row] = config[:col] = 0 # ??? XXX
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
def view_file(filename)
|
|
79
|
+
@file = filename
|
|
80
|
+
@content = File.open(filename,"r").readlines
|
|
81
|
+
@content_rows = @content.count
|
|
82
|
+
@content_cols = content_cols()
|
|
83
|
+
#run()
|
|
84
|
+
end
|
|
85
|
+
# write pad onto window
|
|
86
|
+
private
|
|
87
|
+
def padrefresh
|
|
88
|
+
FFI::NCurses.prefresh(@pad,@prow,@pcol, @startrow,@startcol, @rows + @startrow,@cols+@startcol);
|
|
89
|
+
end
|
|
90
|
+
# returns button index
|
|
91
|
+
# Call this after instantiating the window
|
|
92
|
+
public
|
|
93
|
+
def run
|
|
94
|
+
#@form.repaint
|
|
95
|
+
#@window.wrefresh
|
|
96
|
+
return handle_keys
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# convenience method
|
|
100
|
+
private
|
|
101
|
+
def key x
|
|
102
|
+
x.getbyte(0)
|
|
103
|
+
end
|
|
104
|
+
def content_cols
|
|
105
|
+
longest = @content.max_by(&:length)
|
|
106
|
+
longest.length
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# returns button index
|
|
110
|
+
private
|
|
111
|
+
def handle_keys
|
|
112
|
+
ht = @window.height.ifzero FFI::NCurses.LINES-1
|
|
113
|
+
buttonindex = catch(:close) do
|
|
114
|
+
@maxrow = @content_rows - @rows
|
|
115
|
+
@maxcol = @content_cols - @cols
|
|
116
|
+
while((ch = @window.getchar()) != FFI::NCurses::KEY_F10 )
|
|
117
|
+
#while((ch = FFI::NCurses.wgetch(@pad)) != FFI::NCurses::KEY_F10 )
|
|
118
|
+
break if ch == ?\C-q.getbyte(0)
|
|
119
|
+
begin
|
|
120
|
+
case ch
|
|
121
|
+
when key(?g), 279 # home as per iterm2
|
|
122
|
+
@prow = 0
|
|
123
|
+
when key(?b), key(?G), 277 # end as per iterm2
|
|
124
|
+
@prow = @maxrow-1
|
|
125
|
+
when key(?j)
|
|
126
|
+
@prow += 1
|
|
127
|
+
when key(?k)
|
|
128
|
+
@prow -= 1
|
|
129
|
+
when 32, 338 # Page Down abd Page Up as per iTerm2
|
|
130
|
+
@prow += 10
|
|
131
|
+
when key(?\C-d)
|
|
132
|
+
@prow += ht
|
|
133
|
+
when key(?\C-b)
|
|
134
|
+
@prow -= ht
|
|
135
|
+
when 339
|
|
136
|
+
@prow -= 10
|
|
137
|
+
when key(?l)
|
|
138
|
+
@pcol += 1
|
|
139
|
+
when key(?$)
|
|
140
|
+
@pcol = @maxcol - 1
|
|
141
|
+
when key(?h)
|
|
142
|
+
@pcol -= 1
|
|
143
|
+
when key(?0)
|
|
144
|
+
@pcol = 0
|
|
145
|
+
when key(?q)
|
|
146
|
+
throw :close
|
|
147
|
+
else
|
|
148
|
+
alert " #{ch} not mapped "
|
|
149
|
+
end
|
|
150
|
+
@prow = 0 if @prow < 0
|
|
151
|
+
@pcol = 0 if @pcol < 0
|
|
152
|
+
if @prow > @maxrow-1
|
|
153
|
+
@prow = @maxrow-1
|
|
154
|
+
end
|
|
155
|
+
if @pcol > @maxcol-1
|
|
156
|
+
@pcol = @maxcol-1
|
|
157
|
+
end
|
|
158
|
+
#@window.wclear
|
|
159
|
+
#FFI::NCurses.prefresh(@pad,@prow,@pcol, @startrow,0, @rows,@cols);
|
|
160
|
+
padrefresh
|
|
161
|
+
Ncurses::Panel.update_panels
|
|
162
|
+
#@form.handle_key(ch)
|
|
163
|
+
#@window.wrefresh
|
|
164
|
+
rescue => err
|
|
165
|
+
$log.debug( err) if err
|
|
166
|
+
$log.debug(err.backtrace.join("\n")) if err
|
|
167
|
+
|
|
168
|
+
textdialog ["Error in padreader: #{err} ", *err.backtrace], :title => "Exception"
|
|
169
|
+
$error_message.value = ""
|
|
170
|
+
ensure
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
end # while loop
|
|
174
|
+
end # close
|
|
175
|
+
$log.debug "XXX: CALLER GOT #{buttonindex} "
|
|
176
|
+
@window.destroy unless @config[:window]
|
|
177
|
+
FFI::NCurses.delwin(@pad)
|
|
178
|
+
return buttonindex
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
if __FILE__ == $PROGRAM_NAME
|
|
183
|
+
require 'rbhex/core/util/app'
|
|
184
|
+
App.new do
|
|
185
|
+
#status_line :row => FFI::NCurses.LINES-1
|
|
186
|
+
@form.repaint
|
|
187
|
+
#p = PadReader.new :filename => "padreader.rb", :height => 20, :width => 60, :row => 4, :col => 4, :window => @window, :suppress_border => true
|
|
188
|
+
p = PadReader.new :filename => "padreader.rb", :height => FFI::NCurses.LINES-1, :width => 0, :row => 0, :col => 0, :window => @window, :suppress_border => true
|
|
189
|
+
p.run
|
|
190
|
+
throw :close
|
|
191
|
+
end
|
|
192
|
+
end
|
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
* Name: rcommandwindow: pops up a status message at bottom of screen
|
|
3
|
+
creating a new window, so we don't have to worry about having window
|
|
4
|
+
handle.
|
|
5
|
+
Can use with say, ask etc. wsay wask wagree etc !
|
|
6
|
+
* Description
|
|
7
|
+
* Author: rkumar (arunachalesha)
|
|
8
|
+
* Date: 2008-11-19 12:49
|
|
9
|
+
* License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
|
10
|
+
* file separated on 2009-01-13 22:39
|
|
11
|
+
|
|
12
|
+
=end
|
|
13
|
+
require 'rbhex'
|
|
14
|
+
|
|
15
|
+
module RubyCurses
|
|
16
|
+
##
|
|
17
|
+
#
|
|
18
|
+
#
|
|
19
|
+
class CommandWindow
|
|
20
|
+
include RubyCurses::Utils
|
|
21
|
+
dsl_accessor :box
|
|
22
|
+
dsl_accessor :title
|
|
23
|
+
attr_reader :config
|
|
24
|
+
attr_reader :layout
|
|
25
|
+
attr_reader :window # required for keyboard or printing
|
|
26
|
+
dsl_accessor :height, :width, :top, :left # 2009-01-06 00:05 after removing meth missing
|
|
27
|
+
|
|
28
|
+
def initialize form=nil, aconfig={}, &block
|
|
29
|
+
@config = aconfig
|
|
30
|
+
@config.each_pair { |k,v| instance_variable_set("@#{k}",v) }
|
|
31
|
+
instance_eval &block if block_given?
|
|
32
|
+
if @layout.nil?
|
|
33
|
+
set_layout(1,80, -1, 0)
|
|
34
|
+
end
|
|
35
|
+
@height = @layout[:height]
|
|
36
|
+
@width = @layout[:width]
|
|
37
|
+
@window = VER::Window.new(@layout)
|
|
38
|
+
@start = 0 # row for display of text with paging
|
|
39
|
+
@list = []
|
|
40
|
+
# 2013-03-21 - 00:34 removed due to 187
|
|
41
|
+
#require 'forwardable'
|
|
42
|
+
require 'rbhex/core/util/bottomline'
|
|
43
|
+
@bottomline = Bottomline.new @window, 0
|
|
44
|
+
@bottomline.name = "rcommandwindow's bl"
|
|
45
|
+
# 187compat next line throws up on 187 module_eval undefined method for commandwindow
|
|
46
|
+
#extend Forwardable
|
|
47
|
+
#def_delegators :@bottomline, :ask, :say, :agree, :choose #, :display_text_interactive
|
|
48
|
+
if @box == :border
|
|
49
|
+
@window.box 0,0
|
|
50
|
+
elsif @box
|
|
51
|
+
@window.attron(Ncurses.COLOR_PAIR($normalcolor) | Ncurses::A_REVERSE)
|
|
52
|
+
@window.mvhline 0,0,1,@width
|
|
53
|
+
@window.printstring 0,0,@title, $normalcolor #, 'normal' if @title
|
|
54
|
+
@window.attroff(Ncurses.COLOR_PAIR($normalcolor) | Ncurses::A_REVERSE)
|
|
55
|
+
else
|
|
56
|
+
#@window.printstring 0,0,@title, $normalcolor, 'reverse' if @title
|
|
57
|
+
title @title
|
|
58
|
+
end
|
|
59
|
+
@window.wrefresh
|
|
60
|
+
@panel = @window.panel
|
|
61
|
+
Ncurses::Panel.update_panels
|
|
62
|
+
@window.wrefresh
|
|
63
|
+
@row_offset = 0
|
|
64
|
+
if @box
|
|
65
|
+
@row_offset = 1
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
# 2013-03-21 - 187compat
|
|
69
|
+
#def_delegators :@bottomline, :ask, :say, :agree, :choose #, :display_text_interactive
|
|
70
|
+
def ask *args
|
|
71
|
+
@bottomline.send(:ask, *args)
|
|
72
|
+
end
|
|
73
|
+
def say *args
|
|
74
|
+
@bottomline.send(:say, *args)
|
|
75
|
+
end
|
|
76
|
+
def agree *args
|
|
77
|
+
@bottomline.send(:agree, *args)
|
|
78
|
+
end
|
|
79
|
+
def choose *args
|
|
80
|
+
@bottomline.send(:choose, *args)
|
|
81
|
+
end
|
|
82
|
+
# modify the window title, or get it if no params passed.
|
|
83
|
+
def title t=nil
|
|
84
|
+
return @title unless t
|
|
85
|
+
@title = t
|
|
86
|
+
@window.printstring 0,0,@title, $normalcolor, 'reverse' if @title
|
|
87
|
+
end
|
|
88
|
+
##
|
|
89
|
+
## message box
|
|
90
|
+
def stopping?
|
|
91
|
+
@stop
|
|
92
|
+
end
|
|
93
|
+
# todo handle mappings, so user can map keys TODO
|
|
94
|
+
def handle_keys
|
|
95
|
+
begin
|
|
96
|
+
while((ch = @window.getchar()) != 999 )
|
|
97
|
+
case ch
|
|
98
|
+
when -1
|
|
99
|
+
next
|
|
100
|
+
else
|
|
101
|
+
press ch
|
|
102
|
+
break if @stop
|
|
103
|
+
yield ch if block_given?
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
ensure
|
|
107
|
+
destroy
|
|
108
|
+
end
|
|
109
|
+
return #@selected_index
|
|
110
|
+
end
|
|
111
|
+
# handles a key, commandline
|
|
112
|
+
def press ch
|
|
113
|
+
ch = ch.getbyte(0) if ch.class==String ## 1.9
|
|
114
|
+
$log.debug " XXX press #{ch} " if $log.debug?
|
|
115
|
+
case ch
|
|
116
|
+
when -1
|
|
117
|
+
return
|
|
118
|
+
when KEY_F1, 27, ?\C-q.getbyte(0)
|
|
119
|
+
@stop = true
|
|
120
|
+
return
|
|
121
|
+
when KEY_ENTER, 10, 13
|
|
122
|
+
#$log.debug "popup ENTER : #{@selected_index} "
|
|
123
|
+
#$log.debug "popup ENTER : #{field.name}" if !field.nil?
|
|
124
|
+
@stop = true
|
|
125
|
+
return
|
|
126
|
+
when ?\C-d.getbyte(0)
|
|
127
|
+
@start += @height-1
|
|
128
|
+
bounds_check
|
|
129
|
+
when KEY_UP
|
|
130
|
+
@start -= 1
|
|
131
|
+
@start = 0 if @start < 0
|
|
132
|
+
when KEY_DOWN
|
|
133
|
+
@start += 1
|
|
134
|
+
bounds_check
|
|
135
|
+
when ?\C-b.getbyte(0)
|
|
136
|
+
@start -= @height-1
|
|
137
|
+
@start = 0 if @start < 0
|
|
138
|
+
when 0
|
|
139
|
+
@start = 0
|
|
140
|
+
end
|
|
141
|
+
Ncurses::Panel.update_panels();
|
|
142
|
+
Ncurses.doupdate();
|
|
143
|
+
@window.wrefresh
|
|
144
|
+
end
|
|
145
|
+
# might as well add more keys for paging.
|
|
146
|
+
def configure(*val , &block)
|
|
147
|
+
case val.size
|
|
148
|
+
when 1
|
|
149
|
+
return @config[val[0]]
|
|
150
|
+
when 2
|
|
151
|
+
@config[val[0]] = val[1]
|
|
152
|
+
instance_variable_set("@#{val[0]}", val[1])
|
|
153
|
+
end
|
|
154
|
+
instance_eval &block if block_given?
|
|
155
|
+
end
|
|
156
|
+
def cget param
|
|
157
|
+
@config[param]
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def set_layout(height=0, width=0, top=0, left=0)
|
|
161
|
+
# negative means top should be n rows from last line. -1 is last line
|
|
162
|
+
if top < 0
|
|
163
|
+
top = Ncurses.LINES-top
|
|
164
|
+
end
|
|
165
|
+
@layout = { :height => height, :width => width, :top => top, :left => left }
|
|
166
|
+
@height = height
|
|
167
|
+
@width = width
|
|
168
|
+
end
|
|
169
|
+
def destroy
|
|
170
|
+
$log.debug "DESTROY : rcommandwindow"
|
|
171
|
+
if @window
|
|
172
|
+
begin
|
|
173
|
+
panel = @window.panel
|
|
174
|
+
Ncurses::Panel.del_panel(panel.pointer) if panel
|
|
175
|
+
@window.delwin
|
|
176
|
+
rescue => exc
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
#
|
|
181
|
+
# Displays list in a window at bottom of screen, if large then 2 or 3 columns.
|
|
182
|
+
# @param [Array] list of string to be displayed
|
|
183
|
+
# @param [Hash] configuration options: indexing and indexcolor
|
|
184
|
+
# indexing - can be letter or number. Anything else will be ignored, however
|
|
185
|
+
# it will result in first letter being highlighted in indexcolor
|
|
186
|
+
# indexcolor - color of mnemonic, default green
|
|
187
|
+
def display_menu list, options={}
|
|
188
|
+
indexing = options[:indexing]
|
|
189
|
+
indexcolor = options[:indexcolor] || get_color($normalcolor, :yellow, :black)
|
|
190
|
+
indexatt = Ncurses::A_BOLD
|
|
191
|
+
#
|
|
192
|
+
# the index to start from (used when scrolling a long menu such as file list)
|
|
193
|
+
startindex = options[:startindex] || 0
|
|
194
|
+
|
|
195
|
+
max_cols = 3 # maximum no of columns, we will reduce based on data size
|
|
196
|
+
l_succ = "`"
|
|
197
|
+
act_height = @height
|
|
198
|
+
if @box
|
|
199
|
+
act_height = @height - 2
|
|
200
|
+
end
|
|
201
|
+
lh = list.size
|
|
202
|
+
if lh < act_height
|
|
203
|
+
$log.debug "DDD inside one window" if $log.debug?
|
|
204
|
+
list.each_with_index { |e, i|
|
|
205
|
+
text = e
|
|
206
|
+
case e
|
|
207
|
+
when Array
|
|
208
|
+
text = e.first + " ..."
|
|
209
|
+
end
|
|
210
|
+
if indexing == :number
|
|
211
|
+
mnem = i+1
|
|
212
|
+
text = "%d. %s" % [i+1, text]
|
|
213
|
+
elsif indexing == :letter
|
|
214
|
+
mnem = l_succ.succ!
|
|
215
|
+
text = "%s. %s" % [mnem, text]
|
|
216
|
+
end
|
|
217
|
+
@window.printstring i+@row_offset, 1, text, $normalcolor
|
|
218
|
+
if indexing
|
|
219
|
+
window.mvchgat(y=i+@row_offset, x=1, max=1, indexatt, indexcolor, nil)
|
|
220
|
+
end
|
|
221
|
+
}
|
|
222
|
+
else
|
|
223
|
+
$log.debug "DDD inside two window" if $log.debug?
|
|
224
|
+
row = 0
|
|
225
|
+
h = act_height
|
|
226
|
+
cols = (lh*1.0 / h).ceil
|
|
227
|
+
cols = max_cols if cols > max_cols
|
|
228
|
+
# sometimes elements are large like directory paths, so check size
|
|
229
|
+
datasize = list.first.length
|
|
230
|
+
if datasize > @width/3 # keep safety margin since checking only first row
|
|
231
|
+
cols = 1
|
|
232
|
+
elsif datasize > @width/2
|
|
233
|
+
cols = [2,cols].min
|
|
234
|
+
end
|
|
235
|
+
adv = (@width/cols).to_i
|
|
236
|
+
colct = 0
|
|
237
|
+
col = 1
|
|
238
|
+
$log.debug "DDDcols #{cols}, adv #{adv} size: #{lh} h: #{act_height} w #{@width} " if $log.debug?
|
|
239
|
+
list.each_with_index { |e, i|
|
|
240
|
+
text = e
|
|
241
|
+
# signify that there's a deeper level
|
|
242
|
+
case e
|
|
243
|
+
when Array
|
|
244
|
+
text = e.first + "..."
|
|
245
|
+
end
|
|
246
|
+
if indexing == :number
|
|
247
|
+
mnem = i+1
|
|
248
|
+
text = "%d. %s" % [mnem, text]
|
|
249
|
+
elsif indexing == :letter
|
|
250
|
+
mnem = l_succ.succ!
|
|
251
|
+
text = "%s. %s" % [mnem, text]
|
|
252
|
+
end
|
|
253
|
+
# print only within range and window height
|
|
254
|
+
if i >= startindex && row < @window.actual_height
|
|
255
|
+
$log.debug "XXX: MENU #{i} > #{startindex} row #{row} col #{col} "
|
|
256
|
+
@window.printstring row+@row_offset, col, text, $normalcolor
|
|
257
|
+
if indexing
|
|
258
|
+
@window.mvchgat(y=row+@row_offset, x=col, max=1, indexatt, indexcolor, nil)
|
|
259
|
+
end
|
|
260
|
+
colct += 1
|
|
261
|
+
if colct == cols
|
|
262
|
+
col = 1
|
|
263
|
+
row += 1
|
|
264
|
+
colct = 0
|
|
265
|
+
else
|
|
266
|
+
col += adv
|
|
267
|
+
end
|
|
268
|
+
end # startindex
|
|
269
|
+
}
|
|
270
|
+
end
|
|
271
|
+
Ncurses::Panel.update_panels();
|
|
272
|
+
Ncurses.doupdate();
|
|
273
|
+
@window.wrefresh
|
|
274
|
+
end
|
|
275
|
+
# refresh whatevers painted onto the window
|
|
276
|
+
def refresh
|
|
277
|
+
Ncurses::Panel.update_panels();
|
|
278
|
+
Ncurses.doupdate();
|
|
279
|
+
@window.wrefresh
|
|
280
|
+
end
|
|
281
|
+
# clears the window, leaving the title line as is, from row 1 onwards
|
|
282
|
+
def clear
|
|
283
|
+
@window.wmove 1,1
|
|
284
|
+
@window.wclrtobot
|
|
285
|
+
@window.box 0,0 if @box == :border
|
|
286
|
+
# lower line of border will get erased currently since we are writing to
|
|
287
|
+
# last line FIXME
|
|
288
|
+
end
|
|
289
|
+
def display_interactive text, config={}
|
|
290
|
+
if @to
|
|
291
|
+
@to.content text
|
|
292
|
+
else
|
|
293
|
+
config[:box] = @box
|
|
294
|
+
@to = ListObject.new self, text, config
|
|
295
|
+
end
|
|
296
|
+
yield @to if block_given?
|
|
297
|
+
@to.display_interactive # this returns the item selected
|
|
298
|
+
@to # this will return the ListObject to the user with list and current_index
|
|
299
|
+
end
|
|
300
|
+
# non interactive list display - EACH CALL IS CREATING A LIST OBJECT
|
|
301
|
+
def udisplay_list text, config={}
|
|
302
|
+
if @to
|
|
303
|
+
@to.content text
|
|
304
|
+
else
|
|
305
|
+
config[:box] = @box
|
|
306
|
+
@to = ListObject.new self, text, config
|
|
307
|
+
end
|
|
308
|
+
#@to ||= ListObject.new self, text, config
|
|
309
|
+
yield @to if block_given?
|
|
310
|
+
@to.display_content
|
|
311
|
+
@to
|
|
312
|
+
end
|
|
313
|
+
# displays a list
|
|
314
|
+
# Why did we create another list ? 2011-12-5
|
|
315
|
+
class ListObject
|
|
316
|
+
attr_reader :cw
|
|
317
|
+
attr_reader :list
|
|
318
|
+
attr_reader :current_index
|
|
319
|
+
attr_accessor :focussed_attrib
|
|
320
|
+
attr_accessor :focussed_symbol
|
|
321
|
+
def initialize cw, _list, config={}
|
|
322
|
+
@cw = cw
|
|
323
|
+
layout = @cw.layout
|
|
324
|
+
@window = @cw.window
|
|
325
|
+
@height = layout[:height]
|
|
326
|
+
@width = layout[:width]
|
|
327
|
+
content(_list)
|
|
328
|
+
@height_adjust = config.fetch(:box, true) == :border ? 3 : 2
|
|
329
|
+
@selected_index = nil
|
|
330
|
+
@current_index = 0
|
|
331
|
+
@row_offset = 1
|
|
332
|
+
@toprow = 0
|
|
333
|
+
$multiplier = 0 # till we can do something
|
|
334
|
+
|
|
335
|
+
@focussed_symbol = ''
|
|
336
|
+
@row_selected_symbol = ''
|
|
337
|
+
#@show_selector = true
|
|
338
|
+
if @show_selector
|
|
339
|
+
@row_selected_symbol ||= '*'
|
|
340
|
+
@row_unselected_symbol ||= ' '
|
|
341
|
+
@left_margin ||= @row_selected_symbol.length
|
|
342
|
+
end
|
|
343
|
+
#@show_selector = true
|
|
344
|
+
#@row_selected_symbol = '*'
|
|
345
|
+
#@row_unselected_symbol = ' '
|
|
346
|
+
end
|
|
347
|
+
def content txt, config={}
|
|
348
|
+
@current_index = 0 # sometimes it gets left at a higher value than there are rows to show
|
|
349
|
+
case txt
|
|
350
|
+
when String
|
|
351
|
+
txt = wrap_text(txt, @width-2).split("\n")
|
|
352
|
+
when Array
|
|
353
|
+
# okay
|
|
354
|
+
end
|
|
355
|
+
@list = txt
|
|
356
|
+
end
|
|
357
|
+
# maybe we should just use a textview or label rather than try to
|
|
358
|
+
# do it all voer again !
|
|
359
|
+
def display_interactive
|
|
360
|
+
display_content
|
|
361
|
+
while !@stop
|
|
362
|
+
@window.wrefresh # FFI 2011-09-12
|
|
363
|
+
# FIXME only clear and redisplay if change has happened (repaint_require)
|
|
364
|
+
handle_keys { |ch| @cw.clear; display_content }
|
|
365
|
+
end
|
|
366
|
+
return @list[@current_index]
|
|
367
|
+
end
|
|
368
|
+
def is_row_selected row
|
|
369
|
+
@selected_index == row
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def scrollatrow
|
|
373
|
+
@height - 3
|
|
374
|
+
end
|
|
375
|
+
def row_count
|
|
376
|
+
@list.size
|
|
377
|
+
end
|
|
378
|
+
def rowcol
|
|
379
|
+
return @row_offset, @col_offset
|
|
380
|
+
end
|
|
381
|
+
def display_content #:nodoc:
|
|
382
|
+
|
|
383
|
+
@graphic = @window
|
|
384
|
+
@start ||= 0
|
|
385
|
+
@toprow ||= 0
|
|
386
|
+
@left_margin ||= @row_selected_symbol.length + @focussed_symbol.length
|
|
387
|
+
|
|
388
|
+
#print_borders unless @suppress_borders # do this once only, unless everything changes
|
|
389
|
+
#maxlen = @maxlen ||= @width-2
|
|
390
|
+
tm = @list
|
|
391
|
+
rc = tm.size
|
|
392
|
+
@col_offset = 1
|
|
393
|
+
#@longest_line = @width
|
|
394
|
+
if rc > 0 # just added in case no data passed
|
|
395
|
+
#tr = @start #@toprow
|
|
396
|
+
tr = @toprow
|
|
397
|
+
acolor = get_color $datacolor
|
|
398
|
+
#h = @height - 3 #2
|
|
399
|
+
h = @height - @height_adjust
|
|
400
|
+
r,c = @row_offset, @col_offset
|
|
401
|
+
0.upto(h) do |hh|
|
|
402
|
+
crow = tr+hh
|
|
403
|
+
if crow < rc
|
|
404
|
+
focussed = @current_index == crow # row focussed ?
|
|
405
|
+
selected = is_row_selected crow
|
|
406
|
+
content = tm[crow] # 2009-01-17 18:37 chomp giving error in some cases says frozen
|
|
407
|
+
# by now it has to be a String
|
|
408
|
+
## set the selector symbol if requested
|
|
409
|
+
selection_symbol = ''
|
|
410
|
+
if @show_selector
|
|
411
|
+
if selected
|
|
412
|
+
selection_symbol = @row_selected_symbol
|
|
413
|
+
else
|
|
414
|
+
selection_symbol = @row_unselected_symbol
|
|
415
|
+
end
|
|
416
|
+
@graphic.printstring r+hh, c, selection_symbol, acolor,@attr
|
|
417
|
+
end
|
|
418
|
+
#renderer = get_default_cell_renderer_for_class content.class.to_s
|
|
419
|
+
if focussed
|
|
420
|
+
if @focussed_symbol
|
|
421
|
+
@graphic.printstring r+hh, c, @focussed_symbol, acolor,@attr
|
|
422
|
+
end
|
|
423
|
+
@graphic.printstring r+hh, c+@left_margin, content, acolor, @focussed_attrib || 'reverse'
|
|
424
|
+
else
|
|
425
|
+
@graphic.printstring r+hh, c+@left_margin, content, acolor,@attr
|
|
426
|
+
end
|
|
427
|
+
#renderer.repaint @graphic, r+hh, c+@left_margin, crow, content, focussed, selected
|
|
428
|
+
else
|
|
429
|
+
# clear rows
|
|
430
|
+
@graphic.printstring r+hh, c, " " * (@width-2), acolor,@attr
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
end # rc == 0
|
|
434
|
+
set_form_row
|
|
435
|
+
end
|
|
436
|
+
# listobject
|
|
437
|
+
def press ch # list TODO copy from rbasiclist
|
|
438
|
+
ch = ch.getbyte(0) if ch.class==String ## 1.9
|
|
439
|
+
$log.debug " XXX press #{ch} " if $log.debug?
|
|
440
|
+
case ch
|
|
441
|
+
when -1
|
|
442
|
+
return
|
|
443
|
+
when KEY_F1, 27, ?\C-q.getbyte(0)
|
|
444
|
+
@stop = true
|
|
445
|
+
return
|
|
446
|
+
when KEY_ENTER, 10, 13
|
|
447
|
+
#$log.debug "popup ENTER : #{@selected_index} "
|
|
448
|
+
#$log.debug "popup ENTER : #{field.name}" if !field.nil?
|
|
449
|
+
@stop = true
|
|
450
|
+
return
|
|
451
|
+
when 32, ?\C-d.getbyte(0)
|
|
452
|
+
scroll_forward
|
|
453
|
+
#@start += @height-1
|
|
454
|
+
#bounds_check
|
|
455
|
+
when KEY_UP, ?k.getbyte(0)
|
|
456
|
+
previous_row
|
|
457
|
+
#@start -= 1
|
|
458
|
+
#@current_index -= 1
|
|
459
|
+
#@current_index = 0 if @current_index < 0
|
|
460
|
+
#@start = 0 if @start < 0
|
|
461
|
+
when KEY_DOWN, ?j.getbyte(0)
|
|
462
|
+
next_row
|
|
463
|
+
#@start += 1
|
|
464
|
+
#@current_index += 1
|
|
465
|
+
#bounds_check
|
|
466
|
+
when ?\C-b.getbyte(0)
|
|
467
|
+
scroll_backward
|
|
468
|
+
#@start -= @height-1
|
|
469
|
+
#@start = 0 if @start < 0
|
|
470
|
+
when 0, ?g.getbyte(0)
|
|
471
|
+
goto_top
|
|
472
|
+
when ?G.getbyte(0)
|
|
473
|
+
goto_bottom
|
|
474
|
+
end
|
|
475
|
+
#@form.repaint
|
|
476
|
+
Ncurses::Panel.update_panels();
|
|
477
|
+
Ncurses.doupdate();
|
|
478
|
+
@window.wrefresh
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
def previous_row num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
|
|
482
|
+
#return :UNHANDLED if @current_index == 0 # EVIL
|
|
483
|
+
return false if @current_index == 0
|
|
484
|
+
@oldrow = @current_index
|
|
485
|
+
num.times {
|
|
486
|
+
@current_index -= 1 if @current_index > 0
|
|
487
|
+
}
|
|
488
|
+
bounds_check
|
|
489
|
+
$multiplier = 0
|
|
490
|
+
end
|
|
491
|
+
alias :up :previous_row
|
|
492
|
+
def next_row num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
|
|
493
|
+
rc = row_count
|
|
494
|
+
return false if @current_index == rc-1
|
|
495
|
+
@oldrow = @current_index
|
|
496
|
+
@current_index += 1*num if @current_index < rc
|
|
497
|
+
bounds_check
|
|
498
|
+
$multiplier = 0
|
|
499
|
+
end
|
|
500
|
+
alias :down :next_row
|
|
501
|
+
def goto_bottom
|
|
502
|
+
@oldrow = @current_index
|
|
503
|
+
rc = row_count
|
|
504
|
+
@current_index = rc -1
|
|
505
|
+
bounds_check
|
|
506
|
+
end
|
|
507
|
+
alias :goto_end :goto_bottom
|
|
508
|
+
def goto_top
|
|
509
|
+
@oldrow = @current_index
|
|
510
|
+
@current_index = 0
|
|
511
|
+
bounds_check
|
|
512
|
+
end
|
|
513
|
+
alias :goto_start :goto_top
|
|
514
|
+
def scroll_backward
|
|
515
|
+
@oldrow = @current_index
|
|
516
|
+
h = scrollatrow()
|
|
517
|
+
m = $multiplier == 0? 1 : $multiplier
|
|
518
|
+
@current_index -= h * m
|
|
519
|
+
bounds_check
|
|
520
|
+
$multiplier = 0
|
|
521
|
+
end
|
|
522
|
+
def scroll_forward
|
|
523
|
+
@oldrow = @current_index
|
|
524
|
+
h = scrollatrow()
|
|
525
|
+
rc = row_count
|
|
526
|
+
m = $multiplier == 0? 1 : $multiplier
|
|
527
|
+
# more rows than box
|
|
528
|
+
if h * m < rc
|
|
529
|
+
@toprow += h+1 #if @current_index+h < rc
|
|
530
|
+
@current_index = @toprow
|
|
531
|
+
else
|
|
532
|
+
# fewer rows than box
|
|
533
|
+
@current_index = rc -1
|
|
534
|
+
end
|
|
535
|
+
#@current_index += h+1 #if @current_index+h < rc
|
|
536
|
+
bounds_check
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
##
|
|
540
|
+
# please set oldrow before calling this. Store current_index as oldrow before changing. NOTE
|
|
541
|
+
def bounds_check
|
|
542
|
+
h = scrollatrow()
|
|
543
|
+
rc = row_count
|
|
544
|
+
|
|
545
|
+
@current_index = 0 if @current_index < 0 # not lt 0
|
|
546
|
+
@current_index = rc-1 if @current_index >= rc && rc>0 # not gt rowcount
|
|
547
|
+
@toprow = rc-h-1 if rc > h && @toprow > rc - h - 1 # toprow shows full page if possible
|
|
548
|
+
# curr has gone below table, move toprow forward
|
|
549
|
+
if @current_index - @toprow > h
|
|
550
|
+
@toprow = @current_index - h
|
|
551
|
+
elsif @current_index < @toprow
|
|
552
|
+
# curr has gone above table, move toprow up
|
|
553
|
+
@toprow = @current_index
|
|
554
|
+
end
|
|
555
|
+
set_form_row
|
|
556
|
+
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def set_form_row
|
|
560
|
+
r,c = rowcol
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
# when the toprow is set externally then cursor can be mispositioned since
|
|
564
|
+
# bounds_check has not been called
|
|
565
|
+
if @current_index < @toprow
|
|
566
|
+
# cursor is outside table
|
|
567
|
+
@current_index = @toprow # ??? only if toprow 2010-10-19 12:56
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
row = r + (@current_index-@toprow)
|
|
571
|
+
# row should not be < r or greater than r+height TODO FIXME
|
|
572
|
+
|
|
573
|
+
#setrowcol row, nil
|
|
574
|
+
@window.wmove row, c
|
|
575
|
+
@window.wrefresh # FFI added to keep cursor display in synch with selection
|
|
576
|
+
end
|
|
577
|
+
def OLDbounds_check #:nodoc:
|
|
578
|
+
@start = 0 if @start < 0
|
|
579
|
+
row_offset = 1
|
|
580
|
+
last = (@list.length)-(@height-row_offset-1)
|
|
581
|
+
if @start > last
|
|
582
|
+
@start = last
|
|
583
|
+
end
|
|
584
|
+
end # bounds_check
|
|
585
|
+
def handle_keys #:nodoc:
|
|
586
|
+
begin
|
|
587
|
+
while((ch = @window.getchar()) != 999 )
|
|
588
|
+
case ch
|
|
589
|
+
when -1
|
|
590
|
+
next
|
|
591
|
+
else
|
|
592
|
+
press ch
|
|
593
|
+
break if @stop
|
|
594
|
+
yield ch if block_given?
|
|
595
|
+
end
|
|
596
|
+
end
|
|
597
|
+
ensure
|
|
598
|
+
@cw.destroy
|
|
599
|
+
end
|
|
600
|
+
return @current_index
|
|
601
|
+
end
|
|
602
|
+
end # class ListObject
|
|
603
|
+
end # class CommandWindow
|
|
604
|
+
end # module
|