rbcurse 1.3.0 → 1.4.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.
- data/CHANGELOG +33 -0
- data/README.markdown +7 -1
- data/TODO2.txt +21 -15
- data/VERSION +1 -1
- data/examples/abasiclist.rb +2 -2
- data/examples/alpmenu.rb +1 -1
- data/examples/app.rb +0 -1
- data/examples/appdirtree.rb +4 -2
- data/examples/appemail.rb +7 -3
- data/examples/appemaillb.rb +1 -1
- data/examples/appgcompose.rb +2 -2
- data/examples/appgmail.rb +1 -1
- data/examples/appmethods.rb +20 -2
- data/examples/atree.rb +9 -1
- data/examples/dbdemo.rb +460 -0
- data/examples/dirtree.rb +1 -1
- data/examples/menu1.rb +37 -5
- data/examples/multispl.rb +1 -1
- data/examples/rfe.rb +9 -2
- data/examples/splitp.rb +1 -1
- data/examples/sqlc.rb +6 -10
- data/examples/sqlm.rb +2 -20
- data/examples/sqlt.rb +408 -0
- data/examples/term2.rb +1 -1
- data/examples/test2.rb +169 -97
- data/examples/testapp.rb +1 -1
- data/examples/testapp2.rb +1 -1
- data/examples/testkeypress.rb +4 -2
- data/examples/testtable.rb +6 -0
- data/examples/testtpane.rb +35 -23
- data/examples/testvimsplit.rb +3 -2
- data/lib/rbcurse.rb +1 -1
- data/lib/rbcurse/action.rb +8 -0
- data/lib/rbcurse/app.rb +39 -23
- data/lib/rbcurse/extras/bottomline.rb +101 -13
- data/lib/rbcurse/extras/directorylist.rb +14 -5
- data/lib/rbcurse/extras/divider.rb +1 -1
- data/lib/rbcurse/extras/listselectable.rb +42 -8
- data/lib/rbcurse/extras/masterdetail.rb +2 -2
- data/lib/rbcurse/extras/scrollbar.rb +11 -2
- data/lib/rbcurse/extras/statusline.rb +56 -0
- data/lib/rbcurse/extras/stdscrwindow.rb +11 -0
- data/lib/rbcurse/extras/tabular.rb +2 -1
- data/lib/rbcurse/extras/tabularwidget.rb +60 -17
- data/lib/rbcurse/extras/viewer.rb +16 -4
- data/lib/rbcurse/keylabelprinter.rb +34 -4
- data/lib/rbcurse/listeditable.rb +5 -1
- data/lib/rbcurse/listkeys.rb +1 -1
- data/lib/rbcurse/listscrollable.rb +15 -8
- data/lib/rbcurse/rbasiclistbox.rb +44 -23
- data/lib/rbcurse/rcommandwindow.rb +8 -14
- data/lib/rbcurse/rdialogs.rb +187 -2
- data/lib/rbcurse/rlistbox.rb +38 -19
- data/lib/rbcurse/rmenu.rb +313 -93
- data/lib/rbcurse/rmessagebox.rb +3 -2
- data/lib/rbcurse/rmulticontainer.rb +5 -3
- data/lib/rbcurse/rmultisplit.rb +2 -11
- data/lib/rbcurse/rmultitextview.rb +4 -5
- data/lib/rbcurse/rtabbedpane.rb +223 -69
- data/lib/rbcurse/rtable.rb +6 -10
- data/lib/rbcurse/rtextarea.rb +57 -36
- data/lib/rbcurse/rtextview.rb +12 -15
- data/lib/rbcurse/rtree.rb +79 -22
- data/lib/rbcurse/rvimsplit.rb +16 -25
- data/lib/rbcurse/rwidget.rb +376 -523
- data/lib/rbcurse/tree/treecellrenderer.rb +24 -11
- data/lib/rbcurse/tree/treemodel.rb +1 -1
- data/lib/ver/window.rb +130 -66
- metadata +5 -3
- data/examples/term.rb +0 -48
data/lib/rbcurse/rdialogs.rb
CHANGED
@@ -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
|
___
|
data/lib/rbcurse/rlistbox.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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 '
|
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
|
-
|
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
|
-
|
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
|
-
|
130
|
-
|
131
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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],
|
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
|
-
|
310
|
-
|
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
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
@
|
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
|
-
@
|
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
|
-
|
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
|
362
|
-
|
363
|
-
|
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 =
|
366
|
-
item.
|
367
|
-
|
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
|
-
|
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
|
-
|
430
|
-
|
431
|
-
cmenu.parent.current_menu.
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
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
|
-
|
439
|
-
|
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
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
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
|
-
|
612
|
-
|
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
|
-
|
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
|
-
@
|
644
|
-
@window
|
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
|
-
|
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
|
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
|
-
|
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
|