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.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/CHANGELOG +2000 -0
  4. data/LICENSE +56 -0
  5. data/README.md +44 -0
  6. data/examples/abasiclist.rb +179 -0
  7. data/examples/alpmenu.rb +50 -0
  8. data/examples/app.sample +19 -0
  9. data/examples/atree.rb +100 -0
  10. data/examples/bline.rb +136 -0
  11. data/examples/common/file.rb +45 -0
  12. data/examples/data/README.markdown +9 -0
  13. data/examples/data/brew.txt +38 -0
  14. data/examples/data/color.2 +37 -0
  15. data/examples/data/gemlist.txt +60 -0
  16. data/examples/data/lotr.txt +12 -0
  17. data/examples/data/ports.txt +136 -0
  18. data/examples/data/table.txt +37 -0
  19. data/examples/data/tasks.csv +88 -0
  20. data/examples/data/tasks.txt +27 -0
  21. data/examples/data/todo.txt +10 -0
  22. data/examples/data/todo.txt.bak +10 -0
  23. data/examples/data/todocsv.csv +28 -0
  24. data/examples/data/unix1.txt +21 -0
  25. data/examples/data/unix2.txt +11 -0
  26. data/examples/dbdemo.rb +502 -0
  27. data/examples/dirtree.rb +94 -0
  28. data/examples/newtabbedwindow.rb +100 -0
  29. data/examples/newtesttabp.rb +92 -0
  30. data/examples/tabular.rb +146 -0
  31. data/examples/tasks.rb +178 -0
  32. data/examples/term2.rb +84 -0
  33. data/examples/testbuttons.rb +296 -0
  34. data/examples/testcombo.rb +102 -0
  35. data/examples/testfields.rb +195 -0
  36. data/examples/testkeypress.rb +72 -0
  37. data/examples/testlistbox.rb +170 -0
  38. data/examples/testmessagebox.rb +140 -0
  39. data/examples/testprogress.rb +116 -0
  40. data/examples/testree.rb +106 -0
  41. data/examples/testwsshortcuts.rb +66 -0
  42. data/examples/testwsshortcuts2.rb +128 -0
  43. data/lib/rbhex.rb +6 -0
  44. data/lib/rbhex/core/docs/index.txt +73 -0
  45. data/lib/rbhex/core/include/action.rb +80 -0
  46. data/lib/rbhex/core/include/actionmanager.rb +49 -0
  47. data/lib/rbhex/core/include/appmethods.rb +214 -0
  48. data/lib/rbhex/core/include/bordertitle.rb +48 -0
  49. data/lib/rbhex/core/include/chunk.rb +203 -0
  50. data/lib/rbhex/core/include/io.rb +553 -0
  51. data/lib/rbhex/core/include/listbindings.rb +74 -0
  52. data/lib/rbhex/core/include/listcellrenderer.rb +140 -0
  53. data/lib/rbhex/core/include/listeditable.rb +317 -0
  54. data/lib/rbhex/core/include/listscrollable.rb +663 -0
  55. data/lib/rbhex/core/include/listselectable.rb +271 -0
  56. data/lib/rbhex/core/include/multibuffer.rb +83 -0
  57. data/lib/rbhex/core/include/orderedhash.rb +77 -0
  58. data/lib/rbhex/core/include/ractionevent.rb +73 -0
  59. data/lib/rbhex/core/include/rchangeevent.rb +27 -0
  60. data/lib/rbhex/core/include/rhistory.rb +95 -0
  61. data/lib/rbhex/core/include/rinputdataevent.rb +47 -0
  62. data/lib/rbhex/core/include/vieditable.rb +172 -0
  63. data/lib/rbhex/core/include/widgetmenu.rb +66 -0
  64. data/lib/rbhex/core/system/colormap.rb +165 -0
  65. data/lib/rbhex/core/system/keyboard.rb +150 -0
  66. data/lib/rbhex/core/system/keydefs.rb +30 -0
  67. data/lib/rbhex/core/system/ncurses.rb +236 -0
  68. data/lib/rbhex/core/system/panel.rb +162 -0
  69. data/lib/rbhex/core/system/window.rb +913 -0
  70. data/lib/rbhex/core/util/ansiparser.rb +119 -0
  71. data/lib/rbhex/core/util/app.rb +1228 -0
  72. data/lib/rbhex/core/util/basestack.rb +410 -0
  73. data/lib/rbhex/core/util/bottomline.rb +1859 -0
  74. data/lib/rbhex/core/util/colorparser.rb +77 -0
  75. data/lib/rbhex/core/util/focusmanager.rb +31 -0
  76. data/lib/rbhex/core/util/padreader.rb +192 -0
  77. data/lib/rbhex/core/util/rcommandwindow.rb +604 -0
  78. data/lib/rbhex/core/util/rdialogs.rb +574 -0
  79. data/lib/rbhex/core/util/viewer.rb +149 -0
  80. data/lib/rbhex/core/util/widgetshortcuts.rb +506 -0
  81. data/lib/rbhex/core/version.rb +5 -0
  82. data/lib/rbhex/core/widgets/applicationheader.rb +103 -0
  83. data/lib/rbhex/core/widgets/box.rb +58 -0
  84. data/lib/rbhex/core/widgets/divider.rb +310 -0
  85. data/lib/rbhex/core/widgets/keylabelprinter.rb +194 -0
  86. data/lib/rbhex/core/widgets/rcombo.rb +253 -0
  87. data/lib/rbhex/core/widgets/rcontainer.rb +415 -0
  88. data/lib/rbhex/core/widgets/rlink.rb +30 -0
  89. data/lib/rbhex/core/widgets/rlist.rb +696 -0
  90. data/lib/rbhex/core/widgets/rmenu.rb +958 -0
  91. data/lib/rbhex/core/widgets/rmenulink.rb +22 -0
  92. data/lib/rbhex/core/widgets/rmessagebox.rb +387 -0
  93. data/lib/rbhex/core/widgets/rprogress.rb +118 -0
  94. data/lib/rbhex/core/widgets/rtabbedpane.rb +634 -0
  95. data/lib/rbhex/core/widgets/rtabbedwindow.rb +70 -0
  96. data/lib/rbhex/core/widgets/rtextarea.rb +960 -0
  97. data/lib/rbhex/core/widgets/rtextview.rb +739 -0
  98. data/lib/rbhex/core/widgets/rtree.rb +768 -0
  99. data/lib/rbhex/core/widgets/rwidget.rb +3277 -0
  100. data/lib/rbhex/core/widgets/scrollbar.rb +143 -0
  101. data/lib/rbhex/core/widgets/statusline.rb +113 -0
  102. data/lib/rbhex/core/widgets/tabular.rb +264 -0
  103. data/lib/rbhex/core/widgets/tabularwidget.rb +1142 -0
  104. data/lib/rbhex/core/widgets/textpad.rb +995 -0
  105. data/lib/rbhex/core/widgets/tree/treecellrenderer.rb +150 -0
  106. data/lib/rbhex/core/widgets/tree/treemodel.rb +428 -0
  107. data/rbhex-core.gemspec +32 -0
  108. 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