rbcurse 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/CHANGELOG +33 -0
  2. data/README.markdown +7 -1
  3. data/TODO2.txt +21 -15
  4. data/VERSION +1 -1
  5. data/examples/abasiclist.rb +2 -2
  6. data/examples/alpmenu.rb +1 -1
  7. data/examples/app.rb +0 -1
  8. data/examples/appdirtree.rb +4 -2
  9. data/examples/appemail.rb +7 -3
  10. data/examples/appemaillb.rb +1 -1
  11. data/examples/appgcompose.rb +2 -2
  12. data/examples/appgmail.rb +1 -1
  13. data/examples/appmethods.rb +20 -2
  14. data/examples/atree.rb +9 -1
  15. data/examples/dbdemo.rb +460 -0
  16. data/examples/dirtree.rb +1 -1
  17. data/examples/menu1.rb +37 -5
  18. data/examples/multispl.rb +1 -1
  19. data/examples/rfe.rb +9 -2
  20. data/examples/splitp.rb +1 -1
  21. data/examples/sqlc.rb +6 -10
  22. data/examples/sqlm.rb +2 -20
  23. data/examples/sqlt.rb +408 -0
  24. data/examples/term2.rb +1 -1
  25. data/examples/test2.rb +169 -97
  26. data/examples/testapp.rb +1 -1
  27. data/examples/testapp2.rb +1 -1
  28. data/examples/testkeypress.rb +4 -2
  29. data/examples/testtable.rb +6 -0
  30. data/examples/testtpane.rb +35 -23
  31. data/examples/testvimsplit.rb +3 -2
  32. data/lib/rbcurse.rb +1 -1
  33. data/lib/rbcurse/action.rb +8 -0
  34. data/lib/rbcurse/app.rb +39 -23
  35. data/lib/rbcurse/extras/bottomline.rb +101 -13
  36. data/lib/rbcurse/extras/directorylist.rb +14 -5
  37. data/lib/rbcurse/extras/divider.rb +1 -1
  38. data/lib/rbcurse/extras/listselectable.rb +42 -8
  39. data/lib/rbcurse/extras/masterdetail.rb +2 -2
  40. data/lib/rbcurse/extras/scrollbar.rb +11 -2
  41. data/lib/rbcurse/extras/statusline.rb +56 -0
  42. data/lib/rbcurse/extras/stdscrwindow.rb +11 -0
  43. data/lib/rbcurse/extras/tabular.rb +2 -1
  44. data/lib/rbcurse/extras/tabularwidget.rb +60 -17
  45. data/lib/rbcurse/extras/viewer.rb +16 -4
  46. data/lib/rbcurse/keylabelprinter.rb +34 -4
  47. data/lib/rbcurse/listeditable.rb +5 -1
  48. data/lib/rbcurse/listkeys.rb +1 -1
  49. data/lib/rbcurse/listscrollable.rb +15 -8
  50. data/lib/rbcurse/rbasiclistbox.rb +44 -23
  51. data/lib/rbcurse/rcommandwindow.rb +8 -14
  52. data/lib/rbcurse/rdialogs.rb +187 -2
  53. data/lib/rbcurse/rlistbox.rb +38 -19
  54. data/lib/rbcurse/rmenu.rb +313 -93
  55. data/lib/rbcurse/rmessagebox.rb +3 -2
  56. data/lib/rbcurse/rmulticontainer.rb +5 -3
  57. data/lib/rbcurse/rmultisplit.rb +2 -11
  58. data/lib/rbcurse/rmultitextview.rb +4 -5
  59. data/lib/rbcurse/rtabbedpane.rb +223 -69
  60. data/lib/rbcurse/rtable.rb +6 -10
  61. data/lib/rbcurse/rtextarea.rb +57 -36
  62. data/lib/rbcurse/rtextview.rb +12 -15
  63. data/lib/rbcurse/rtree.rb +79 -22
  64. data/lib/rbcurse/rvimsplit.rb +16 -25
  65. data/lib/rbcurse/rwidget.rb +376 -523
  66. data/lib/rbcurse/tree/treecellrenderer.rb +24 -11
  67. data/lib/rbcurse/tree/treemodel.rb +1 -1
  68. data/lib/ver/window.rb +130 -66
  69. metadata +5 -3
  70. data/examples/term.rb +0 -48
@@ -5,6 +5,11 @@
5
5
 
6
6
  --------
7
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 !
8
13
  * License:
9
14
  Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
15
 
@@ -12,8 +17,6 @@ TODO:
12
17
  Add one get_string(message, len, regex ...)
13
18
  Add select_one (message, values, default)
14
19
  =end
15
- require 'rubygems'
16
- ##require 'ncurses'
17
20
  require 'logger'
18
21
  require 'rbcurse/rwidget'
19
22
  require 'rbcurse/rmessagebox'
@@ -26,6 +29,7 @@ require 'rbcurse/rmessagebox'
26
29
  # alert("You did not enter anything!", "title"=>"Wake Up")
27
30
  # alert("You did not enter anything!", {"title"=>"Wake Up", "bgcolor"=>"blue", "color"=>"white"})
28
31
  # block currently ignored. don't know what to do, can't pass it to MB since alread sending in a block
32
+ #
29
33
  def alert text, config={}, &block
30
34
  title = config['title'] || "Alert"
31
35
  #instance_eval &block if block_given?
@@ -38,6 +42,8 @@ def alert text, config={}, &block
38
42
  button_type :ok
39
43
  end
40
44
  end
45
+ # confirms from user returning :YES or :NO
46
+ # Darn, should have returned boolean, now have to live with it.
41
47
  def confirm text, config={}, &block
42
48
  title = config['title'] || "Confirm"
43
49
  #instance_eval &block if block_given?
@@ -158,6 +164,185 @@ def get_string_with_options(message, len=20, default="", config={})
158
164
  return mb.selected_index, mform.by_name['input'].getvalue, hash
159
165
  end
160
166
 
