rbcurse-core 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/README.md +69 -0
  2. data/VERSION +1 -0
  3. data/examples/abasiclist.rb +151 -0
  4. data/examples/alpmenu.rb +46 -0
  5. data/examples/app.sample +17 -0
  6. data/examples/atree.rb +100 -0
  7. data/examples/common/file.rb +45 -0
  8. data/examples/data/README.markdown +9 -0
  9. data/examples/data/brew.txt +38 -0
  10. data/examples/data/color.2 +37 -0
  11. data/examples/data/gemlist.txt +60 -0
  12. data/examples/data/lotr.txt +12 -0
  13. data/examples/data/ports.txt +136 -0
  14. data/examples/data/table.txt +37 -0
  15. data/examples/data/tasks.csv +88 -0
  16. data/examples/data/tasks.txt +27 -0
  17. data/examples/data/todo.txt +10 -0
  18. data/examples/data/todocsv.csv +28 -0
  19. data/examples/data/unix1.txt +21 -0
  20. data/examples/data/unix2.txt +11 -0
  21. data/examples/dbdemo.rb +487 -0
  22. data/examples/dirtree.rb +90 -0
  23. data/examples/newtabbedwindow.rb +100 -0
  24. data/examples/newtesttabp.rb +92 -0
  25. data/examples/tabular.rb +132 -0
  26. data/examples/tasks.rb +167 -0
  27. data/examples/term2.rb +83 -0
  28. data/examples/testkeypress.rb +72 -0
  29. data/examples/testlistbox.rb +158 -0
  30. data/examples/testmessagebox.rb +140 -0
  31. data/examples/testree.rb +106 -0
  32. data/examples/testwsshortcuts.rb +66 -0
  33. data/examples/testwsshortcuts2.rb +127 -0
  34. data/lib/rbcurse.rb +8 -0
  35. data/lib/rbcurse/core/docs/index.txt +73 -0
  36. data/lib/rbcurse/core/include/action.rb +40 -0
  37. data/lib/rbcurse/core/include/appmethods.rb +112 -0
  38. data/lib/rbcurse/core/include/bordertitle.rb +41 -0
  39. data/lib/rbcurse/core/include/chunk.rb +182 -0
  40. data/lib/rbcurse/core/include/io.rb +953 -0
  41. data/lib/rbcurse/core/include/listcellrenderer.rb +140 -0
  42. data/lib/rbcurse/core/include/listeditable.rb +317 -0
  43. data/lib/rbcurse/core/include/listscrollable.rb +590 -0
  44. data/lib/rbcurse/core/include/listselectable.rb +264 -0
  45. data/lib/rbcurse/core/include/multibuffer.rb +83 -0
  46. data/lib/rbcurse/core/include/orderedhash.rb +77 -0
  47. data/lib/rbcurse/core/include/ractionevent.rb +67 -0
  48. data/lib/rbcurse/core/include/rchangeevent.rb +27 -0
  49. data/lib/rbcurse/core/include/rhistory.rb +62 -0
  50. data/lib/rbcurse/core/include/rinputdataevent.rb +47 -0
  51. data/lib/rbcurse/core/include/vieditable.rb +170 -0
  52. data/lib/rbcurse/core/system/colormap.rb +163 -0
  53. data/lib/rbcurse/core/system/keyboard.rb +150 -0
  54. data/lib/rbcurse/core/system/keydefs.rb +30 -0
  55. data/lib/rbcurse/core/system/ncurses.rb +218 -0
  56. data/lib/rbcurse/core/system/panel.rb +162 -0
  57. data/lib/rbcurse/core/system/window.rb +901 -0
  58. data/lib/rbcurse/core/util/ansiparser.rb +117 -0
  59. data/lib/rbcurse/core/util/app.rb +1235 -0
  60. data/lib/rbcurse/core/util/basestack.rb +407 -0
  61. data/lib/rbcurse/core/util/bottomline.rb +1850 -0
  62. data/lib/rbcurse/core/util/colorparser.rb +71 -0
  63. data/lib/rbcurse/core/util/focusmanager.rb +31 -0
  64. data/lib/rbcurse/core/util/padreader.rb +189 -0
  65. data/lib/rbcurse/core/util/rcommandwindow.rb +587 -0
  66. data/lib/rbcurse/core/util/rdialogs.rb +619 -0
  67. data/lib/rbcurse/core/util/viewer.rb +149 -0
  68. data/lib/rbcurse/core/util/widgetshortcuts.rb +505 -0
  69. data/lib/rbcurse/core/widgets/applicationheader.rb +102 -0
  70. data/lib/rbcurse/core/widgets/box.rb +58 -0
  71. data/lib/rbcurse/core/widgets/divider.rb +310 -0
  72. data/lib/rbcurse/core/widgets/keylabelprinter.rb +178 -0
  73. data/lib/rbcurse/core/widgets/rcombo.rb +238 -0
  74. data/lib/rbcurse/core/widgets/rcontainer.rb +415 -0
  75. data/lib/rbcurse/core/widgets/rlink.rb +30 -0
  76. data/lib/rbcurse/core/widgets/rlist.rb +723 -0
  77. data/lib/rbcurse/core/widgets/rmenu.rb +939 -0
  78. data/lib/rbcurse/core/widgets/rmenulink.rb +22 -0
  79. data/lib/rbcurse/core/widgets/rmessagebox.rb +373 -0
  80. data/lib/rbcurse/core/widgets/rprogress.rb +118 -0
  81. data/lib/rbcurse/core/widgets/rtabbedpane.rb +615 -0
  82. data/lib/rbcurse/core/widgets/rtabbedwindow.rb +68 -0
  83. data/lib/rbcurse/core/widgets/rtextarea.rb +920 -0
  84. data/lib/rbcurse/core/widgets/rtextview.rb +780 -0
  85. data/lib/rbcurse/core/widgets/rtree.rb +787 -0
  86. data/lib/rbcurse/core/widgets/rwidget.rb +3040 -0
  87. data/lib/rbcurse/core/widgets/scrollbar.rb +143 -0
  88. data/lib/rbcurse/core/widgets/statusline.rb +94 -0
  89. data/lib/rbcurse/core/widgets/tabular.rb +264 -0
  90. data/lib/rbcurse/core/widgets/tabularwidget.rb +1211 -0
  91. data/lib/rbcurse/core/widgets/textpad.rb +516 -0
  92. data/lib/rbcurse/core/widgets/tree/treecellrenderer.rb +150 -0
  93. data/lib/rbcurse/core/widgets/tree/treemodel.rb +428 -0
  94. metadata +156 -0
