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,553 @@
|
|
|
1
|
+
#*******************************************************
|
|
2
|
+
# Some common io routines for getting data or putting
|
|
3
|
+
# at some point
|
|
4
|
+
# Arunachalesha
|
|
5
|
+
# 2010-03-06 12:10
|
|
6
|
+
# Some are outdated.
|
|
7
|
+
# Current are:
|
|
8
|
+
# * rbgetstr (and those it calls)
|
|
9
|
+
# * display_cmenu and create_mitem
|
|
10
|
+
# Changes:
|
|
11
|
+
# 2011-12-6 : removed many old, outdated methods.
|
|
12
|
+
#*******************************************************#
|
|
13
|
+
module RubyCurses
|
|
14
|
+
module Io
|
|
15
|
+
|
|
16
|
+
# create a 2 line window at bottom to accept user input
|
|
17
|
+
#
|
|
18
|
+
def __create_footer_window h = 2 , w = Ncurses.COLS, t = Ncurses.LINES-2, l = 0
|
|
19
|
+
ewin = VER::Window.new(h, w , t, l)
|
|
20
|
+
end
|
|
21
|
+
# 2011-11-27 I have replaced the getting of chars with a field
|
|
22
|
+
|
|
23
|
+
# routine to get a string at bottom of window.
|
|
24
|
+
# The first 3 params are no longer required since we create a window
|
|
25
|
+
# of our own.
|
|
26
|
+
# @param [String] prompt - label to show
|
|
27
|
+
# @param [Fixnum] maxlen - max length of input
|
|
28
|
+
# @param [Hash] config - :default, :display_length of Field, :help_text, :tab_completion
|
|
29
|
+
# help_text is displayed on F1
|
|
30
|
+
# tab_completion is a proc which helps to complete user input
|
|
31
|
+
# This method is now only for backward compatibility
|
|
32
|
+
# rbgetstr had various return codes based on whether user asked for help
|
|
33
|
+
# possibly mimicking alpine, or because i could do nothing about it.
|
|
34
|
+
# Now, rbgets handles that and only returns if the user cancels or enters
|
|
35
|
+
# a string, so rbgets does not need to return other codes.
|
|
36
|
+
def rbgetstr(nolongerused, r, c, prompt, maxlen, config={})
|
|
37
|
+
config[:maxlen] = maxlen
|
|
38
|
+
str = rb_gets(prompt, config)
|
|
39
|
+
if str
|
|
40
|
+
return 0, str
|
|
41
|
+
else
|
|
42
|
+
return -1, nil
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# get a string at the bottom of the screen
|
|
47
|
+
#
|
|
48
|
+
# @param [String] prompt - label to show
|
|
49
|
+
# @param [Hash] config - :default, :display_length of Field, :help_text, :tab_completion
|
|
50
|
+
# help_text is displayed on F1
|
|
51
|
+
# tab_completion is a proc which helps to complete user input
|
|
52
|
+
# @yield [Field] for overriding or customization
|
|
53
|
+
# @return [String, nil] String if entered, nil if canceled
|
|
54
|
+
def rb_gets(prompt, config={}) # yield field
|
|
55
|
+
if config.is_a? Array
|
|
56
|
+
options = config
|
|
57
|
+
completion_proc = Proc.new{|str|
|
|
58
|
+
options.dup.grep Regexp.new("^#{str}");
|
|
59
|
+
}
|
|
60
|
+
config = {}
|
|
61
|
+
config[:tab_completion] = completion_proc
|
|
62
|
+
end
|
|
63
|
+
begin
|
|
64
|
+
win = __create_footer_window
|
|
65
|
+
form = Form.new win
|
|
66
|
+
r = 0; c = 1;
|
|
67
|
+
default = config[:default] || ""
|
|
68
|
+
prompt = "#{prompt} [#{default}]:" if default.size > 0
|
|
69
|
+
_max = FFI::NCurses.COLS-1-prompt.size-4
|
|
70
|
+
displen = config[:display_length] || [config[:maxlen] || 999, _max].min
|
|
71
|
+
maxlen = config[:maxlen] || _max
|
|
72
|
+
field = Field.new form, :row => r, :col => c, :maxlen => maxlen, :default => default, :label => prompt,
|
|
73
|
+
:display_length => displen
|
|
74
|
+
bg = Ncurses.COLORS >= 236 ? 233 : :blue
|
|
75
|
+
field.bgcolor = bg
|
|
76
|
+
field.cursor_end if default.size > 0
|
|
77
|
+
def field.default=(x); default(x);end
|
|
78
|
+
|
|
79
|
+
# if user wishes to use the yield and say "field.history = [x,y,z] then
|
|
80
|
+
# we should alredy have extended this, so lets make it permanent
|
|
81
|
+
#if config[:history]
|
|
82
|
+
#raise ArgumentError, "Field history must be an array" unless config[:history].is_a? Array
|
|
83
|
+
require 'rbhex/core/include/rhistory'
|
|
84
|
+
field.extend(FieldHistory)
|
|
85
|
+
#field.history_config :row =>
|
|
86
|
+
field.history = config[:history]
|
|
87
|
+
#end
|
|
88
|
+
|
|
89
|
+
yield field if block_given?
|
|
90
|
+
form.repaint
|
|
91
|
+
win.wrefresh
|
|
92
|
+
prevchar = 0
|
|
93
|
+
entries = nil
|
|
94
|
+
oldstr = nil # for tab completion, origal word entered by user
|
|
95
|
+
while ((ch = win.getchar()) != 999)
|
|
96
|
+
break if ch == 10 || ch == 13 || ch == KEY_ENTER
|
|
97
|
+
#return -1, nil if ch == ?\C-c.getbyte(0) || ch == ?\C-g.getbyte(0)
|
|
98
|
+
return nil if ch == ?\C-c.getbyte(0) || ch == ?\C-g.getbyte(0)
|
|
99
|
+
#if ch == ?\M-h.getbyte(0) # HELP KEY
|
|
100
|
+
#help_text = config[:help_text] || "No help provided"
|
|
101
|
+
#color = $datacolor
|
|
102
|
+
#print_help(win, r, c, color, help_text)
|
|
103
|
+
## this will come over our text
|
|
104
|
+
#end
|
|
105
|
+
# TODO tab completion and help_text print on F1
|
|
106
|
+
# that field objects can extend, same for tab completion and gmail completion
|
|
107
|
+
if ch == KEY_TAB
|
|
108
|
+
if config
|
|
109
|
+
str = field.text
|
|
110
|
+
if prevchar == KEY_TAB
|
|
111
|
+
if !entries.nil? && !entries.empty?
|
|
112
|
+
str = entries.delete_at(0)
|
|
113
|
+
else
|
|
114
|
+
str = oldstr if oldstr
|
|
115
|
+
prevchar = ch = nil # so it can start again completing
|
|
116
|
+
end
|
|
117
|
+
else
|
|
118
|
+
tabc = config[:tab_completion] unless tabc
|
|
119
|
+
next unless tabc
|
|
120
|
+
oldstr = str.dup
|
|
121
|
+
entries = tabc.call(str).dup
|
|
122
|
+
$log.debug " tab got #{entries} for str=#{str}"
|
|
123
|
+
str = entries.delete_at(0) unless entries.nil? || entries.empty?
|
|
124
|
+
str = str.to_s.dup
|
|
125
|
+
end
|
|
126
|
+
if str
|
|
127
|
+
field.text = str
|
|
128
|
+
field.cursor_end
|
|
129
|
+
field.set_form_col # shit why are we doign this, text sets curpos to 0
|
|
130
|
+
end
|
|
131
|
+
form.repaint
|
|
132
|
+
win.wrefresh
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# tab_completion
|
|
136
|
+
# if previous char was not tab, execute tab_completion_proc and push first entry
|
|
137
|
+
# else push the next entry
|
|
138
|
+
elsif ch == KEY_F1
|
|
139
|
+
help_text = config[:help_text] || "No help provided. C-c/C-g aborts. <TAB> completion. Alt-h history. C-a/e"
|
|
140
|
+
print_status_message help_text, :wait => 7
|
|
141
|
+
else
|
|
142
|
+
form.handle_key ch
|
|
143
|
+
end
|
|
144
|
+
prevchar = ch
|
|
145
|
+
win.wrefresh
|
|
146
|
+
end
|
|
147
|
+
rescue => err
|
|
148
|
+
Ncurses.beep
|
|
149
|
+
textdialog [err.to_s, *err.backtrace], :title => "Exception"
|
|
150
|
+
$log.error "EXC in rbgetsr #{err} "
|
|
151
|
+
$log.error(err.backtrace.join("\n"))
|
|
152
|
+
ensure
|
|
153
|
+
win.destroy if win
|
|
154
|
+
end
|
|
155
|
+
config[:history] << field.text if config[:history] && field.text
|
|
156
|
+
return field.text
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# get a character.
|
|
160
|
+
# unlike rb_gets allows user to enter control or alt or function character too.
|
|
161
|
+
# @param [String] prompt or label to show.
|
|
162
|
+
# @param [Hash] configuration such as default or regexp for validation
|
|
163
|
+
# @return [Fixnum] nil if canceled, or ret value of getchar which is numeric
|
|
164
|
+
# If default provided, then ENTER returns the default
|
|
165
|
+
def rb_getchar(prompt, config={}) # yield field
|
|
166
|
+
begin
|
|
167
|
+
win = __create_footer_window
|
|
168
|
+
#form = Form.new win
|
|
169
|
+
r = 0; c = 1;
|
|
170
|
+
default = config[:default]
|
|
171
|
+
prompt = "#{prompt} [#{default}] " if default
|
|
172
|
+
win.mvprintw(r, c, "%s: " % prompt);
|
|
173
|
+
bg = Ncurses.COLORS >= 236 ? 236 : :blue
|
|
174
|
+
color_pair = get_color($reversecolor, :white, bg)
|
|
175
|
+
win.printstring r, c + prompt.size + 2, " ", color_pair
|
|
176
|
+
|
|
177
|
+
win.wrefresh
|
|
178
|
+
prevchar = 0
|
|
179
|
+
entries = nil
|
|
180
|
+
while ((ch = win.getchar()) != 999)
|
|
181
|
+
return default.ord if default && (ch == 13 || ch == KEY_ENTER)
|
|
182
|
+
return nil if ch == ?\C-c.getbyte(0) || ch == ?\C-g.getbyte(0)
|
|
183
|
+
if ch == KEY_F1
|
|
184
|
+
help_text = config[:help_text] || "No help provided. C-c/C-g aborts."
|
|
185
|
+
print_status_message help_text, :wait => 7
|
|
186
|
+
win.wrefresh # nevr had to do this with ncurses, but have to with ffi-ncurses ??
|
|
187
|
+
next
|
|
188
|
+
end
|
|
189
|
+
if config[:regexp]
|
|
190
|
+
reg = config[:regexp]
|
|
191
|
+
if ch > 0 && ch < 256
|
|
192
|
+
chs = ch.chr
|
|
193
|
+
return ch if chs =~ reg
|
|
194
|
+
alert "Wrong character. #{reg} "
|
|
195
|
+
else
|
|
196
|
+
alert "Wrong character. #{reg} "
|
|
197
|
+
end
|
|
198
|
+
else
|
|
199
|
+
return ch
|
|
200
|
+
end
|
|
201
|
+
#form.handle_key ch
|
|
202
|
+
win.wrefresh
|
|
203
|
+
end
|
|
204
|
+
rescue => err
|
|
205
|
+
Ncurses.beep
|
|
206
|
+
$log.error "EXC in rbgetsr #{err} "
|
|
207
|
+
$log.error(err.backtrace.join("\n"))
|
|
208
|
+
ensure
|
|
209
|
+
win.destroy if win
|
|
210
|
+
end
|
|
211
|
+
return nil
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# This is just experimental, trying out tab_completion
|
|
215
|
+
# Prompt user for a file name, allowing him to tab to complete filenames
|
|
216
|
+
# @param [String] label to print before field
|
|
217
|
+
# @param [Fixnum] max length of field
|
|
218
|
+
# @return [String] filename or blank if user cancelled
|
|
219
|
+
def get_file prompt, config={} #:nodoc:
|
|
220
|
+
maxlen = 70
|
|
221
|
+
tabc = Proc.new {|str| Dir.glob(str +"*") }
|
|
222
|
+
config[:tab_completion] ||= tabc
|
|
223
|
+
#config[:default] = "test"
|
|
224
|
+
ret, str = rbgetstr(nil,0,0, prompt, maxlen, config)
|
|
225
|
+
#$log.debug " get_file returned #{ret} , #{str} "
|
|
226
|
+
return "" if ret != 0
|
|
227
|
+
return str
|
|
228
|
+
end
|
|
229
|
+
def clear_this win, r, c, color, len
|
|
230
|
+
print_this(win, "%-*s" % [len," "], color, r, c)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
##
|
|
236
|
+
# prints given text to window, in color at x and y coordinates
|
|
237
|
+
# @param [Window] window to write to
|
|
238
|
+
# @param [String] text to print
|
|
239
|
+
# @param [int] color pair such as $datacolor or $promptcolor
|
|
240
|
+
# @param [int] x row
|
|
241
|
+
# @param [int] y col
|
|
242
|
+
# @see Window#printstring
|
|
243
|
+
def print_this(win, text, color, x, y)
|
|
244
|
+
raise "win nil in print_this" unless win
|
|
245
|
+
color=Ncurses.COLOR_PAIR(color);
|
|
246
|
+
win.attron(color);
|
|
247
|
+
#win.mvprintw(x, y, "%-40s" % text);
|
|
248
|
+
win.mvprintw(x, y, "%s" % text);
|
|
249
|
+
win.attroff(color);
|
|
250
|
+
win.refresh
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
#
|
|
255
|
+
# warn user: currently flashes and places error in log file
|
|
256
|
+
# experimental, may change interface later
|
|
257
|
+
# it does not say anything on screen
|
|
258
|
+
# @param [String] text of error/warning to put in log
|
|
259
|
+
# @since 1.1.5
|
|
260
|
+
def warn string
|
|
261
|
+
$log.warn string
|
|
262
|
+
Ncurses.beep
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
#def add_item hotkey, label, desc,action
|
|
266
|
+
#
|
|
267
|
+
## A *simple* way of creating menus that will appear in a single row.
|
|
268
|
+
# This copies the menu at the bottom of "most" upon pressing ":".
|
|
269
|
+
# hotkey is the key to invoke an item (a single digit letter)
|
|
270
|
+
#
|
|
271
|
+
# label is an action name
|
|
272
|
+
#
|
|
273
|
+
# desc is a description displayed after an item is chosen. Usually, its like:
|
|
274
|
+
#+ "Folding has been enabled" or "Searches will now be case sensitive"
|
|
275
|
+
#
|
|
276
|
+
# action may be a Proc or a symbol which will be called if item selected
|
|
277
|
+
#+ action may be another menu, so recursive menus can be built, but each
|
|
278
|
+
#+ should fit in a line, its a simple system.
|
|
279
|
+
|
|
280
|
+
CMenuItem = Struct.new( :hotkey, :label, :desc, :action )
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
## An encapsulated form of yesterday's Most Menu
|
|
284
|
+
# It keeps the internals away from the user.
|
|
285
|
+
# Its not really OOP in the sense that the PromptMenu is not a MenuItem. That's how it is in
|
|
286
|
+
# our Menu system, and that led to a lot of painful coding (at least for me). This is quite
|
|
287
|
+
# simple. A submenu contains a PromptMenu in its action object and is evaluated in a switch.
|
|
288
|
+
# A recursive loop handles submenus.
|
|
289
|
+
#
|
|
290
|
+
# Prompting of menu options with suboptions etc.
|
|
291
|
+
# A block of code or symbol or proc is executed for any leaf node
|
|
292
|
+
# This allows us to define different menus for different objects on the screen, and not have to map
|
|
293
|
+
# all kinds of control keys for operations, and have the user remember them. Only one key invokes the menu
|
|
294
|
+
# and the rest are ordinary characters.
|
|
295
|
+
#
|
|
296
|
+
# == Example
|
|
297
|
+
# menu = PromptMenu.new self do
|
|
298
|
+
# item :s, :goto_start
|
|
299
|
+
# item :b, :goto_bottom
|
|
300
|
+
# item :r, :scroll_backward
|
|
301
|
+
# item :l, :scroll_forward
|
|
302
|
+
# submenu :m, "submenu" do
|
|
303
|
+
# item :p, :goto_last_position
|
|
304
|
+
# item :r, :scroll_backward
|
|
305
|
+
# item :l, :scroll_forward
|
|
306
|
+
# end
|
|
307
|
+
# end
|
|
308
|
+
# menu.display @form.window, $error_message_row, $error_message_col, $datacolor #, menu
|
|
309
|
+
|
|
310
|
+
class PromptMenu
|
|
311
|
+
include Io
|
|
312
|
+
attr_reader :text
|
|
313
|
+
attr_reader :options
|
|
314
|
+
def initialize caller, text="Choose:", &block
|
|
315
|
+
@caller = caller
|
|
316
|
+
@text = text
|
|
317
|
+
@options = []
|
|
318
|
+
yield_or_eval &block if block_given?
|
|
319
|
+
end
|
|
320
|
+
def add *menuitem
|
|
321
|
+
item = nil
|
|
322
|
+
case menuitem.first
|
|
323
|
+
when CMenuItem
|
|
324
|
+
item = menuitem.first
|
|
325
|
+
@options << item
|
|
326
|
+
else
|
|
327
|
+
case menuitem.size
|
|
328
|
+
when 4
|
|
329
|
+
item = CMenuItem.new(*menuitem.flatten)
|
|
330
|
+
when 2
|
|
331
|
+
# if user only sends key and symbol
|
|
332
|
+
menuitem[3] = menuitem[1]
|
|
333
|
+
item = CMenuItem.new(*menuitem.flatten)
|
|
334
|
+
when 1
|
|
335
|
+
if menuitem.first.is_a? Action
|
|
336
|
+
item = menuitem.first
|
|
337
|
+
else
|
|
338
|
+
raise ArgumentError, "Don't know how to handle #{menuitem.size} : #{menuitem} "
|
|
339
|
+
end
|
|
340
|
+
else
|
|
341
|
+
raise ArgumentError, "Don't know how to handle #{menuitem.size} : #{menuitem} "
|
|
342
|
+
end
|
|
343
|
+
@options << item
|
|
344
|
+
end
|
|
345
|
+
return item
|
|
346
|
+
end
|
|
347
|
+
alias :item :add
|
|
348
|
+
def create_mitem *args
|
|
349
|
+
item = CMenuItem.new(*args.flatten)
|
|
350
|
+
end
|
|
351
|
+
# Added this, since actually it could have been like this 2011-12-22
|
|
352
|
+
def self.create_menuitem *args
|
|
353
|
+
item = CMenuItem.new(*args.flatten)
|
|
354
|
+
end
|
|
355
|
+
# create the whole thing using a MenuTree which has minimal information.
|
|
356
|
+
# It uses a hotkey and a code only. We are supposed to resolve the display text
|
|
357
|
+
# and actual proc from the caller using this code.
|
|
358
|
+
def menu_tree mt, pm = self
|
|
359
|
+
mt.each_pair { |ch, code|
|
|
360
|
+
if code.is_a? RubyCurses::MenuTree
|
|
361
|
+
item = pm.add(ch, code.value, "")
|
|
362
|
+
current = PromptMenu.new @caller, code.value
|
|
363
|
+
item.action = current
|
|
364
|
+
menu_tree code, current
|
|
365
|
+
else
|
|
366
|
+
item = pm.add(ch, code.to_s, "", code)
|
|
367
|
+
end
|
|
368
|
+
}
|
|
369
|
+
end
|
|
370
|
+
#
|
|
371
|
+
# To allow a more rubyesque way of defining menus and submenus
|
|
372
|
+
def submenu key, label, &block
|
|
373
|
+
item = CMenuItem.new(key, label)
|
|
374
|
+
@options << item
|
|
375
|
+
item.action = PromptMenu.new @caller, label, &block
|
|
376
|
+
end
|
|
377
|
+
#
|
|
378
|
+
# Display prompt_menu in columns using commandwindow
|
|
379
|
+
# This is an improved way of showing the "most" like menu. The earlier
|
|
380
|
+
# format would only print in one row.
|
|
381
|
+
#
|
|
382
|
+
def display_columns config={}
|
|
383
|
+
prompt = config[:prompt] || "Choose: "
|
|
384
|
+
require 'rbhex/core/util/rcommandwindow'
|
|
385
|
+
layout = { :height => 5, :width => Ncurses.COLS-0, :top => Ncurses.LINES-6, :left => 0 }
|
|
386
|
+
rc = CommandWindow.new nil, :layout => layout, :box => true, :title => config[:title] || "Menu"
|
|
387
|
+
w = rc.window
|
|
388
|
+
r = 4
|
|
389
|
+
c = 1
|
|
390
|
+
color = $datacolor
|
|
391
|
+
begin
|
|
392
|
+
menu = @options
|
|
393
|
+
$log.debug " DISP MENU "
|
|
394
|
+
ret = 0
|
|
395
|
+
len = 80
|
|
396
|
+
while true
|
|
397
|
+
h = {}
|
|
398
|
+
valid = []
|
|
399
|
+
labels = []
|
|
400
|
+
menu.each{ |item|
|
|
401
|
+
if item.respond_to? :hotkey
|
|
402
|
+
hk = item.hotkey.to_s
|
|
403
|
+
else
|
|
404
|
+
raise ArgumentError, "Promptmenu needs hotkey or mnemonic"
|
|
405
|
+
end
|
|
406
|
+
# 187compat 2013-03-20 - 19:00 throws up
|
|
407
|
+
labels << "%c. %s " % [ hk.getbyte(0), item.label ]
|
|
408
|
+
h[hk] = item
|
|
409
|
+
valid << hk
|
|
410
|
+
}
|
|
411
|
+
#$log.debug " valid are #{valid} "
|
|
412
|
+
color = $datacolor
|
|
413
|
+
#print_this(win, str, color, r, c)
|
|
414
|
+
rc.display_menu labels, :indexing => :custom
|
|
415
|
+
ch=w.getchar()
|
|
416
|
+
rc.clear
|
|
417
|
+
#$log.debug " got ch #{ch} "
|
|
418
|
+
next if ch < 0 or ch > 255
|
|
419
|
+
if ch == 3 || ch == ?\C-g.getbyte(0)
|
|
420
|
+
clear_this w, r, c, color, len
|
|
421
|
+
print_this(w, "Aborted.", color, r,c)
|
|
422
|
+
break
|
|
423
|
+
end
|
|
424
|
+
ch = ch.chr
|
|
425
|
+
index = valid.index ch
|
|
426
|
+
if index.nil?
|
|
427
|
+
clear_this w, r, c, color, len
|
|
428
|
+
print_this(w, "Not valid. Valid are #{valid}. C-c/C-g to abort.", color, r,c)
|
|
429
|
+
sleep 1
|
|
430
|
+
next
|
|
431
|
+
end
|
|
432
|
+
#$log.debug " index is #{index} "
|
|
433
|
+
item = h[ch]
|
|
434
|
+
# I don;t think this even shows now, its useless
|
|
435
|
+
if item.respond_to? :desc
|
|
436
|
+
desc = item.desc
|
|
437
|
+
#desc ||= "Could not find desc for #{ch} "
|
|
438
|
+
desc ||= ""
|
|
439
|
+
clear_this w, r, c, color, len
|
|
440
|
+
print_this(w, desc, color, r,c)
|
|
441
|
+
end
|
|
442
|
+
action = item.action
|
|
443
|
+
case action
|
|
444
|
+
#when Array
|
|
445
|
+
when PromptMenu
|
|
446
|
+
# submenu
|
|
447
|
+
menu = action.options
|
|
448
|
+
title = rc.title
|
|
449
|
+
rc.title title +" => " + action.text # set title of window to submenu
|
|
450
|
+
when Proc
|
|
451
|
+
ret = action.call
|
|
452
|
+
break
|
|
453
|
+
when Symbol
|
|
454
|
+
if @caller.respond_to?(action, true)
|
|
455
|
+
$log.debug "XXX: IO caller responds to action #{action} "
|
|
456
|
+
ret = @caller.send(action)
|
|
457
|
+
elsif @caller.respond_to?(:execute_this, true)
|
|
458
|
+
ret = @caller.send(:execute_this, action)
|
|
459
|
+
else
|
|
460
|
+
alert "PromptMenu: unidentified action #{action} for #{@caller.class} "
|
|
461
|
+
raise "PromptMenu: unidentified action #{action} for #{@caller.class} "
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
break
|
|
465
|
+
else
|
|
466
|
+
$log.debug " Unidentified flying class #{action.class} "
|
|
467
|
+
break
|
|
468
|
+
end
|
|
469
|
+
end # while
|
|
470
|
+
ensure
|
|
471
|
+
rc.destroy
|
|
472
|
+
rc = nil
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
alias :display_new :display_columns
|
|
476
|
+
|
|
477
|
+
# Display the top level menu and accept user input
|
|
478
|
+
# Calls actions or symbols upon selection, or traverses submenus
|
|
479
|
+
# @return retvalue of last call or send, or 0
|
|
480
|
+
# @param win window
|
|
481
|
+
# @param r, c row and col to display on
|
|
482
|
+
# @param color text color (use $datacolor if in doubt)
|
|
483
|
+
# @see display_new - it presents in a much better manner
|
|
484
|
+
# and is not restricted to one row. Avoid this.
|
|
485
|
+
def display win, r, c, color
|
|
486
|
+
raise "Please use display_new, i've replace this with that"
|
|
487
|
+
# FIXME use a oneline window, user should not have to give all this crap.
|
|
488
|
+
# What about panning if we can;t fit, should we use horiz list to show ?
|
|
489
|
+
menu = @options
|
|
490
|
+
$log.debug " DISP MENU "
|
|
491
|
+
ret = 0
|
|
492
|
+
while true
|
|
493
|
+
str = @text.dup
|
|
494
|
+
h = {}
|
|
495
|
+
valid = []
|
|
496
|
+
menu.each{ |item|
|
|
497
|
+
hk = item.hotkey.to_s
|
|
498
|
+
str << "(%c) %s " % [ hk, item.label ]
|
|
499
|
+
h[hk] = item
|
|
500
|
+
valid << hk
|
|
501
|
+
}
|
|
502
|
+
#$log.debug " valid are #{valid} "
|
|
503
|
+
color = $datacolor
|
|
504
|
+
print_this(win, str, color, r, c)
|
|
505
|
+
ch=win.getchar()
|
|
506
|
+
#$log.debug " got ch #{ch} "
|
|
507
|
+
next if ch < 0 or ch > 255
|
|
508
|
+
if ch == 3 || ch == ?\C-g.getbyte(0)
|
|
509
|
+
clear_this win, r, c, color, str.length
|
|
510
|
+
print_this(win, "Aborted.", color, r,c)
|
|
511
|
+
break
|
|
512
|
+
end
|
|
513
|
+
ch = ch.chr
|
|
514
|
+
index = valid.index ch
|
|
515
|
+
if index.nil?
|
|
516
|
+
clear_this win, r, c, color, str.length
|
|
517
|
+
print_this(win, "Not valid. Valid are #{valid}", color, r,c)
|
|
518
|
+
sleep 1
|
|
519
|
+
next
|
|
520
|
+
end
|
|
521
|
+
#$log.debug " index is #{index} "
|
|
522
|
+
item = h[ch]
|
|
523
|
+
desc = item.desc
|
|
524
|
+
#desc ||= "Could not find desc for #{ch} "
|
|
525
|
+
desc ||= ""
|
|
526
|
+
clear_this win, r, c, color, str.length
|
|
527
|
+
print_this(win, desc, color, r,c)
|
|
528
|
+
action = item.action
|
|
529
|
+
case action
|
|
530
|
+
#when Array
|
|
531
|
+
when PromptMenu
|
|
532
|
+
# submenu
|
|
533
|
+
menu = action.options
|
|
534
|
+
str = "%s: " % action.text
|
|
535
|
+
when Proc
|
|
536
|
+
ret = action.call
|
|
537
|
+
break
|
|
538
|
+
when Symbol
|
|
539
|
+
ret = @caller.send(action)
|
|
540
|
+
break
|
|
541
|
+
else
|
|
542
|
+
$log.debug " Unidentified flying class #{action.class} "
|
|
543
|
+
break
|
|
544
|
+
end
|
|
545
|
+
end # while
|
|
546
|
+
return ret # ret val of last send or call
|
|
547
|
+
end
|
|
548
|
+
end # class PromptMenu
|
|
549
|
+
|
|
550
|
+
### ADD HERE ###
|
|
551
|
+
|
|
552
|
+
end # module
|
|
553
|
+
end # module
|