167
+ # ------------------------ We've Moved here from window class ---------------- #
168
+ # #
169
+ # Moving some methods from window. They no longer require having a window. #
170
+ # #
171
+ # ---------------------------------------------------------------------------- #
172
+ #
173
+ #
174
+
175
+ # new version with a window created on 2011-10-1 12:37 AM
176
+ # Now can be separate from window class, needing nothing, just a util class
177
+ # prints a status message and pauses for a char
178
+ def print_status_message text, aconfig={}, &block
179
+ _print_message :status, text, aconfig, &block
180
+ end
181
+ # new version with a window created on 2011-10-1 12:30 AM
182
+ # Now can be separate from window class, needing nothing, just a util class
183
+ # Why are we dealing with $error_message, that was due to old idea which failed
184
+ # scrap it and send the message.
185
+ def print_error_message text, aconfig={}, &block
186
+ _print_message :error, text, aconfig, &block
187
+ end
188
+ def _create_footer_window h = 2 , w = Ncurses.COLS, t = Ncurses.LINES-2, l = 0
189
+ ewin = VER::Window.new(h, w , t, l)
190
+ end
191
+ # @param [:symbol] :error or :status kind of message
192
+ # @private
193
+ def _print_message type, text, aconfig={}, &block
194
+ case text
195
+ when RubyCurses::Variable # added 2011-09-20 incase variable passed
196
+ text = text.get_value
197
+ when Exception
198
+ text = text.to_s
199
+ end
200
+ # NOTE we are polluting global namespace
201
+ aconfig.each_pair { |k,v| instance_variable_set("@#{k}",v) }
202
+ ewin = _create_footer_window #*@layout
203
+ r = 0; c = 1;
204
+ case type
205
+ when :error
206
+ @color ||= 'red'
207
+ @bgcolor ||= 'black'
208
+ else
209
+ @color ||= :white
210
+ @bgcolor ||= :black
211
+ end
212
+ color_pair = get_color($promptcolor, @color, @bgcolor)
213
+ ewin.bkgd(Ncurses.COLOR_PAIR(color_pair));
214
+ ewin.printstring r, c, text, color_pair
215
+ ewin.printstring r+1, c, "Press a key", color_pair
216
+ ewin.wrefresh
217
+ ewin.getchar
218
+ ewin.destroy
219
+ end
220
+ #
221
+ # Alternative to confirm dialog, if you want this look and feel, at last 2 lines of screen
222
+ # @param [String] text to prompt
223
+ # @return [true, false] 'y' is true, all else if false
224
+ def confirm_window text, aconfig={}, &block
225
+ case text
226
+ when RubyCurses::Variable # added 2011-09-20 incase variable passed
227
+ text = text.get_value
228
+ when Exception
229
+ text = text.to_s
230
+ end
231
+ ewin = _create_footer_window
232
+ r = 0; c = 1;
233
+ aconfig.each_pair { |k,v| instance_variable_set("@#{k}",v) }
234
+ @color ||= :white
235
+ @bgcolor ||= :black
236
+ color_pair = get_color($promptcolor, @color, @bgcolor)
237
+ ewin.bkgd(Ncurses.COLOR_PAIR(color_pair));
238
+ ewin.printstring r, c, text, color_pair
239
+ ewin.printstring r+1, c, "[y/n]", color_pair
240
+ ewin.wrefresh
241
+ #retval = false
242
+ retval = :NO # consistent with confirm
243
+ begin
244
+ ch = ewin.getchar
245
+ retval = :YES if ch.chr == 'y'
246
+ ensure
247
+ ewin.destroy
248
+ end
249
+ retval
250
+ end
251
+ # class created to display multiple messages without asking for user to hit a key
252
+ # returns a window to which one can keep calling printstring with 0 or 1 as row.
253
+ # destroy when finished.
254
+ # Also, one can pause if one wants, or linger.
255
+ # This is meant to be a replacement for the message_immediate and message_raw
256
+ # I was trying out in App.rb. 2011-10-1 1:27 AM
257
+ # Testing from test2.rb
258
+ # TODO: add option of putting progress_bar
259
+ class StatusWindow
260
+ attr_reader :h, :w, :top, :left # height, width, top row, left col of window
261
+ attr_reader :win
262
+ attr_accessor :color_pair
263
+ def initialize config={}, &block
264
+ @color_pair = config[:color_pair]
265
+ @row_offset = config[:row_offset] || 0
266
+ @col_offset = config[:col_offset] || 0
267
+ create_window *config[:layout]
268
+ end
269
+ def create_window h = 2 , w = Ncurses.COLS-0, t = Ncurses.LINES-2, l = 0
270
+ return @win if @win
271
+ @win = VER::Window.new(h, w , t, l)
272
+ @h = h ; @w = w; @top = t ; @left = l
273
+ @color_pair ||= get_color($promptcolor, 'white','black')
274
+ @win.bkgd(Ncurses.COLOR_PAIR(@color_pair));
275
+ @win
276
+ end
277
+ # creates a color pair based on given bg and fg colors as strings
278
+ #def set_colors bgcolor, fgcolor='white'
279
+ #@color_pair = get_color($datacolor, 'white','black')
280
+ #end
281
+ # prints a string on given row (0 or 1)
282
+ def printstring r, c, text, color_pair=@color_pair
283
+ create_window unless @win
284
+ show unless @visible
285
+ r = @h-1 if r > @h-1
286
+ #@win.printstring r, c, ' '*@w, @color_pair
287
+ # FIXME this padding overwrites the border and the offset means next line wiped
288
+ # However, now it may now totally clear a long line.
289
+ @win.printstring r+@row_offset, c+@col_offset, "%-*s" % [@w-(@col_offset*2)-c, text], color_pair
290
+ @win.wrefresh
291
+ end
292
+ # print given strings from first first column onwards
293
+ def print *textarray
294
+ create_window unless @win
295
+ show unless @visible
296
+ c = 1
297
+ textarray.each_with_index { |s, i|
298
+ @win.printstring i+@row_offset, c+@col_offset, "%-*s" % [@w-(@col_offset*2)-c, s], @color_pair
299
+ }
300
+ @win.wrefresh
301
+ end
302
+ def pause; @win.getchar; end
303
+ # pauses with the message, but doesn't ask the user to press a key.
304
+ # If he does, the key should be used by underlying window.
305
+ # Do not call destroy if you call linger, it does the destroy.
306
+ def linger caller_window=nil
307
+ begin
308
+ if caller_window
309
+ ch = @win.getchar
310
+ caller_window.ungetch(ch) # will this be available to underlying window XXX i think not !!
311
+ else
312
+ sleep 1
313
+ end
314
+ ensure
315
+ destroy
316
+ end
317
+ end
318
+ # caller must destroy after he's finished printing messages, unless
319
+ # user calls linger
320
+ def destroy; @win.destroy if @win; @win = nil; end
321
+ def hide
322
+ @win.hide
323
+ @visible = false
324
+ end
325
+ def show
326
+ @win.show unless @visible
327
+ @visible = true
328
+ end
329
+ end
330
+ # returns instance of a status_window for sending multiple
331
+ # statuses during some process
332
+ def status_window aconfig={}, &block
333
+ return StatusWindow.new aconfig
334
+ end
335
+ # this is a popup dialog box on which statuses can be printed as a process is taking place.
336
+ # I am reusing StatusWindow and so there's an issue since I've put a box, so in clearing
337
+ # the line, I might overwrite the box
338
+ def progress_dialog aconfig={}, &block
339
+ aconfig[:layout] = [10,60,10,20]
340
+ window = status_window aconfig
341
+ height = 10; width = 60
342
+ window.win.print_border_mb 1,2, height, width, $normalcolor, FFI::NCurses::A_REVERSE
343
+ return window
344
+ end
345
+ #
161
346
  =begin
162
347
  http://www.kammerl.de/ascii/AsciiSignature.php
163
348
  ___
@@ -58,9 +58,6 @@ module RubyCurses
58
58
  def each(&blk)
59
59
  @list.each(&blk)
60
60
  end
61
- #def each
62
- # @list.each { |item| yield item }
63
- #end
64
61
  # not sure how to do this XXX removed on 2009-01-14 12:28
65
62
  #def <=>(other)
66
63
  # @list <=> other
@@ -309,7 +306,13 @@ module RubyCurses
309
306
  when KEY_ENTER, 10, 13