@@ -0,0 +1,619 @@
1
+ =begin
2
+ * Name: dialogs so user can do basic stuff in one line.
3
+ * Description:
4
+ * Author: rkumar
5
+
6
+ --------
7
+ * Date: 2008-12-30 12:22
8
+ * 2011-10-1 : moving print_error and print_status methods here as alternatives
9
+ to alert and confirm. Anyone who has included those will get these.
10
+ And this file is included in the base file.
11
+
12
+ Shucks, this file has no module. It's bare !
13
+ * License:
14
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
15
+
16
+ # CHANGES:
17
+ # -- moving to the new Messagebox 2011-11-19 v 1.5.0
18
+ TODO:
19
+ Add select_one (message, values, default)
20
+ =end
21
+ require 'rbcurse/core/widgets/rwidget'
22
+ #require 'rbcurse/deprecated/widgets/rmessagebox'
23
+ require 'rbcurse/core/widgets/rmessagebox'
24
+
25
+ # trying out 2011-12-4 so non-apps can get it.
26
+ require 'rbcurse/core/util/bottomline'
27
+ $tt ||= RubyCurses::Bottomline.new
28
+ $tt.name = "$tt"
29
+ require 'forwardable'
30
+ module Kernel
31
+ extend Forwardable
32
+ def_delegators :$tt, :ask, :say, :agree, :choose, :numbered_menu, :display_text, :display_text_interactive, :display_list, :say_with_pause, :hide_bottomline, :say_with_wait
33
+ end
34
+ # -- moving to the new Messagebox 2011-11-19 v 1.5.0
35
+ # Alert user with a one line message
36
+ #
37
+ def alert text, config={}
38
+
39
+ if text.is_a? RubyCurses::Variable
40
+ text = text.get_value
41
+ end
42
+ _title = config[:title] || "Alert"
43
+ tp = MessageBox.new config do
44
+ title _title
45
+ button_type :ok
46
+ message text
47
+ #text mess
48
+ end
49
+ tp.run
50
+ end
51
+
52
+ # Alert user with a block of text. This will popup a textview in which the user can scroll
53
+ # Use this if you are not sure of the size of the text, such as printing a stack trace,
54
+ # exception
55
+ def textdialog mess, config={}
56
+ config[:title] ||= "Alert"
57
+ tp = MessageBox.new config do
58
+ button_type :ok
59
+ text mess
60
+ end
61
+ tp.run
62
+ end
63
+ #
64
+ # This uses the new messagebox 2011-11-19 v 1.5.0
65
+ # NOTE: The earlier get_string had only an OK button, this seems to have a CANCEL
66
+ # Are we doing anyhting to let caller know, cancel was pressed. FIXME
67
+ # @param [String] a label such as "Enter name:"
68
+ # @return [String] value entered by user
69
+ def get_string label, config={}
70
+ config[:title] ||= "Entry"
71
+ label_config = config[:label_config] || {}
72
+ label_config[:row] ||= 2
73
+ label_config[:col] ||= 2
74
+ label_config[:text] = label
75
+
76
+ field_config = config[:field_config] || {}
77
+ field_config[:row] ||= 3
78
+ field_config[:col] ||= 2
79
+ field_config[:attr] = :reverse
80
+ field_config[:maxlen] ||= config[:maxlen]
81
+ field_config[:display_length] ||= config[:display_length]
82
+ field_config[:default] ||= config[:default]
83
+ field_config[:default] = field_config[:default].chomp if field_config[:default]
84
+ field_config[:name] = :name
85
+ #field_config[:display_length] ||= 50 # i want it to extend since i don't know the actual width
86
+ #field_config[:width] ||= 50 # i want it to extend since i don't know the actual width
87
+ field_config[:width] ||= (field_config[:display_length] || 50)
88
+
89
+ defwid = config[:default].nil? ? 30 : config[:default].size + 13
90
+ w = [label.size + 8, defwid, field_config[:width]+13 ].max
91
+ config[:width] ||= w
92
+ $log.debug "XXX: FIELD SIZE #{w} "
93
+ $log.debug "XXX: FIELD CONFIG #{field_config} "
94
+ tp = MessageBox.new config do
95
+ button_type :ok_cancel
96
+ default_button 0
97
+ item Label.new nil, label_config
98
+ item Field.new nil, field_config
99
+ end
100
+ index = tp.run
101
+ if index == 0 # OK
102
+ return tp.form.by_name[:name].text
103
+ else # CANCEL
104
+ # Should i use nil or blank. I am currently opting for nil, as this may imply to caller
105
+ # that user does not wish to override whatever value is being prompted for.
106
+ return nil
107
+ end
108
+ end
109
+ # new version using new messagebox
110
+ # @param [String] question
111
+ # @return [Boolean] true or false
112
+ # FIXME focus hould fall on default button so ENTER does not fire first one.
113
+ def confirm text, config={}, &block
114
+ title = config['title'] || "Confirm"
115
+ config[:default_button] ||= 0
116
+ #instance_eval &block if block_given?
117
+ mb = RubyCurses::MessageBox.new config do
118
+ title title
119
+ message text
120
+ button_type :yes_no
121
+ end
122
+ index = mb.run
123
+ return index == 0
124
+ end
125
+ ##
126
+ # pops up a modal box with a message and an OK button.
127
+ # No return value.
128
+ # Usage:
129
+ # alert("You did not enter anything!")
130
+ # alert("You did not enter anything!", "title"=>"Wake Up")
131
+ # alert("You did not enter anything!", {"title"=>"Wake Up", "bgcolor"=>"blue", "color"=>"white"})
132
+ # block currently ignored. don't know what to do, can't pass it to MB since alread sending in a block
133
+ #
134
+ def DEPalert text, config={}, &block
135
+ title = config['title'] || "Alert"
136
+ #instance_eval &block if block_given?
137
+ if text.is_a? RubyCurses::Variable # added 2011-09-20 incase variable passed
138
+ text = text.get_value
139
+ end
140
+ mb = RubyCurses::MessageBox.new nil, config do
141
+ title title
142
+ message text
143
+ button_type :ok
144
+ end
145
+ end
146
+ # confirms from user returning :YES or :NO
147
+ # Darn, should have returned boolean, now have to live with it.
148
+ def OLDconfirm text, config={}, &block
149
+ title = config['title'] || "Confirm"
150
+ #instance_eval &block if block_given?
151
+ mb = RubyCurses::MessageBox.new nil, config do
152
+ title title
153
+ message text
154
+ button_type :yes_no
155
+ end
156
+ return mb.selected_index == 0 ? :YES : :NO
157
+ end
158
+
159
+ ##
160
+ # allows user entry of a string.
161
+ # In config you may pass Field related properties such as chars_allowed, valid_regex, values, etc.
162
+ def DEPget_string(message, len=50, default="", config={})
163
+
164
+ config["input_config"] = {}
165
+ config["input_config"]["maxlen"] = len
166
+ config["maxlen"]=len
167
+ title = config["title"] || "Input required"
168
+ mb = RubyCurses::MessageBox.new nil, config do
169
+ title title
170
+ message message
171
+ type :input
172
+ button_type :ok
173
+ default_value default
174
+ end
175
+ return mb.input_value
176
+ end
177
+
178
+ ##
179
+ # Added 2009-02-05 13:16
180
+ # get a string from user with some additional checkboxes and optionally supply default values
181
+ # Usage:
182
+ #sel, inp, hash = get_string_with_options("Enter a filter pattern", 20, "*", {"checkboxes" => ["case sensitive","reverse"], "checkbox_defaults"=>[true, false]})
183
+ # sel, inp, hash = get_string_with_options("Enter a filter pattern", 20, "*", {"checkboxes" => ["case sensitive","reverse"]})
184
+ # $log.debug " POPUP: #{sel}: #{inp}, #{hash['case sensitive']}, #{hash['reverse']}"
185
+ #
186
+ # @param: message to print,
187
+ # @param: length of entry field
188
+ # @param: default value of field
189
+ # @param: configuration of box or field
190
+ # checkboxes: array of strings to use as checkboxes
191
+ # checkbox_defaults : array of true/false default values for each cb
192
+ # @return: int 0 OK, 1 cancel pressed
193
+ # @return: string value entered
194
+ # @return: hash of strings and booleans for checkboxes and values
195
+ #
196
+ # @deprecated - user should be able to do this quite easily now.
197
+ def TODOget_string_with_options(message, len=20, default="", config={})
198
+ title = config["title"] || "Input required"
199
+ input_config = config["input_config"] || {}
200
+ checks = config["checkboxes"]
201
+ checkbox_defaults = config["checkbox_defaults"] || []
202
+
203
+ height = config["height"] || 1
204
+ display_length = config["display_length"] || 30
205
+
206
+ r = 3
207
+ c = 4
208
+ mform = RubyCurses::Form.new nil
209
+ message_label = RubyCurses::Label.new mform, {'text' => message, "name"=>"message_label","row" => r, "col" => c, "display_length" => display_length, "height" => height, "attr"=>"reverse"}
210
+
211
+ r += 1
212
+ input = RubyCurses::Field.new mform, input_config do
213
+ name "input"
214
+ row r
215
+ col c
216
+ display_length display_length
217
+ maxlen len
218
+ set_buffer default
219
+ end
220
+ if !checks.nil?
221
+ r += 2
222
+ checks.each_with_index do |cbtext,ix|
223
+ field = RubyCurses::CheckBox.new mform do
224
+ text cbtext
225
+ name cbtext
226
+ value checkbox_defaults[ix]||false
227
+ color 'black'
228
+ bgcolor 'white'
229
+ row r
230
+ col c
231
+ end
232
+ r += 1
233
+ end
234
+ end
235
+ radios = config["radiobuttons"]
236
+ if !radios.nil?
237
+ radio_default = config["radio_default"] || radios[0]
238
+ radio = RubyCurses::Variable.new radio_default
239
+ r += 2
240
+ radios.each_with_index do |cbtext,ix|
241
+ field = RubyCurses::RadioButton.new mform do
242
+ variable radio
243
+ text cbtext
244
+ value cbtext
245
+ color 'black'
246
+ bgcolor 'white'
247
+ row r
248
+ col c
249
+ end
250
+ r += 1
251
+ end
252
+ end
253
+ mb = RubyCurses::MessageBox.new mform do
254
+ title title
255
+ button_type :ok_cancel
256
+ default_button 0
257
+ end
258
+ hash = {}
259
+ if !checks.nil?
260
+ checks.each do |c|
261
+ hash[c] = mform.by_name[c].getvalue
262
+ end
263
+ end
264
+ hash["radio"] = radio.get_value unless radio.nil?
265
+ # returns button index (0 = OK), value of field, hash containing values of checkboxes
266
+ return mb.selected_index, mform.by_name['input'].getvalue, hash
267
+ end
268
+
269
+ # ------------------------ We've Moved here from window class ---------------- #
270
+ # #
271
+ # Moving some methods from window. They no longer require having a window. #
272
+ # #
273
+ # ---------------------------------------------------------------------------- #
274
+ #
275
+ #
276
+
277
+ # new version with a window created on 2011-10-1 12:37 AM
278
+ # Now can be separate from window class, needing nothing, just a util class
279
+ # prints a status message and pauses for a char
280
+ def print_status_message text, aconfig={}, &block
281
+ _print_message :status, text, aconfig, &block
282
+ end
283
+ # new version with a window created on 2011-10-1 12:30 AM
284
+ # Now can be separate from window class, needing nothing, just a util class
285
+ # Why are we dealing with $error_message, that was due to old idea which failed
286
+ # scrap it and send the message.
287
+ def print_error_message text, aconfig={}, &block
288
+ _print_message :error, text, aconfig, &block
289
+ end
290
+ def _create_footer_window h = 2 , w = Ncurses.COLS, t = Ncurses.LINES-2, l = 0
291
+ ewin = VER::Window.new(h, w , t, l)
292
+ end
293
+ # @param [:symbol] :error or :status kind of message
294
+ # @private
295
+ def _print_message type, text, aconfig={}, &block
296
+ case text
297
+ when RubyCurses::Variable # added 2011-09-20 incase variable passed
298
+ text = text.get_value
299
+ when Exception
300
+ text = text.to_s
301
+ end
302
+ # NOTE we are polluting global namespace
303
+ aconfig.each_pair { |k,v| instance_variable_set("@#{k}",v) }
304
+ ewin = _create_footer_window #*@layout
305
+ r = 0; c = 1;
306
+ case type
307
+ when :error
308
+ @color ||= 'red'
309
+ @bgcolor ||= 'black'
310
+ else
311
+ @color ||= :white
312
+ @bgcolor ||= :black
313
+ end
314
+ color_pair = get_color($promptcolor, @color, @bgcolor)
315
+ ewin.bkgd(Ncurses.COLOR_PAIR(color_pair));
316
+ ewin.printstring r, c, text, color_pair
317
+ ewin.printstring r+1, c, "Press a key", color_pair
318
+ ewin.wrefresh
319
+ ewin.getchar
320
+ ewin.destroy
321
+ end
322
+ #
323
+ # Alternative to confirm dialog, if you want this look and feel, at last 2 lines of screen
324
+ # @param [String] text to prompt
325
+ # @return [true, false] 'y' is true, all else if false
326
+ def confirm_window text, aconfig={}, &block
327
+ case text
328
+ when RubyCurses::Variable # added 2011-09-20 incase variable passed
329
+ text = text.get_value
330
+ when Exception
331
+ text = text.to_s
332
+ end
333
+ ewin = _create_footer_window
334
+ r = 0; c = 1;
335
+ aconfig.each_pair { |k,v| instance_variable_set("@#{k}",v) }
336
+ @color ||= :white
337
+ @bgcolor ||= :black
338
+ color_pair = get_color($promptcolor, @color, @bgcolor)
339
+ ewin.bkgd(Ncurses.COLOR_PAIR(color_pair));
340
+ ewin.printstring r, c, text, color_pair
341
+ ewin.printstring r+1, c, "[y/n]", color_pair
342
+ ewin.wrefresh
343
+ #retval = :NO # consistent with confirm # CHANGE TO TRUE FALSE NOW
344
+ retval = false
345
+ begin
346
+ ch = ewin.getchar
347
+ #retval = :YES if ch.chr == 'y'
348
+ retval = (ch.chr == 'y' )
349
+ ensure
350
+ ewin.destroy
351
+ end
352
+ retval
353
+ end
354
+ # class created to display multiple messages without asking for user to hit a key
355
+ # returns a window to which one can keep calling printstring with 0 or 1 as row.
356
+ # destroy when finished.
357
+ # Also, one can pause if one wants, or linger.
358
+ # This is meant to be a replacement for the message_immediate and message_raw
359
+ # I was trying out in App.rb. 2011-10-1 1:27 AM
360
+ # Testing from test2.rb
361
+ # TODO: add option of putting progress_bar
362
+ class StatusWindow
363
+ attr_reader :h, :w, :top, :left # height, width, top row, left col of window
364
+ attr_reader :win
365
+ attr_accessor :color_pair
366
+ def initialize config={}, &block
367
+ @color_pair = config[:color_pair]
368
+ @row_offset = config[:row_offset] || 0
369
+ @col_offset = config[:col_offset] || 0
370
+ create_window *config[:layout]
371
+ end
372
+ def create_window h = 2 , w = Ncurses.COLS-0, t = Ncurses.LINES-2, l = 0
373
+ return @win if @win
374
+ @win = VER::Window.new(h, w , t, l)
375
+ @h = h ; @w = w; @top = t ; @left = l
376
+ @color_pair ||= get_color($promptcolor, 'white','black')
377
+ @win.bkgd(Ncurses.COLOR_PAIR(@color_pair));
378
+ @win
379
+ end
380
+ # creates a color pair based on given bg and fg colors as strings
381
+ #def set_colors bgcolor, fgcolor='white'
382
+ #@color_pair = get_color($datacolor, 'white','black')
383
+ #end
384
+ # prints a string on given row (0 or 1)
385
+ def printstring r, c, text, color_pair=@color_pair
386
+ create_window unless @win
387
+ show unless @visible
388
+ r = @h-1 if r > @h-1
389
+ #@win.printstring r, c, ' '*@w, @color_pair
390
+ # FIXME this padding overwrites the border and the offset means next line wiped
391
+ # However, now it may now totally clear a long line.
392
+ @win.printstring r+@row_offset, c+@col_offset, "%-*s" % [@w-(@col_offset*2)-c, text], color_pair
393
+ @win.wrefresh
394
+ end
395
+ # print given strings from first first column onwards
396
+ def print *textarray
397
+ create_window unless @win
398
+ show unless @visible
399
+ c = 1
400
+ textarray.each_with_index { |s, i|
401
+ @win.printstring i+@row_offset, c+@col_offset, "%-*s" % [@w-(@col_offset*2)-c, s], @color_pair
402
+ }
403
+ @win.wrefresh
404
+ end
405
+ def pause; @win.getchar; end
406
+ # pauses with the message, but doesn't ask the user to press a key.
407
+ # If he does, the key should be used by underlying window.
408
+ # Do not call destroy if you call linger, it does the destroy.
409
+ def linger caller_window=nil
410
+ begin
411
+ if caller_window
412
+ ch = @win.getchar
413
+ caller_window.ungetch(ch) # will this be available to underlying window XXX i think not !!
414
+ else
415
+ sleep 1
416
+ end
417
+ ensure
418
+ destroy
419
+ end
420
+ end
421
+ # caller must destroy after he's finished printing messages, unless
422
+ # user calls linger
423
+ def destroy; @win.destroy if @win; @win = nil; end
424
+ def hide
425
+ @win.hide
426
+ @visible = false
427
+ end
428
+ def show
429
+ @win.show unless @visible
430
+ @visible = true
431
+ end
432
+ end
433
+ # returns instance of a status_window for sending multiple
434
+ # statuses during some process
435
+ def status_window aconfig={}, &block
436
+ return StatusWindow.new aconfig
437
+ end
438
+ # this is a popup dialog box on which statuses can be printed as a process is taking place.
439
+ # I am reusing StatusWindow and so there's an issue since I've put a box, so in clearing
440
+ # the line, I might overwrite the box
441
+ def progress_dialog aconfig={}, &block
442
+ aconfig[:layout] = [10,60,10,20]
443
+ window = status_window aconfig
444
+ height = 10; width = 60
445
+ window.win.print_border_mb 1,2, height, width, $normalcolor, FFI::NCurses::A_REVERSE
446
+ return window
447
+ end
448
+ #
449
+ # Display a popup and return the seliected index from list
450
+ # Config includes row and col and title of window
451
+ # You may also pass bgcolor and color
452
+ # @since 1.4.1 2011-11-1
453
+ def popuplist list, config={}, &block
454
+ require 'rbcurse/core/widgets/rlist'
455
+
456
+ max_visible_items = config[:max_visible_items]
457
+ row = config[:row] || 5
458
+ col = config[:col] || 5
459
+ relative_to = config[:relative_to]
460
+ if relative_to
461
+ layout = relative_to.form.window.layout
462
+ row += layout[:top]
463
+ col += layout[:left]
464
+ end
465
+ config.delete :relative_to
466
+ width = config[:width] || longest_in_list(list)+2 # borders take 2
467
+ height = config[:height]
468
+ height ||= [max_visible_items || 10+2, list.length+2].min
469
+ #layout(1+height, width+4, row, col)
470
+ layout = { :height => 0+height, :width => 0+width, :top => row, :left => col }
471
+ window = VER::Window.new(layout)
472
+ form = RubyCurses::Form.new window
473
+
474
+ listconfig = config[:listconfig] || {}
475
+ listconfig[:list] = list
476
+ listconfig[:width] = width
477
+ listconfig[:height] = height
478
+ listconfig[:selection_mode] ||= :single
479
+ listconfig.merge!(config)
480
+ listconfig.delete(:row);
481
+ listconfig.delete(:col);
482
+ # trying to pass populists block to listbox
483
+ lb = RubyCurses::List.new form, listconfig, &block
484
+ #
485
+ # added next line so caller can configure listbox with
486
+ # events such as ENTER_ROW, LEAVE_ROW or LIST_SELECTION_EVENT or PRESS
487
+ # 2011-11-11
488
+ #yield lb if block_given? # No it won't work since this returns
489
+ window.bkgd(Ncurses.COLOR_PAIR($reversecolor));
490
+ window.wrefresh
491
+ Ncurses::Panel.update_panels
492
+ form.repaint
493
+ window.wrefresh
494
+ begin
495
+ while((ch = window.getchar()) != 999 )
496
+ case ch
497
+ when -1
498
+ next
499
+ when ?\C-q.getbyte(0)
500
+ break
501
+ else
502
+ lb.handle_key ch
503
+ form.repaint
504
+ if ch == 13 || ch == 10
505
+ return lb.current_index if lb.selection_mode != :multiple
506
+
507
+ x = lb.selected_indices
508
+ return x if x
509
+ x = lb.current_index unless x
510
+ return [x]
511
+ # if multiple selection, then return list of selected_indices and don't catch 32
512
+ elsif ch == 32 # if single selection
513
+ return lb.current_index if lb.selection_mode != :multiple
514
+ end
515
+ #yield ch if block_given?
516
+ end
517
+ end
518
+ ensure
519
+ window.destroy
520
+ end
521
+ return nil
522
+ end
523
+ # returns length of longest
524
+ def longest_in_list list #:nodoc:
525
+ longest = list.inject(0) do |memo,word|
526
+ memo >= word.length ? memo : word.length
527
+ end
528
+ longest
529
+ end
530
+ def install_help_text text
531
+ @_help_text = text
532
+ end
533
+ # this routine prints help_text for an application
534
+ # If help_text has been set using install_help_text
535
+ # it will be displayed. Else, general help will be
536
+ # displayed. Even when custom help is displayed,
537
+ # user may use <next> to see general help.
538
+ #
539
+ # earlier in app.rb
540
+ def display_app_help
541
+ filename = File.dirname(__FILE__) + "/../docs/index.txt"
542
+ # defarr contains default help
543
+ if File.exists?(filename)
544
+ defarr = File.open(filename,'r').readlines
545
+ else
546
+ arr = []
547
+ arr << " NO HELP SPECIFIED FOR APP "
548
+ arr << " "
549
+ arr << " --- General help --- "
550
+ arr << " F10 - exit application "
551
+ arr << " Alt-x - select commands "
552
+ arr << " : - select commands "
553
+ arr << " "
554
+ defarr = arr
555
+ end
556
+ defhelp = true
557
+ if respond_to? :help_text
558
+ arr = help_text
559
+ defhelp = false
560
+ elsif @_help_text
561
+ arr = @_help_text
562
+ defhelp = false
563
+ else
564
+ arr = defarr
565
+ end
566
+ case arr
567
+ when String
568
+ arr = arr.split("\n")
569
+ when Array
570
+ end
571
+ #w = arr.max_by(&:length).length
572
+ h = FFI::NCurses.LINES - 4
573
+ w = FFI::NCurses.COLS - 10
574
+
575
+ require 'rbcurse/core/util/viewer'
576
+ RubyCurses::Viewer.view(arr, :layout => [2, 4, h, w],:close_key => KEY_F10, :title => "[ Help ]", :print_footer => true) do |t|
577
+ # you may configure textview further here.
578
+ #t.suppress_borders true
579
+ #t.color = :black
580
+ #t.bgcolor = :white
581
+ # or
582
+ #t.attr = :reverse
583
+
584
+ # help was provided, so default help is provided in second buffer
585
+ unless defhelp
586
+ t.add_content defarr, :title => ' General Help '
587
+ end
588
+ end
589
+ end
590
+ #
591
+ =begin
592
+ http://www.kammerl.de/ascii/AsciiSignature.php
593
+ ___
594
+ |__ \
595
+ ) |
596
+ / /
597
+ |_|
598
+ (_)
599
+
600
+ _
601
+ | |
602
+ | |
603
+ | |
604
+ |_|
605
+ (_)
606
+
607
+
608
+ _____ _ _____
609
+ | __ \ | | / ____|
610
+ | |__) | _| |__ _ _ | | _ _ _ __ ___ ___ ___
611
+ | _ / | | | '_ \| | | | | | | | | | '__/ __|/ _ \/ __|
612
+ | | \ \ |_| | |_) | |_| | | |___| |_| | | \__ \ __/\__ \
613
+ |_| \_\__,_|_.__/ \__, | \_____\__,_|_| |___/\___||___/
614
+ __/ |
615
+ |___/
616
+
617
+ =end
618
+
619
+