310
307
  # if you press ENTER without selecting, it won't come here
311
308
  # it will fire button OK's fire, if that's the default button
312
- fire_handler :PRESS, @listbox.focussed_index
309
+
310
+ # returns an array of indices if multiple selection
311
+ if @listbox.selection_mode == :multiple
312
+ fire_handler :PRESS, @listbox
313
+ else
314
+ fire_handler :PRESS, @listbox.focussed_index
315
+ end
313
316
  # since Listbox is handling enter, COMBO_SELECT will not be fired
314
317
  # $log.debug "popup ENTER : #{field.name}" if !field.nil?
315
318
  @stop = true
@@ -462,8 +465,6 @@ module RubyCurses
462
465
  @win_left = 0
463
466
  @win_top = 0
464
467
 
465
- #x safe_create_buffer # 2010-01-04 12:36 BUFFERED moved here 2010-01-05 18:07
466
- #x print_borders unless @win.nil? # in messagebox we don;t have window as yet!
467
468
  # next 2 lines carry a redundancy
468
469
  select_default_values
469
470
  # when the combo box has a certain row in focus, the popup should have the same row in focus
@@ -471,6 +472,7 @@ module RubyCurses
471
472
  install_keys
472
473
  init_vars
473
474
  install_list_keys
475
+ bind(:PROPERTY_CHANGE){|e| @cell_renderer = nil } # will be recreated if anything changes 2011-09-28 V1.3.1
474
476
 
475
477
  if @list && !@list.selected_index.nil?
476
478
  set_focus_on @list.selected_index # the new version
@@ -627,7 +629,7 @@ module RubyCurses
627
629
  end
628
630
  end
629
631
  # added 2010-09-15 00:11 to make life easier
630
- def_delegators :@list, :insert, :remove_all, :delete_at, :include?
632
+ def_delegators :@list, :insert, :remove_all, :delete_at, :include?, :each, :values
631
633
  # get element at
632
634
  # @param [Fixnum] index for element
633
635
  # @return [Object] element
@@ -661,7 +663,8 @@ module RubyCurses
661
663
  startcol = @col
662
664
  startrow = @row
663
665
  @color_pair = get_color($datacolor)
664
- bordercolor = @border_color || $datacolor
666
+ # bordercolor = @border_color || $datacolor # changed 2011 dts
667
+ bordercolor = @border_color || @color_pair
665
668
  borderatt = @border_attrib || Ncurses::A_NORMAL
666
669
 
667
670
  #$log.debug "rlistb #{name}: window.print_border #{startrow}, #{startcol} , h:#{height}, w:#{width} , @color_pair, @attr "
@@ -737,7 +740,7 @@ module RubyCurses
737
740
  when @KEY_CLEAR_SELECTION
738
741
  clear_selection
739
742
  @repaint_required = true
740
- when 27, ?\C-c.getbyte(0)
743
+ when 27, ?\C-c.getbyte(0), ?\C-g.getbyte(0)
741
744
  editing_canceled @current_index if @cell_editing_allowed
742
745
  cancel_block # block
743
746
  $multiplier = 0
@@ -847,7 +850,8 @@ module RubyCurses
847
850
  # @return [Boolean] false if no data
848
851
  def on_enter
849
852
  if @list.nil? || @list.size == 0
850
- Ncurses.beep
853
+ #Ncurses.beep
854
+ get_window.ungetch($current_key) # 2011-10-4 push key back so form can go next
851
855
  return :UNHANDLED
852
856
  end
853
857
  on_enter_row @current_index
@@ -886,10 +890,10 @@ module RubyCurses
886
890
  editor.component.curpos = 0 # reset it after search, if user scrols down
887
891
  #editor.component.graphic = @graphic # 2010-01-05 00:36 TRYING OUT BUFFERED
888
892
  ## override is required if the listbox uses a buffer
889
- if @should_create_buffer
890
- $log.debug " overriding editors comp with GRAPHIC #{@graphic} "
891
- editor.component.override_graphic(@graphic) # 2010-01-05 00:36 TRYING OUT BUFFERED
892
- end
893
+ #if @should_create_buffer # removed on 2011-09-29
894
+ #$log.debug " overriding editors comp with GRAPHIC #{@graphic} "
895
+ #editor.component.override_graphic(@graphic) # 2010-01-05 00:36 TRYING OUT BUFFERED
896
+ #end
893
897
  set_form_col 0 #@left_margin
894
898
 
895
899
  # set original value so we can cancel
@@ -951,7 +955,6 @@ module RubyCurses
951
955
  # processing. also, it pans the data horizontally giving the renderer
952
956
  # a section of it.
953
957
  def repaint
954
- safe_create_buffer # 2010-01-04 12:36 BUFFERED moved here 2010-01-05 18:07
955
958
  return unless @repaint_required
956
959
  # not sure where to put this, once for all or repeat 2010-02-17 23:07 RFED16
957
960
  my_win = @form ? @form.window : @target_window
@@ -972,7 +975,7 @@ module RubyCurses
972
975
  $log.debug " rlistbox #{row_count} "
973
976
  if rc > 0 # just added in case no data passed
974
977
  tr = @toprow
975
- acolor = get_color $datacolor
978
+ acolor = get_color $datacolor # should be set once, if color or bgcolor changs TODO FIXME
976
979
  h = scrollatrow()
977
980
  r,c = rowcol
978
981
  0.upto(h) do |hh|
@@ -1015,8 +1018,6 @@ module RubyCurses
1015
1018
  end # rc == 0
1016
1019
  #@table_changed = false
1017
1020
  @repaint_required = false
1018
- @buffer_modified = true # required by form to call buffer_to_screen BUFFERED
1019
- buffer_to_window # RFED16 2010-02-17 23:16
1020
1021
  end
1021
1022
  # the idea here is to allow users who subclass Listbox to easily override parts of the cumbersome repaint
1022
1023
  # method. This assumes your List has some data, but you print a lot more. Now you don't need to
@@ -1139,7 +1140,8 @@ module RubyCurses
1139
1140
  # the earlier painted edited comp in yellow keeps showing until a key is pressed
1140
1141
 
1141
1142
  def set_buffering params
1142
- super
1143
+ $log.warn "CALLED set_buffering in LISTBOX listbox " if $log.debug?
1144
+ super # removed from widget 2011-09-29
1143
1145
  ## Ensuring that changes to top get reflect in editing comp
1144
1146
  #+ otherwise it raises an exception. Still the earlier cell_edit is being
1145
1147
  #+ printed where it was , until a key is moved
@@ -1159,6 +1161,23 @@ module RubyCurses
1159
1161
  @repaint_required = true
1160
1162
  end
1161
1163
 
1164
+ # trying to simplify usage. The Java way has made listboxes very difficult to use
1165
+ # Returns selected indices
1166
+ # Indices are often required since the renderer may modify the values displayed
1167
+ #
1168
+ def get_selected_indices
1169
+ @list_selection_model.get_selected_indices
1170
+ end
1171
+
1172
+ # Returns selected values
1173
+ #
1174
+ def get_selected_values
1175
+ selected = []
1176
+ @list_selection_model.get_selected_indices.each { |i| selected << list_data_model[i] }
1177
+ return selected
1178
+ end
1179
+ alias :selected_values :get_selected_values
1180
+ alias :selected_indices :get_selected_indices
1162
1181
 
1163
1182
  # ADD HERE
1164
1183
  end # class listb
data/lib/rbcurse/rmenu.rb CHANGED
@@ -2,46 +2,52 @@
2
2
  * Name: menu and related classes
3
3
  * Description
4
4
  * Author: rkumar
5
+ * I am redoing this totally, since this was one my first ruby programs and needs
6
+ * simplification. It was hard to maintain.
5
7
  TODO
6
- FIXME : works with 2 levels, but focus does not go into third level. This has been fixed in rpopupmenu
7
- and needs to be fixed here. DONE 2009-01-21 12:50
8
- - menu bar : what to do if adding a menu, or option later.
9
- we dnt show disabld options in a way that user can know its disabled
10
- - separate file created on 2008-12-24 17:58
11
- NOTE : this program works but is one of the first programs and is untouched. It needs to be rewritten
12
- since its quite crappy.
13
- Also, we should move to Action classes as against just blokcs of code. And action class would have
8
+ -- cursor to be on current menuitem if possible ... UNABLE TO !!
9
+ -- Number and letter indexing for item_list
10
+ -- Use Box characters and hline for separator
11
+ -- MenuSeparator and MenuItem should be common to popups and menus, so we don't need
12
+ 2 separate names, there was clobbering the same namespace.
13
+
14
+ ?? Also, we should move to Action classes as against just blokcs of code. And action class would have
14
15
  a user friendly string to identifiy the action, as well as a disabled option.
15
- NOTE on 2010-09-10 11:40 : this interface is based on Java's and is not block friendy. Also, i tried to keep the same class to work for horizontal menu bar and vertical submenus as per java's classes and this makes the code very complex. I should just make 2 classes and keep it simple.
16
16
 
17
17
  --------
18
- * Date: 2008-11-14 23:43
18
+ * Date: 2011-09-23 (old 2008-11-14 23:43 )
19
+ == Major changes v1.3.1
20
+ 2011-09-24 V1.3.1 added item_list for dynamic menuitem generation, see examples/menu1.rb
21
+ 2011-09-24 V1.3.1 added multicolumn outputs
22
+ 2011-09-24 V1.3.1 left and right keys on menua, C-g to abort
23
+
19
24
  * License:
20
25
  Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
21
26
 
22
27
  =end
23
- require 'rubygems'
24
- #require 'ncurses'
25
- require 'logger'
28
+ #require 'logger'
26
29
  require 'rbcurse'
27
30
 
28
- #include Ncurses # FFI 2011-09-8
29
31
  include RubyCurses
30
32
  module RubyCurses
31
33
  extend self
32
34
 
33
35
 
36
+ # The separator that separates menuitems, helping to group them.
34
37
  class MenuSeparator
35
38
  attr_accessor :enabled
36
39
  attr_accessor :parent
37
40
  attr_accessor :row
38
41
  attr_accessor :col
42
+ attr_accessor :coffset
39
43
  attr_accessor :width
44
+ attr_accessor :color, :bgcolor # 2011-09-25 V1.3.1
40
45
  def initialize
41
46
  @enable = false
42
47
  end
43
48
  def repaint
44
- @parent.window.printstring( @row, 0, "|%s|" % ("-"*@width), $reversecolor)
49
+ acolor = get_color($reversecolor, @color, @bgcolor)
50
+ @parent.window.printstring( @row, 0, "|%s|" % ("-"*@width), acolor)
45
51
  end
46
52
  def destroy
47
53
  end
@@ -54,18 +60,31 @@ module RubyCurses
54
60
  end
55
61
  end
56
62
  ##
63
+ # Items in menus. These will usually result in an action which closes the entire
64
+ # menubar.
57
65
  class MenuItem
58
66
  attr_accessor :parent
59
67
  # attr_accessor :window
60
68
  attr_accessor :row
61
69
  attr_accessor :col
70
+ attr_accessor :coffset
62
71
  attr_accessor :width
63
72
  attr_writer :accelerator
64
73
  attr_accessor :enabled
74
+ attr_accessor :color, :bgcolor # 2011-09-25 V1.3.1
75
+ attr_accessor :color_pair # 2011-09-25 V1.3.1
76
+ attr_reader :active_index # 2011-09-24 V1.3.1 trying to do a right
65
77
  attr_accessor :text, :mnemonic # changed reader to accessor
66
78
  def initialize text, mnemonic=nil, &block
67
79
  @text = text
68
80
  @enabled = true
81
+ # check for mnem that is not one char, could be an accelerator
82
+ if mnemonic
83
+ if mnemonic.length != 1
84
+ $log.error "MenuItem #{text} mnemonic #{mnemonic} should be one character. Maybe you meant accelerator? "
85
+ mnemonic = nil
86
+ end
87
+ end
69
88
  @mnemonic = mnemonic
70
89
  instance_eval &block if block_given?
71
90
  end
@@ -75,6 +94,7 @@ module RubyCurses
75
94
  def command *args, &block
76
95
  $log.debug ">>>command : #{@text} "
77
96
  @command = block if block_given?
97
+ alert "Command nil or some error! #{text} " unless @command
78
98
  @args = args
79
99
  end
80
100
  # add accelerator for a menu item
@@ -92,15 +112,17 @@ module RubyCurses
92
112
  @accelerator = val[0]
93
113
  end
94
114
  end
95
- def on_enter
115
+ def on_enter #item
96
116
  highlight
117
+ #@parent.window.wmove @row, @col+1 # 2011-09-25 V1.3.1 NO EFFECT
97
118
  end
98
119
  def on_leave
99
120
  highlight false
100
121
  end
101
122
  ## XXX it could be a menu again
123
+ # We should not be firing a :NO_MENUITEMS
102
124
  def fire
103
- #$log.debug ">>>fire menuitem : #{@text} #{@command} "
125
+ $log.debug ">>>fire menuitem : #{@text} #{@command} "
104
126
  @command.call self, *@args if !@command.nil?
105
127
  @parent.clear_menus
106
128
  return :CLOSE # added 2009-01-02 00:09 to close only actions, not submenus
@@ -111,10 +133,14 @@ module RubyCurses
111
133
  #$log.debug "HL XXX #{self} - > #{@parent} parent nil"
112
134
  end
113
135
  if tf
114
- color = $datacolor
136
+ #color = $datacolor
115
137
  #@parent.window.mvchgat(y=@row, x=1, @width, Ncurses::A_NORMAL, color, nil)
116
138
  # above line did not work in vt100, 200 terminals, next works.
117
- @parent.window.mvchgat(y=@row, x=1, @width, Ncurses::A_REVERSE, $reversecolor, nil)
139
+ # @parent.window.mvchgat(y=@row, x=1, @width, Ncurses::A_REVERSE, $reversecolor, nil) # changed 2011 dts 2011-09-24 multicolumn, 1 skips the border
140
+ @color_pair ||= get_color($reversecolor, @color, @bgcolor)
141
+ @parent.window.mvchgat(y=@row, x=@col+1, @width, Ncurses::A_REVERSE, @color_pair, nil)
142
+ #@parent.window.mvaddch @row, @col, "*".ord
143
+ #@parent.window.wmove @row, @col # 2011-09-25 V1.3.1 NO EFFECT
118
144
  else
119
145
  repaint
120
146
  end
@@ -126,11 +152,18 @@ module RubyCurses
126
152
  # return
127
153
  end
128
154
  r = @row
129
- acolor = $reversecolor
130
- acolor = get_color($reversecolor, 'green', 'white') if !@enabled
131
- @parent.window.printstring( @row, 0, "|%-*s|" % [@width, text], acolor)
155
+ c = @col
156
+ ltext = text
157
+ ltext = "* No Items *" if text == :NO_MENUITEMS
158
+ @color_pair = get_color($reversecolor, @color, @bgcolor)
159
+ #acolor = $reversecolor
160
+ acolor = @color_pair
161
+ acolor = get_color($reversecolor, 'green', @bgcolor) if !@enabled
162
+ # @parent.window.printstring( @row, 0, "|%-*s|" % [@width, ltext], acolor) # changed 2011 2011-09-24
163
+ @parent.window.printstring( @row, c, "|%-*s|" % [@width, ltext], acolor)
132
164
  if @enabled # 2010-09-10 23:56
133
165
  if !@accelerator.nil?
166
+ # FIXME add c earlier 0 was offset
134
167
  @parent.window.printstring( r, (@width+1)-@accelerator.length, @accelerator, acolor)
135
168
  elsif !@mnemonic.nil?
136
169
  m = @mnemonic
@@ -140,17 +173,20 @@ module RubyCurses
140
173
  # prev line changed since not working in vt100 and vt200
141
174
  @parent.window.printstring( r, ix+1, charm, $reversecolor, 'reverse') if !ix.nil?
142
175
  end
176
+ #@parent.window.wmove r, c # NO EFFECT
143
177
  end
144
178
  end
145
179
  def destroy
146
180
  $log.debug "DESTROY menuitem #{@text}"
147
181
  end
148
182
  end
149
- ##class Menu
150
- class Menu < MenuItem ## NEW
183
+ ## class Menu. Contains menuitems, and can be a menuitem itself.
184
+ # Opens out another list of menuitems.
185
+ class Menu < MenuItem
151
186
  attr_accessor :parent
152
187
  attr_accessor :row
153
188
  attr_accessor :col
189
+ attr_accessor :coffset
154
190
  attr_accessor :width
155
191
  attr_accessor :enabled
156
192
  attr_reader :text
@@ -173,7 +209,9 @@ module RubyCurses
173
209
  super text, nil, &block
174
210
  @row ||=10
175
211
  @col ||=10
212
+ @coffset = 0
176
213
  @@menus ||= []
214
+ @active_index = nil # 2011-09-25 V1.3.1 otherwise crashing in select_right
177
215
  end
178
216
  ## called upon firing so when we next show menubar there are not any left overs in here.
179
217
  def clear_menus
@@ -192,7 +230,7 @@ module RubyCurses
192
230
 
193
231
  # add item method which could be used from blocks
194
232
  # add 2010-09-10 12:20 simplifying
195
- def item text, mnem, &block
233
+ def item text, mnem=nil, &block
196
234
  #$log.debug "YYYY inside M: menuitem text #{text} "
197
235
  m = MenuItem.new text, mnem, &block
198
236
  add m
@@ -227,30 +265,64 @@ module RubyCurses
227
265
  @items.delete n
228
266
  end
229
267
  end
268
+ # generate an item list at runtime for this menu
269
+ def item_list *args, &block
270
+ $log.debug ">>>item_list : #{@text} "
271
+ @item_list = block if block_given?
272
+ @item_list_args = args
273
+ end
230
274
  # menu -
231
275
  def fire
232
276
  $log.debug "menu fire called: #{text} "
233
277
  if @window.nil?
234
278
  #repaint
235
- create_window
279
+ # added 2011-09-24 adding ability to generate list of items
280
+ if @item_list
281
+ # generate a list, but we need to know what to do with that list.
282
+ @items = []
283
+ l = @item_list.call self, *@item_list_args if !@item_list.nil?
284
+ if l.nil? || l.size == 0
285
+ item(:NO_MENUITEMS)
286
+ else
287
+ # for each element returned create a menuitem, and attach the command to it.
288
+ l.each { |e| it = item(e);
289
+ if @command # there should be a command otherwise what's the point
290
+ it.command(@args) do @command.call(it, it.text) end;
291
+ else
292
+ it.command(@args) do alert("No command attached to #{it.text} ") end;
293
+ $log.warn "No command attached to item_list "
294
+ end
295
+ }
296
+ end
297
+ $log.debug "menu got items #{@items.count} "
298
+ end
299
+ if @items.empty? # user did not specify any items
300
+ item(:NO_MENUITEMS)
301
+ end
302
+ create_window
236
303
  if !@parent.is_a? RubyCurses::MenuBar
237
304
  @parent.current_menu << self
238
305
  @@menus << self # NEW
239
306
  end
240
307
  else
241
308
  ### shouod this not just show ?
242
- $log.debug "menu fire called: #{text} ELSE XXX WHEN IS THIS CALLED ? 658 "
243
- return @items[@active_index].fire # this should happen if selected. else selected()
309
+ $log.debug "menu fire called: #{text} ELSE XXX WHEN IS THIS CALLED ? 658 #{@items[@active_index].text} "
310
+ if @active_index # sometimes no menu item specified 2011-09-24 NEWMENU
311
+ return @items[@active_index].fire # this should happen if selected. else selected()
312
+ end
244
313
  end
245
314
  #@action.call if !@action.nil?
246
315
  end
247
316
  # user has clicked down, we shoud display items
248
317
  # DRAW menuitems
249
318
  def repaint # menu.repaint
250
- return if @items.nil? or @items.empty?
319
+ # OMG will not print anything if no items !
320
+ # When we do item generation this list will be empty
321
+ #return if @items.nil? or @items.empty? # commented 2011-09-24 NEWMENU
251
322
  #$log.debug "menu repaint: #{text} row #{@row} col #{@col} "
323
+ @color_pair = get_color($reversecolor, @color, @bgcolor)
252
324
  if !@parent.is_a? RubyCurses::MenuBar
253
- @parent.window.printstring( @row, 0, "|%-*s>|" % [@width-1, text], $reversecolor)
325
+ @parent.window.printstring( @row, 0, "|%-*s>|" % [@width-1, text], @color_pair)
254
326
  @parent.window.refresh
255
327
  end
256
328
  if @window.nil?
@@ -302,14 +374,55 @@ module RubyCurses
302
374
  #select_item @items.length-1
303
375
  end
304
376
  end
377
+ #
378
+ # If multi-column menuitems then try going to a left item (prev column same row)
379
+ # NOTE It should only come here if items are open, otherwise row and col will be blank.
380
+ # NOTE active_index nil means no items open
381
+ #
382
+ def select_left_item
383
+ return :UNHANDLED if @items.nil? or @items.empty? or @active_index.nil?
384
+ index = nil
385
+ crow = @items[@active_index].row
386
+ ccol = @items[@active_index].col
387
+ @items.each_with_index { |e, i| index = i if e.row == crow && e.col < ccol }
388
+ if index
389
+ select_item index
390
+ else
391
+ return :UNHANDLED
392
+ end
393
+ end
394
+ # @since 1.3.1 2011-09-24
395
+ # If multi-column menuitems then try going to a right item (next column same row)
396
+ # Only if items are open, not from a menubar menu
397
+ def select_right_item
398
+ return :UNHANDLED if @items.nil? or @items.empty? or @active_index.nil?
399
+ crow = @items[@active_index].row
400
+ ccol = @items[@active_index].col
401
+ #alert "inside select right with #{@items.size} #{@items[@active_index].text}: items. r #{crow} col #{ccol} "
402
+ index = nil
403
+ @items.each_with_index { |e, i|
404
+ $log.debug " select_right #{e.row} == #{crow} , #{e.col} > #{ccol} " if $log.debug?
405
+ if e.row == crow && e.col > ccol
406
+ index = i
407
+ $log.debug "YYY select_right #{e.row} == #{crow} , #{e.col} > #{ccol} FOUND #{i} " if $log.debug?
408
+ break
409
+ end
410
+ }
411
+ if index
412
+ select_item index
413
+ else
414
+ return :UNHANDLED
415
+ end
416
+ end
305
417
  def on_enter # menu.on_enter
306
418
  #$log.debug "menu onenter: #{text} #{@row} #{@col} "
307
419
  # call parent method. XXX
308
- if @parent.is_a? RubyCurses::MenuBar
309
- @parent.window.printstring( @row, @col, " %s " % text, $datacolor)
310
- else
420
+ #if @parent.is_a? RubyCurses::MenuBar
421
+ #acolor = get_color($datacolor, @bgcolor, @color)
422
+ #@parent.window.printstring( @row, @col, " %s " % text, acolor)
423
+ #else
311
424
  highlight
312
- end
425
+ #end
313
426
  if !@window.nil? #and @parent.selected
314
427
  #$log.debug "menu onenter: #{text} calling window,show"
315
428
  @window.show
@@ -324,8 +437,10 @@ module RubyCurses
324
437
  def on_leave # menu.on_leave
325
438
  #$log.debug "menu onleave: #{text} #{@row} #{@col} "
326
439
  # call parent method. XXX
440
+ @color_pair ||= get_color($reversecolor, @color, @bgcolor)
327
441
  if @parent.is_a? RubyCurses::MenuBar
328
- @parent.window.printstring( @row, @col, " %s " % text, $reversecolor)
442
+ # @parent.window.printstring( @row, @col, " %s " % text, $reversecolor) # changed 2011 2011-09-24
443
+ @parent.window.printstring( @row, @col, " %s " % text, @color_pair)
329
444
  @window.hide if !@window.nil?
330
445
  else
331
446
  #$log.debug "MENU SUBMEN. menu onleave: #{text} #{@row} #{@col} "
@@ -337,43 +452,87 @@ module RubyCurses
337
452
  end
338
453
  end
339
454
  def highlight tf=true # menu
340
- #$log.debug "MENU SUBMENU menu highlight: #{text} #{@row} #{@col}, PW #{@parent.width} "
341
- color = tf ? $datacolor : $reversecolor
342
- att = tf ? Ncurses::A_REVERSE : Ncurses::A_NORMAL
343
- #@parent.window.mvchgat(y=@row, x=1, @width, Ncurses::A_NORMAL, color, nil)
344
- #@parent.window.mvchgat(y=@row, x=1, @parent.width, Ncurses::A_NORMAL, color, nil)
345
- # above line did not work with vt100/vt200 next does
346
- @parent.window.mvchgat(y=@row, x=1, @parent.width, att, $reversecolor, nil)
347
- @parent.window.wrefresh
348
- end
349
- def create_window # menu
350
- margin = 3
351
- @width = array_width @items
352
- #$log.debug "create window menu #{@text}: #{@row} ,#{@col},wd #{@width} "
353
- @layout = { :height => @items.length+3, :width => @width+margin, :top => @row+1, :left => @col }
455
+ if @parent.is_a? RubyCurses::MenuBar # top level menu
456
+ #acolor = get_color($datacolor, @bgcolor, @color)
457
+ #@parent.window.printstring( @row, @col, " %s " % text, acolor)
458
+ @color_pair ||= get_color($reversecolor, @color, @bgcolor)
459
+ att = Ncurses::A_REVERSE
460
+ @parent.window.mvchgat(y=@row, x=@col+1, text.length+1, att, @color_pair, nil)
461
+ else
462
+ #$log.debug "MENU SUBMENU menu highlight: #{text} #{@row} #{@col}, PW #{@parent.width} "
463
+ acolor = tf ? $datacolor : $reversecolor
464
+ att = tf ? Ncurses::A_REVERSE : Ncurses::A_NORMAL
465
+ #@parent.window.mvchgat(y=@row, x=1, @width, Ncurses::A_NORMAL, color, nil)
466
+ #@parent.window.mvchgat(y=@row, x=1, @parent.width, Ncurses::A_NORMAL, color, nil)
467
+ # above line did not work with vt100/vt200 next does
468
+ # @parent.window.mvchgat(y=@row, x=1, @parent.width, att, $reversecolor, nil) # changed 2011 2011-09-24
469
+ @parent.window.mvchgat(y=@row, x=1, @parent.width, att, @color_pair, nil)
470
+ @parent.window.wrefresh
471
+ end
472
+ end
473
+ def create_window # menu
474
+ margin = 2 # flush against parent
475
+ @width = array_width(@items) + 1 # adding 1 since menus append a ">" 2011-09-24
476
+ $log.debug "create window menu #{@text}: r #{@row} ,col #{@col}, wd #{@width} "
477
+ t = @row+1
478
+ h = @items.length+3
479
+ ww = @width+margin
480
+ ww1 = @width
481
+ max = Ncurses.LINES-1
482
+ if t + h > max
483
+ t = 2 # one below menubar, not touching
484
+ if h > max
485
+ i = ((h*1.0)/max).ceil
486
+ h = max - 1
487
+ ww = ww * i # FIXME we need to calculate
488
+ end
489
+ end # t + 1
490
+ $log.debug "create window menu #{@text}: t #{t} ,h #{h}, w: #{ww} , col #{@col} max #{max} "
491
+
492
+ #@layout = { :height => @items.length+3, :width => ww, :top => @row+1, :left => @col }
493
+ # earlier col had the offset to start the next level, I was not using it to print
494
+ # but with mulitple cols i am using it. So, this col will overwrite existing menu.
495
+ @layout = { :height => h-1, :width => ww, :top => t, :left => @coffset }
354
496
  @win = VER::Window.new(@layout)
355
497
  @window = @win
356
- @win.bkgd(Ncurses.COLOR_PAIR($datacolor));
498
+ @color_pair ||= get_color($datacolor, @color, @bgcolor)
499
+ @rev_color_pair ||= get_color($reversecolor, @color, @bgcolor)
500
+ @win.bkgd(Ncurses.COLOR_PAIR(@color_pair));
357
501
  @panel = @win.panel
358
- @window.printstring( 0, 0, "+%s+" % ("-"*@width), $reversecolor)
502
+ #@window.printstring( 0, 0, "+%s+" % ("-"*@width), $reversecolor)
503
+ @window.printstring( 0, 0, "+%s+" % ("-"*(ww1)), @rev_color_pair)
504
+ saved_r = 1
359
505
  r = 1
506
+ #saved_c = @col+@width+margin # margins???
507
+ saved_c = 0 ; # actual program uses 0 in repain for col
508
+ c = saved_c
509
+ $log.debug "create window menu #{@text}: first col r #{r} ,c #{c}"
360
510
  @items.each do |item|
361
- #if item == :SEPARATOR
362
- # @window.printstring( r, 0, "|%s|" % ("-"*@width), $reversecolor)
363
- #else
511
+ #break if r > h # added 2011-09-24 for large number of items - causes error
512
+ if r >= h-2
513
+ @window.printstring( h-2, c, "+%s+" % ("-"*(ww1)), @rev_color_pair)
514
+ r = saved_r
515
+ c += (@width + 2)
516
+ @window.printstring( 0, c, "+%s+" % ("-"*(ww1)), @rev_color_pair)
517
+ $log.debug "create window menu #{@text}: new col r #{r} ,c #{c}, #{item.text} "
518
+ end
364
519
  item.row = r
365
- item.col = 0
366
- item.col = @col+@width+margin # margins???
367
- # $log.debug "create window menu loop passing col : #{item.col} "
520
+ item.col = c
521
+ item.coffset = @coffset+@width+margin # margins???
522
+
523
+
368
524
  item.width = @width
369
525
  #item.window = @window
370
526
  item.parent = self
527
+ item.color = @color; item.bgcolor = @bgcolor
371
528
  item.repaint
372
- #end
373
529
  r+=1
374
530
  end
375
- @window.printstring( r, 0, "+%s+" % ("-"*@width), $reversecolor)
376
- select_item 0
531
+ # @window.printstring( r, 0, "+%s+" % ("-"*@width), $reversecolor) # changed 2011 2011-09-24
532
+ @window.printstring( h-2, 0, "+%s+" % ("-"*(ww1)), @rev_color_pair)
533
+ # in case of multiple rows
534
+ @window.printstring( r, c, "+%s+" % ("-"*(ww1)), @rev_color_pair)
535
+ select_item 0
377
536
  @window.refresh
378
537
  return @window
379
538
  end
@@ -415,7 +574,7 @@ module RubyCurses
415
574
  cmenu.select_next_item
416
575
  #return cmenu.fire # XXX 2010-10-16 21:39 trying out
417
576
  if cmenu.is_a? RubyCurses::Menu
418
- #alert "is a menu"
577
+ #alert "is a menu" # this gets triggered even when we are on items
419
578
  end
420
579
  when KEY_UP
421
580
  cmenu.select_prev_item
@@ -426,27 +585,48 @@ module RubyCurses
426
585
  #$log.debug "LEFT IN MENU : #{cmenu.parent.class} len: #{cmenu.parent.current_menu.length}"
427
586
  #$log.debug "left IN MENU : #{cmenu.parent.class} len: #{cmenu.current_menu.length}"
428
587
  end
429
- if cmenu.parent.is_a? RubyCurses::Menu and !cmenu.parent.current_menu.empty?
430
- #$log.debug " ABOU TO DESTROY DUE TO LEFT"
431
- cmenu.parent.current_menu.pop
432
- @@menus.pop ## NEW
433
- cmenu.destroy
434
- else
435
- return :UNHANDLED
588
+ ret = cmenu.select_left_item # 2011-09-24 V1.3.1 attempt to goto left item if columns
589
+ if ret == :UNHANDLED
590
+ if cmenu.parent.is_a? RubyCurses::MenuBar #and !cmenu.parent.current_menu.empty?
591
+ #$log.debug " ABOU TO DESTROY DUE TO LEFT"
592
+ cmenu.current_menu.pop
593
+ @@menus.pop ## NEW
594
+ cmenu.destroy
595
+ return :UNHANDLED
596
+ end
597
+ # LEFT on a menu list allows me to close and return to higher level
598
+ if cmenu.parent.is_a? RubyCurses::Menu #and !cmenu.parent.current_menu.empty?
599
+ #$log.debug " ABOU TO DESTROY DUE TO LEFT"
600
+ cmenu.current_menu.pop
601
+ @@menus.pop ## NEW
602
+ cmenu.destroy
603
+ #return :UNHANDLED
604
+ end
436
605
  end
437
606
  when KEY_RIGHT
438
- #$log.debug "RIGHTIN MENU : "
439
- if cmenu.parent.is_a? RubyCurses::Menu
607
+ $log.debug "RIGHTIN MENU : #{text} "
608
+ if cmenu.active_index
609
+ if cmenu.items[cmenu.active_index].is_a? RubyCurses::Menu
610
+ #alert "could fire here cmenu: #{cmenu.text}, par: #{cmenu.parent.text} "
611
+ cmenu.fire
612
+ return
440
613
  #$log.debug "right IN MENU : #{cmenu.parent.class} len: #{cmenu.parent.current_menu.length}"
441
614
  #$log.debug "right IN MENU : #{cmenu.parent.class} len: #{cmenu.current_menu.length}"
442
615
  end
443
- if cmenu.parent.is_a? RubyCurses::Menu and !cmenu.parent.current_menu.empty?
444
- #$log.debug " ABOU TO DESTROY DUE TO RIGHT"
445
- cmenu.parent.current_menu.pop
446
- @@menus.pop
447
- cmenu.destroy
616
+ end
617
+ # This introduces a bug if no open items
618
+ ret = cmenu.select_right_item # 2011-09-24 V1.3.1 attempt to goto right item if columns
619
+ #alert "attempting to select right #{ret} "
620
+ if ret == :UNHANDLED
621
+ #if cmenu.parent.is_a? RubyCurses::Menu and !cmenu.parent.current_menu.empty?
622
+ if cmenu.parent.is_a? RubyCurses::MenuBar #and !cmenu.current_menu.empty?
623
+ $log.debug " ABOU TO DESTROY DUE TO RIGHT"
624
+ cmenu.current_menu.pop
625
+ @@menus.pop
626
+ cmenu.destroy
627
+ return :UNHANDLED
628
+ end
448
629
  end
449
- return :UNHANDLED
450
630
  else
451
631
  ret = check_mnemonics cmenu, ch
452
632
  return ret
@@ -472,7 +652,7 @@ module RubyCurses
472
652
  def show # menu.show
473
653
  #$log.debug "show (menu) : #{@text} "
474
654
  if @window.nil?
475
- create_window
655
+ create_window #@col+@width
476
656
  end
477
657
  @window.show
478
658
  select_item 0
@@ -487,12 +667,16 @@ module RubyCurses
487
667
  attr_reader :window
488
668
  attr_reader :panel
489
669
  attr_reader :selected
670
+ attr_reader :text # temp 2011-09-24 V1.3.1
490
671
  attr_accessor :visible
491
672
  attr_accessor :active_index
492
673
  attr_accessor :state # normal, selected, highlighted
493
674
  attr_accessor :toggle_key # key used to popup, should be set prior to attaching to form
675
+ attr_accessor :color, :bgcolor # 2011-09-25 V1.3.1
676
+ attr_accessor :_object_created # 2011-10-7 if visible then Form will call this
494
677
  def initialize &block
495
678
  @window = nil
679
+ @text = "menubar"
496
680
  @items = []
497
681
  init_vars
498
682
  @visible = false
@@ -519,6 +703,8 @@ module RubyCurses
519
703
  def menu text, &block
520
704
  #$log.debug "YYYY inside MB: menu text #{text} "
521
705
  m = Menu.new text, &block
706
+ m.color = @color
707
+ m.bgcolor = @bgcolor
522
708
  add m
523
709
  return m
524
710
  end
@@ -549,6 +735,13 @@ module RubyCurses
549
735
  # menu.show
550
736
  # menu.window.wrefresh # XXX we need this
551
737
  end
738
+
739
+ def keep_visible flag=nil
740
+ return @keep_visible unless flag
741
+ @keep_visible = flag
742
+ @visible = flag
743
+ self
744
+ end
552
745
  # menubar LEFT, RIGHT, DOWN
553
746
  def handle_keys
554
747
  @selected = false
@@ -590,6 +783,8 @@ module RubyCurses
590
783
  #$log.debug " mb insdie KEYRIGHT : #{ch}"
591
784
  ret = current_menu.handle_key ch
592
785
  next_menu if ret == :UNHANDLED
786
+ when ?\C-g.getbyte(0) # abort
787
+ throw :menubarclose
593
788
  else
594
789
  #$log.debug " mb insdie ELSE : #{ch}"
595
790
  ret = current_menu.handle_key ch
@@ -608,15 +803,24 @@ module RubyCurses
608
803
  ensure
609
804
  #ensure is required becos one can throw a :close
610
805
  $log.debug " DESTROY IN ENSURE"
611
- current_menu.clear_menus #@@menus = [] # added 2009-01-23 13:21
612
- destroy # Note that we destroy the menu bar upon exit
806
+ current_menu.clear_menus #@@menus = [] # added 2009-01-23 13:21
807
+ destroy # Note that we destroy the menu bar upon exit
613
808
  end
614
809
  end
615
810
  def current_menu
616
811
  @items[@active_index]
617
812
  end
813
+ # called by set_menu_bar in widget.rb (class Form).
618
814
  def toggle
619
- @items.each { |i| $log.debug " ITEM DDD : #{i.text}" }
815
+ # added keeping it visible, 2011-10-7 being tested in dbdemo
816
+ if @keep_visible
817
+ init_vars
818
+ show
819
+ @items[0].highlight
820
+ @window.ungetch(KEY_DOWN)
821
+ return
822
+ end
823
+ #@items.each { |i| $log.debug " ITEM DDD : #{i.text}" }
620
824
  @visible = !@visible
621
825
  if !@visible
622
826
  hide
@@ -627,7 +831,7 @@ module RubyCurses
627
831
  end
628
832
  def hide
629
833
  @visible = false
630
- @window.hide if !@window.nil?
834
+ @window.hide if !@window.nil? # seems to cause auto-firing when we resume toggle 2011-09-26
631
835
  end
632
836
  def show
633
837
  @visible = true
@@ -638,35 +842,49 @@ module RubyCurses
638
842
  end
639
843
  end
640
844
  ## menubar
845
+ # TODO: check for menu to be flush right (only for last one).
641
846
  def repaint
642
847
  return if !@visible
643
- @window ||= create_window
644
- @window.printstring( 0, 0, "%-*s" % [@cols," "], $reversecolor)
848
+ @color_pair = get_color($reversecolor, @color, @bgcolor)
849
+ @window ||= create_window_menubar
850
+ # @window.printstring( 0, 0, "%-*s" % [@cols," "], $reversecolor) # changed 2011 2011-09-24
851
+ @window.printstring( 0, 0, "%-*s" % [@cols," "], @color_pair)
645
852
  c = 1; r = 0;
646
853
  @items.each do |item|
647
- item.row = r; item.col = c; item.parent = self
648
- @window.printstring( r, c, " %s " % item.text, $reversecolor)
854
+ item.row = r; item.col = c; item.coffset = c; item.parent = self
855
+ item.color = @color
856
+ item.bgcolor = @bgcolor
857
+ @window.printstring( r, c, " %s " % item.text, @color_pair)
858
+ # 2011-09-26 V1.3.1 quick dirty highlighting of first menu on menubar
859
+ # on opening since calling highlight was giving bug in parent.width
860
+ #if c == 1
861
+ #att = Ncurses::A_REVERSE
862
+ #@window.mvchgat(y=r, x=c+1, item.text.length+1, att, @color_pair, nil)
863
+ #end
649
864
  c += (item.text.length + 2)
650
865
  end
866
+ #@items[0].on_enter # 2011-09-25 V1.3.1 caused issues when toggling, first item fired on DOWN
867
+ @items[0].highlight unless @keep_visible # 2011-09-26 V1.3.1 fixed to take both cases into account
651
868
  @window.wrefresh
652
869
  end
653
- def create_window
870
+ def create_window_menubar
654
871
  @layout = { :height => 1, :width => 0, :top => 0, :left => 0 }
655
872
  @win = VER::Window.new(@layout)
656
873
  @window = @win
657
- @win.bkgd(Ncurses.COLOR_PAIR(5));
874
+ @win.bkgd(Ncurses.COLOR_PAIR(5)); # <---- FIXME
658
875
  @panel = @win.panel
659
876
  return @window
660
877
  end
661
878
  def destroy
662
879
  $log.debug "DESTRY menubar "
880
+ @items.each do |item|
881
+ item.destroy
882
+ end
883
+ return if @keep_visible
663
884
  @visible = false
664
885
  panel = @window.panel
665
886
  Ncurses::Panel.del_panel(panel.pointer) if !panel.nil?
666
887
  @window.delwin if !@window.nil?
667
- @items.each do |item|
668
- item.destroy
669
- end
670
888
  @window = nil
671
889
  end
672
890
  end # menubar
@@ -702,8 +920,10 @@ module RubyCurses
702
920
  repaint
703
921
  highlight true
704
922
  end
705
- def repaint
706
- @parent.window.printstring( row, 0, getvalue_for_paint, $reversecolor)
923
+ def repaint # checkbox
924
+ # FIXME need @color_pair here
925
+ @color_pair ||= get_color($reversecolor, @color, @bgcolor)
926
+ @parent.window.printstring( row, 0, getvalue_for_paint, @color_pair)
707
927
  parent.window.wrefresh
708
928
  end
709
929
  def method_missing(sym, *args)
@@ -714,6 +934,6 @@ module RubyCurses
714
934
  $log.error("ERROR CHECKBOXMENU #{sym} called")
715
935
  end
716
936
  end
937
+ end # class
717
938
 
718
- end
719
939
  end # modul