rbhex-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/CHANGELOG +2000 -0
- data/LICENSE +56 -0
- data/README.md +44 -0
- data/examples/abasiclist.rb +179 -0
- data/examples/alpmenu.rb +50 -0
- data/examples/app.sample +19 -0
- data/examples/atree.rb +100 -0
- data/examples/bline.rb +136 -0
- data/examples/common/file.rb +45 -0
- data/examples/data/README.markdown +9 -0
- data/examples/data/brew.txt +38 -0
- data/examples/data/color.2 +37 -0
- data/examples/data/gemlist.txt +60 -0
- data/examples/data/lotr.txt +12 -0
- data/examples/data/ports.txt +136 -0
- data/examples/data/table.txt +37 -0
- data/examples/data/tasks.csv +88 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/todo.txt +10 -0
- data/examples/data/todo.txt.bak +10 -0
- data/examples/data/todocsv.csv +28 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +502 -0
- data/examples/dirtree.rb +94 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +146 -0
- data/examples/tasks.rb +178 -0
- data/examples/term2.rb +84 -0
- data/examples/testbuttons.rb +296 -0
- data/examples/testcombo.rb +102 -0
- data/examples/testfields.rb +195 -0
- data/examples/testkeypress.rb +72 -0
- data/examples/testlistbox.rb +170 -0
- data/examples/testmessagebox.rb +140 -0
- data/examples/testprogress.rb +116 -0
- data/examples/testree.rb +106 -0
- data/examples/testwsshortcuts.rb +66 -0
- data/examples/testwsshortcuts2.rb +128 -0
- data/lib/rbhex.rb +6 -0
- data/lib/rbhex/core/docs/index.txt +73 -0
- data/lib/rbhex/core/include/action.rb +80 -0
- data/lib/rbhex/core/include/actionmanager.rb +49 -0
- data/lib/rbhex/core/include/appmethods.rb +214 -0
- data/lib/rbhex/core/include/bordertitle.rb +48 -0
- data/lib/rbhex/core/include/chunk.rb +203 -0
- data/lib/rbhex/core/include/io.rb +553 -0
- data/lib/rbhex/core/include/listbindings.rb +74 -0
- data/lib/rbhex/core/include/listcellrenderer.rb +140 -0
- data/lib/rbhex/core/include/listeditable.rb +317 -0
- data/lib/rbhex/core/include/listscrollable.rb +663 -0
- data/lib/rbhex/core/include/listselectable.rb +271 -0
- data/lib/rbhex/core/include/multibuffer.rb +83 -0
- data/lib/rbhex/core/include/orderedhash.rb +77 -0
- data/lib/rbhex/core/include/ractionevent.rb +73 -0
- data/lib/rbhex/core/include/rchangeevent.rb +27 -0
- data/lib/rbhex/core/include/rhistory.rb +95 -0
- data/lib/rbhex/core/include/rinputdataevent.rb +47 -0
- data/lib/rbhex/core/include/vieditable.rb +172 -0
- data/lib/rbhex/core/include/widgetmenu.rb +66 -0
- data/lib/rbhex/core/system/colormap.rb +165 -0
- data/lib/rbhex/core/system/keyboard.rb +150 -0
- data/lib/rbhex/core/system/keydefs.rb +30 -0
- data/lib/rbhex/core/system/ncurses.rb +236 -0
- data/lib/rbhex/core/system/panel.rb +162 -0
- data/lib/rbhex/core/system/window.rb +913 -0
- data/lib/rbhex/core/util/ansiparser.rb +119 -0
- data/lib/rbhex/core/util/app.rb +1228 -0
- data/lib/rbhex/core/util/basestack.rb +410 -0
- data/lib/rbhex/core/util/bottomline.rb +1859 -0
- data/lib/rbhex/core/util/colorparser.rb +77 -0
- data/lib/rbhex/core/util/focusmanager.rb +31 -0
- data/lib/rbhex/core/util/padreader.rb +192 -0
- data/lib/rbhex/core/util/rcommandwindow.rb +604 -0
- data/lib/rbhex/core/util/rdialogs.rb +574 -0
- data/lib/rbhex/core/util/viewer.rb +149 -0
- data/lib/rbhex/core/util/widgetshortcuts.rb +506 -0
- data/lib/rbhex/core/version.rb +5 -0
- data/lib/rbhex/core/widgets/applicationheader.rb +103 -0
- data/lib/rbhex/core/widgets/box.rb +58 -0
- data/lib/rbhex/core/widgets/divider.rb +310 -0
- data/lib/rbhex/core/widgets/keylabelprinter.rb +194 -0
- data/lib/rbhex/core/widgets/rcombo.rb +253 -0
- data/lib/rbhex/core/widgets/rcontainer.rb +415 -0
- data/lib/rbhex/core/widgets/rlink.rb +30 -0
- data/lib/rbhex/core/widgets/rlist.rb +696 -0
- data/lib/rbhex/core/widgets/rmenu.rb +958 -0
- data/lib/rbhex/core/widgets/rmenulink.rb +22 -0
- data/lib/rbhex/core/widgets/rmessagebox.rb +387 -0
- data/lib/rbhex/core/widgets/rprogress.rb +118 -0
- data/lib/rbhex/core/widgets/rtabbedpane.rb +634 -0
- data/lib/rbhex/core/widgets/rtabbedwindow.rb +70 -0
- data/lib/rbhex/core/widgets/rtextarea.rb +960 -0
- data/lib/rbhex/core/widgets/rtextview.rb +739 -0
- data/lib/rbhex/core/widgets/rtree.rb +768 -0
- data/lib/rbhex/core/widgets/rwidget.rb +3277 -0
- data/lib/rbhex/core/widgets/scrollbar.rb +143 -0
- data/lib/rbhex/core/widgets/statusline.rb +113 -0
- data/lib/rbhex/core/widgets/tabular.rb +264 -0
- data/lib/rbhex/core/widgets/tabularwidget.rb +1142 -0
- data/lib/rbhex/core/widgets/textpad.rb +995 -0
- data/lib/rbhex/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/rbhex/core/widgets/tree/treemodel.rb +428 -0
- data/rbhex-core.gemspec +32 -0
- metadata +172 -0
|
@@ -0,0 +1,958 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
* Name: menu and related classes
|
|
3
|
+
* Description
|
|
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.
|
|
7
|
+
TODO
|
|
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
|
|
15
|
+
a user friendly string to identifiy the action, as well as a disabled option.
|
|
16
|
+
|
|
17
|
+
--------
|
|
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
|
+
|
|
24
|
+
* License:
|
|
25
|
+
Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
|
26
|
+
|
|
27
|
+
=end
|
|
28
|
+
#require 'logger'
|
|
29
|
+
require 'rbhex'
|
|
30
|
+
|
|
31
|
+
include RubyCurses
|
|
32
|
+
module RubyCurses
|
|
33
|
+
extend self
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# The separator that separates menuitems, helping to group them.
|
|
37
|
+
class MenuSeparator
|
|
38
|
+
attr_accessor :enabled
|
|
39
|
+
attr_accessor :parent
|
|
40
|
+
attr_accessor :row
|
|
41
|
+
attr_accessor :col
|
|
42
|
+
attr_accessor :coffset
|
|
43
|
+
attr_accessor :width
|
|
44
|
+
attr_accessor :color, :bgcolor # 2011-09-25 V1.3.1
|
|
45
|
+
def initialize
|
|
46
|
+
@enable = false
|
|
47
|
+
end
|
|
48
|
+
def repaint
|
|
49
|
+
acolor = get_color($reversecolor, @color, @bgcolor)
|
|
50
|
+
@parent.window.printstring( @row, 0, "|%s|" % ("-"*@width), acolor)
|
|
51
|
+
end
|
|
52
|
+
def destroy
|
|
53
|
+
end
|
|
54
|
+
def on_enter
|
|
55
|
+
end
|
|
56
|
+
def on_leave
|
|
57
|
+
end
|
|
58
|
+
def to_s
|
|
59
|
+
""
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
##
|
|
63
|
+
# Items in menus. These will usually result in an action which closes the entire
|
|
64
|
+
# menubar.
|
|
65
|
+
class MenuItem
|
|
66
|
+
attr_accessor :parent
|
|
67
|
+
# attr_accessor :window
|
|
68
|
+
attr_accessor :row
|
|
69
|
+
attr_accessor :col
|
|
70
|
+
attr_accessor :coffset
|
|
71
|
+
attr_accessor :width
|
|
72
|
+
attr_writer :accelerator
|
|
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
|
|
77
|
+
attr_accessor :text, :mnemonic # changed reader to accessor
|
|
78
|
+
def initialize text, mnemonic=nil, &block
|
|
79
|
+
@text = text
|
|
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
|
|
88
|
+
@mnemonic = mnemonic
|
|
89
|
+
instance_eval &block if block_given?
|
|
90
|
+
end
|
|
91
|
+
def to_s
|
|
92
|
+
"#{@text} #{@accelerator}"
|
|
93
|
+
end
|
|
94
|
+
def command *args, &block
|
|
95
|
+
$log.debug ">>>command : #{@text} "
|
|
96
|
+
@command = block if block_given?
|
|
97
|
+
alert "Command nil or some error! #{text} " unless @command
|
|
98
|
+
@args = args
|
|
99
|
+
end
|
|
100
|
+
# add accelerator for a menu item
|
|
101
|
+
# NOTE: accelerator means that the application has tied this string to some action, outside
|
|
102
|
+
# of the menu bar. It does not mean that the menu bar will trigger the action. So the app still has to
|
|
103
|
+
# define the action and bind a key to that accelerator. This is only informative.
|
|
104
|
+
# Had to do this since dsl_accessor was throwing some nilclass does not have []= nomethod error
|
|
105
|
+
# This allows user to put accelerator inside dsl block
|
|
106
|
+
# @example
|
|
107
|
+
# accelerator "Ctrl-X"
|
|
108
|
+
def accelerator(*val)
|
|
109
|
+
if val.empty?
|
|
110
|
+
return @accelerator
|
|
111
|
+
else
|
|
112
|
+
@accelerator = val[0]
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
def on_enter #item
|
|
116
|
+
highlight
|
|
117
|
+
#@parent.window.wmove @row, @col+1 # 2011-09-25 V1.3.1 NO EFFECT
|
|
118
|
+
end
|
|
119
|
+
def on_leave
|
|
120
|
+
highlight false
|
|
121
|
+
end
|
|
122
|
+
## XXX it could be a menu again
|
|
123
|
+
# We should not be firing a :NO_MENUITEMS
|
|
124
|
+
def fire
|
|
125
|
+
$log.debug ">>>fire menuitem : #{@text} #{@command} "
|
|
126
|
+
@command.call self, *@args if !@command.nil?
|
|
127
|
+
@parent.clear_menus
|
|
128
|
+
return :CLOSE # added 2009-01-02 00:09 to close only actions, not submenus
|
|
129
|
+
end
|
|
130
|
+
def highlight tf=true
|
|
131
|
+
if @parent.nil? or @parent.window.nil?
|
|
132
|
+
#$log.debug "HL XXX #{self} parent nil"
|
|
133
|
+
#$log.debug "HL XXX #{self} - > #{@parent} parent nil"
|
|
134
|
+
end
|
|
135
|
+
if tf
|
|
136
|
+
#color = $datacolor
|
|
137
|
+
#@parent.window.mvchgat(y=@row, x=1, @width, Ncurses::A_NORMAL, color, nil)
|
|
138
|
+
# above line did not work in vt100, 200 terminals, next works.
|
|
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
|
|
144
|
+
else
|
|
145
|
+
repaint
|
|
146
|
+
end
|
|
147
|
+
@parent.window.wrefresh unless @parent.window.nil? ## XXX 2009-01-21 22:00
|
|
148
|
+
end
|
|
149
|
+
def repaint # menuitem.repaint
|
|
150
|
+
if @parent.nil? or @parent.window.nil?
|
|
151
|
+
$log.debug "repaint #{self} parent nil"
|
|
152
|
+
# return
|
|
153
|
+
end
|
|
154
|
+
r = @row
|
|
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)
|
|
164
|
+
if @enabled # 2010-09-10 23:56
|
|
165
|
+
if !@accelerator.nil?
|
|
166
|
+
# FIXME add c earlier 0 was offset
|
|
167
|
+
@parent.window.printstring( r, (@width+1)-@accelerator.length, @accelerator, acolor)
|
|
168
|
+
elsif !@mnemonic.nil?
|
|
169
|
+
m = @mnemonic
|
|
170
|
+
ix = text.index(m) || text.index(m.swapcase)
|
|
171
|
+
charm = text[ix,1]
|
|
172
|
+
#@parent.window.printstring( r, ix+1, charm, $datacolor) if !ix.nil?
|
|
173
|
+
# prev line changed since not working in vt100 and vt200
|
|
174
|
+
@parent.window.printstring( r, ix+1, charm, $reversecolor, 'reverse') if !ix.nil?
|
|
175
|
+
end
|
|
176
|
+
#@parent.window.wmove r, c # NO EFFECT
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
def destroy
|
|
180
|
+
$log.debug "DESTROY menuitem #{@text}"
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
## class Menu. Contains menuitems, and can be a menuitem itself.
|
|
184
|
+
# Opens out another list of menuitems.
|
|
185
|
+
class Menu < MenuItem
|
|
186
|
+
attr_accessor :parent
|
|
187
|
+
attr_accessor :row
|
|
188
|
+
attr_accessor :col
|
|
189
|
+
attr_accessor :coffset
|
|
190
|
+
attr_accessor :width
|
|
191
|
+
attr_accessor :enabled
|
|
192
|
+
attr_reader :text
|
|
193
|
+
attr_reader :items
|
|
194
|
+
attr_reader :window
|
|
195
|
+
attr_reader :panel
|
|
196
|
+
attr_reader :current_menu
|
|
197
|
+
attr_reader :row_margin ## 2009-01-21 12:06 NEW
|
|
198
|
+
## this keeps a stack of menus. if we coud somehow put this in
|
|
199
|
+
# menubar would be great.
|
|
200
|
+
@@menus = []
|
|
201
|
+
@@row = 0
|
|
202
|
+
@@col = 0
|
|
203
|
+
|
|
204
|
+
def initialize text, &block
|
|
205
|
+
@text = text
|
|
206
|
+
@items = []
|
|
207
|
+
@enabled = true
|
|
208
|
+
@current_menu = []
|
|
209
|
+
super text, nil, &block
|
|
210
|
+
@row ||=10
|
|
211
|
+
@col ||=10
|
|
212
|
+
@coffset = 0
|
|
213
|
+
@@menus ||= []
|
|
214
|
+
@active_index = nil # 2011-09-25 V1.3.1 otherwise crashing in select_right
|
|
215
|
+
end
|
|
216
|
+
## called upon firing so when we next show menubar there are not any left overs in here.
|
|
217
|
+
def clear_menus
|
|
218
|
+
@@menus = []
|
|
219
|
+
end
|
|
220
|
+
def to_s
|
|
221
|
+
@text
|
|
222
|
+
end
|
|
223
|
+
# item could be menuitem or another menu (precreated)
|
|
224
|
+
def add menuitem
|
|
225
|
+
#$log.debug " YYYY inside add menuitem #{menuitem.text} "
|
|
226
|
+
@items << menuitem
|
|
227
|
+
return self
|
|
228
|
+
end
|
|
229
|
+
alias :<< :add
|
|
230
|
+
|
|
231
|
+
# add item method which could be used from blocks
|
|
232
|
+
# add 2010-09-10 12:20 simplifying
|
|
233
|
+
def item text, mnem=nil, &block
|
|
234
|
+
#$log.debug "YYYY inside M: menuitem text #{text} "
|
|
235
|
+
m = MenuItem.new text, mnem, &block
|
|
236
|
+
add m
|
|
237
|
+
return m
|
|
238
|
+
end
|
|
239
|
+
# create a menu within a menu
|
|
240
|
+
# add menu method which could be used from blocks
|
|
241
|
+
# add 2010-09-10 12:20 simplifying
|
|
242
|
+
def menu text, &block
|
|
243
|
+
#$log.debug "YYYY inside M: menu text #{text} "
|
|
244
|
+
m = Menu.new text, &block
|
|
245
|
+
add m
|
|
246
|
+
return m
|
|
247
|
+
end
|
|
248
|
+
def insert_separator ix
|
|
249
|
+
@items.insert ix, MenuSeparator.new
|
|
250
|
+
end
|
|
251
|
+
def add_separator
|
|
252
|
+
@items << MenuSeparator.new
|
|
253
|
+
end
|
|
254
|
+
alias :separator :add_separator
|
|
255
|
+
|
|
256
|
+
## added 2009-01-21 12:09 NEW
|
|
257
|
+
def get_item i
|
|
258
|
+
@items[i]
|
|
259
|
+
end
|
|
260
|
+
## added 2009-01-21 12:09 NEW
|
|
261
|
+
def remove n
|
|
262
|
+
if n.is_a? Fixnum
|
|
263
|
+
@items.delete_at n
|
|
264
|
+
else
|
|
265
|
+
@items.delete n
|
|
266
|
+
end
|
|
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
|
|
274
|
+
# menu -
|
|
275
|
+
def fire
|
|
276
|
+
$log.debug "menu fire called: #{text} "
|
|
277
|
+
if @window.nil?
|
|
278
|
+
#repaint
|
|
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
|
|
303
|
+
if !@parent.is_a? RubyCurses::MenuBar
|
|
304
|
+
@parent.current_menu << self
|
|
305
|
+
@@menus << self # NEW
|
|
306
|
+
end
|
|
307
|
+
else
|
|
308
|
+
### shouod this not just show ?
|
|
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
|
|
313
|
+
end
|
|
314
|
+
#@action.call if !@action.nil?
|
|
315
|
+
end
|
|
316
|
+
# user has clicked down, we shoud display items
|
|
317
|
+
# DRAW menuitems
|
|
318
|
+
def repaint # menu.repaint
|
|
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
|
|
322
|
+
#$log.debug "menu repaint: #{text} row #{@row} col #{@col} "
|
|
323
|
+
@color_pair = get_color($reversecolor, @color, @bgcolor)
|
|
324
|
+
if !@parent.is_a? RubyCurses::MenuBar
|
|
325
|
+
@parent.window.printstring( @row, 0, "|%-*s>|" % [@width-1, text], @color_pair)
|
|
326
|
+
@parent.window.refresh
|
|
327
|
+
end
|
|
328
|
+
if @window.nil?
|
|
329
|
+
#create_window
|
|
330
|
+
else
|
|
331
|
+
@window.show
|
|
332
|
+
select_item 0
|
|
333
|
+
@window.refresh
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
##
|
|
337
|
+
# recursive if given one not enabled goes to next enabled
|
|
338
|
+
def select_item ix0
|
|
339
|
+
return if @items.nil? or @items.empty?
|
|
340
|
+
#$log.debug "insdie select item : #{ix0} active: #{@active_index}"
|
|
341
|
+
if !@active_index.nil?
|
|
342
|
+
@items[@active_index].on_leave
|
|
343
|
+
end
|
|
344
|
+
previtem = @active_index
|
|
345
|
+
@active_index = ix0
|
|
346
|
+
if @items[ix0].enabled
|
|
347
|
+
@items[ix0].on_enter
|
|
348
|
+
else
|
|
349
|
+
#$log.debug "insdie sele nxt item ENABLED FALSE : #{ix0}"
|
|
350
|
+
if @active_index > previtem
|
|
351
|
+
select_next_item
|
|
352
|
+
else
|
|
353
|
+
select_prev_item
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
@window.refresh
|
|
357
|
+
end
|
|
358
|
+
def select_next_item
|
|
359
|
+
return if @items.nil? or @items.empty?
|
|
360
|
+
#$log.debug "insdie sele nxt item : #{@active_index}"
|
|
361
|
+
@active_index = -1 if @active_index.nil?
|
|
362
|
+
if @active_index < @items.length-1
|
|
363
|
+
select_item @active_index + 1
|
|
364
|
+
else
|
|
365
|
+
# select_item 0
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
def select_prev_item
|
|
369
|
+
return if @items.nil? or @items.empty?
|
|
370
|
+
#$log.debug "insdie sele prv item : #{@active_index}"
|
|
371
|
+
if @active_index > 0
|
|
372
|
+
select_item @active_index - 1
|
|
373
|
+
else
|
|
374
|
+
#select_item @items.length-1
|
|
375
|
+
end
|
|
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
|
|
417
|
+
def on_enter # menu.on_enter
|
|
418
|
+
#$log.debug "menu onenter: #{text} #{@row} #{@col} "
|
|
419
|
+
# call parent method. XXX
|
|
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
|
|
424
|
+
highlight
|
|
425
|
+
#end
|
|
426
|
+
if !@window.nil? #and @parent.selected
|
|
427
|
+
#$log.debug "menu onenter: #{text} calling window,show"
|
|
428
|
+
@window.show
|
|
429
|
+
select_item 0
|
|
430
|
+
elsif @parent.is_a? RubyCurses::MenuBar and @parent.selected
|
|
431
|
+
# only on the top level do we open a window if a previous one was opened
|
|
432
|
+
#$log.debug "menu onenter: #{text} calling repaint CLASS: #{@parent.class}"
|
|
433
|
+
# repaint
|
|
434
|
+
create_window
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
def on_leave # menu.on_leave
|
|
438
|
+
#$log.debug "menu onleave: #{text} #{@row} #{@col} "
|
|
439
|
+
# call parent method. XXX
|
|
440
|
+
@color_pair ||= get_color($reversecolor, @color, @bgcolor)
|
|
441
|
+
if @parent.is_a? RubyCurses::MenuBar
|
|
442
|
+
# @parent.window.printstring( @row, @col, " %s " % text, $reversecolor) # changed 2011 2011-09-24
|
|
443
|
+
@parent.window.printstring( @row, @col, " %s " % text, @color_pair)
|
|
444
|
+
@window.hide if !@window.nil?
|
|
445
|
+
else
|
|
446
|
+
#$log.debug "MENU SUBMEN. menu onleave: #{text} #{@row} #{@col} "
|
|
447
|
+
# parent is a menu
|
|
448
|
+
highlight false
|
|
449
|
+
#@parent.current_menu.pop
|
|
450
|
+
#@@menus.pop
|
|
451
|
+
#destroy
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
def highlight tf=true # menu
|
|
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 }
|
|
496
|
+
@win = VER::Window.new(@layout)
|
|
497
|
+
@window = @win
|
|
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));
|
|
501
|
+
@panel = @win.panel
|
|
502
|
+
#@window.printstring( 0, 0, "+%s+" % ("-"*@width), $reversecolor)
|
|
503
|
+
@window.printstring( 0, 0, "+%s+" % ("-"*(ww1)), @rev_color_pair)
|
|
504
|
+
saved_r = 1
|
|
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}"
|
|
510
|
+
@items.each do |item|
|
|
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
|
|
519
|
+
item.row = r
|
|
520
|
+
item.col = c
|
|
521
|
+
item.coffset = @coffset+@width+margin # margins???
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
item.width = @width
|
|
525
|
+
#item.window = @window
|
|
526
|
+
item.parent = self
|
|
527
|
+
item.color = @color; item.bgcolor = @bgcolor
|
|
528
|
+
item.repaint
|
|
529
|
+
r+=1
|
|
530
|
+
end
|
|
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
|
|
536
|
+
@window.refresh
|
|
537
|
+
return @window
|
|
538
|
+
end
|
|
539
|
+
# private
|
|
540
|
+
def array_width a
|
|
541
|
+
longest = a.max {|a,b| a.to_s.length <=> b.to_s.length }
|
|
542
|
+
#$log.debug "array width #{longest}"
|
|
543
|
+
longest.to_s.length
|
|
544
|
+
end
|
|
545
|
+
def destroy
|
|
546
|
+
$log.debug "DESTRY menu #{@text}"
|
|
547
|
+
return if @window.nil?
|
|
548
|
+
@visible = false
|
|
549
|
+
panel = @window.panel
|
|
550
|
+
Ncurses::Panel.del_panel(panel.pointer) if !panel.nil?
|
|
551
|
+
@window.delwin if !@window.nil?
|
|
552
|
+
@items.each do |item|
|
|
553
|
+
#next if item == :SEPARATOR
|
|
554
|
+
item.destroy
|
|
555
|
+
end
|
|
556
|
+
@window = nil
|
|
557
|
+
end
|
|
558
|
+
# menu LEFT, RIGHT, DOWN, UP, ENTER
|
|
559
|
+
# item could be menuitem or another menu
|
|
560
|
+
#
|
|
561
|
+
def handle_key ch
|
|
562
|
+
if !@current_menu.empty?
|
|
563
|
+
cmenu = @current_menu.last
|
|
564
|
+
else
|
|
565
|
+
cmenu = self
|
|
566
|
+
end
|
|
567
|
+
if !@@menus.empty?
|
|
568
|
+
cmenu = @@menus.last
|
|
569
|
+
else
|
|
570
|
+
cmenu = self
|
|
571
|
+
end
|
|
572
|
+
case ch
|
|
573
|
+
when KEY_DOWN
|
|
574
|
+
cmenu.select_next_item
|
|
575
|
+
#return cmenu.fire # XXX 2010-10-16 21:39 trying out
|
|
576
|
+
if cmenu.is_a? RubyCurses::Menu
|
|
577
|
+
#alert "is a menu" # this gets triggered even when we are on items
|
|
578
|
+
end
|
|
579
|
+
when KEY_UP
|
|
580
|
+
cmenu.select_prev_item
|
|
581
|
+
when KEY_ENTER, 10, 13, 32 # added 32 2008-11-27 23:50
|
|
582
|
+
return cmenu.fire
|
|
583
|
+
when KEY_LEFT
|
|
584
|
+
if cmenu.parent.is_a? RubyCurses::Menu
|
|
585
|
+
#$log.debug "LEFT IN MENU : #{cmenu.parent.class} len: #{cmenu.parent.current_menu.length}"
|
|
586
|
+
#$log.debug "left IN MENU : #{cmenu.parent.class} len: #{cmenu.current_menu.length}"
|
|
587
|
+
end
|
|
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
|
|
605
|
+
end
|
|
606
|
+
when KEY_RIGHT
|
|
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
|
|
613
|
+
#$log.debug "right IN MENU : #{cmenu.parent.class} len: #{cmenu.parent.current_menu.length}"
|
|
614
|
+
#$log.debug "right IN MENU : #{cmenu.parent.class} len: #{cmenu.current_menu.length}"
|
|
615
|
+
end
|
|
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
|
|
629
|
+
end
|
|
630
|
+
else
|
|
631
|
+
ret = check_mnemonics cmenu, ch
|
|
632
|
+
return ret
|
|
633
|
+
end
|
|
634
|
+
end
|
|
635
|
+
##
|
|
636
|
+
# checks given key against current menu's items and fires key if
|
|
637
|
+
# added on 2008-11-27 12:07
|
|
638
|
+
def check_mnemonics cmenu, ch
|
|
639
|
+
# $log.debug "inside check_mnemonics #{ch}"
|
|
640
|
+
key = ch.chr.downcase rescue ""
|
|
641
|
+
cmenu.items.each do |item|
|
|
642
|
+
next if !item.respond_to? :mnemonic or item.mnemonic.nil?
|
|
643
|
+
# $log.debug "inside check_mnemonics #{item.mnemonic}"
|
|
644
|
+
if key == item.mnemonic.downcase && item.enabled # 2010-09-11 00:03 enabled
|
|
645
|
+
ret = item.fire
|
|
646
|
+
return ret #0 2009-01-23 00:45
|
|
647
|
+
end
|
|
648
|
+
end
|
|
649
|
+
return :UNHANDLED
|
|
650
|
+
end
|
|
651
|
+
## menu
|
|
652
|
+
def show # menu.show
|
|
653
|
+
#$log.debug "show (menu) : #{@text} "
|
|
654
|
+
if @window.nil?
|
|
655
|
+
create_window #@col+@width
|
|
656
|
+
end
|
|
657
|
+
@window.show
|
|
658
|
+
select_item 0
|
|
659
|
+
end
|
|
660
|
+
end
|
|
661
|
+
##
|
|
662
|
+
# An application related menubar.
|
|
663
|
+
# Currently, I am adding this to a form. But should this not be application specific ?
|
|
664
|
+
# It should popup no matter which window you are on ?? XXX
|
|
665
|
+
class MenuBar
|
|
666
|
+
attr_reader :items
|
|
667
|
+
attr_reader :window
|
|
668
|
+
attr_reader :panel
|
|
669
|
+
attr_reader :selected
|
|
670
|
+
attr_reader :text # temp 2011-09-24 V1.3.1
|
|
671
|
+
attr_accessor :visible
|
|
672
|
+
attr_accessor :active_index
|
|
673
|
+
attr_accessor :state # normal, selected, highlighted
|
|
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
|
|
677
|
+
def initialize &block
|
|
678
|
+
@window = nil
|
|
679
|
+
@text = "menubar"
|
|
680
|
+
@items = []
|
|
681
|
+
init_vars
|
|
682
|
+
@visible = false
|
|
683
|
+
@cols = Ncurses.COLS-1
|
|
684
|
+
instance_eval &block if block_given?
|
|
685
|
+
end
|
|
686
|
+
def init_vars
|
|
687
|
+
@active_index = 0
|
|
688
|
+
@repaint_required = true
|
|
689
|
+
end
|
|
690
|
+
def focusable
|
|
691
|
+
false
|
|
692
|
+
end
|
|
693
|
+
# add a precreated menu
|
|
694
|
+
def add menu
|
|
695
|
+
#$log.debug "YYYY inside MB: add #{menu.text} "
|
|
696
|
+
@items << menu
|
|
697
|
+
return self
|
|
698
|
+
end
|
|
699
|
+
alias :<< :add
|
|
700
|
+
|
|
701
|
+
# add a menu through the block, this would happen through instance eval
|
|
702
|
+
# 2010-09-10 12:07 added while simplifying the interface
|
|
703
|
+
# this calls add so you get the MB back, not a ref to the menu created NOTE
|
|
704
|
+
def menu text, &block
|
|
705
|
+
#$log.debug "YYYY inside MB: menu text #{text} "
|
|
706
|
+
m = Menu.new text, &block
|
|
707
|
+
m.color = @color
|
|
708
|
+
m.bgcolor = @bgcolor
|
|
709
|
+
add m
|
|
710
|
+
return m
|
|
711
|
+
end
|
|
712
|
+
def next_menu
|
|
713
|
+
#$log.debug "next meu: #{@active_index} "
|
|
714
|
+
if @active_index < @items.length-1
|
|
715
|
+
set_menu @active_index + 1
|
|
716
|
+
else
|
|
717
|
+
set_menu 0
|
|
718
|
+
end
|
|
719
|
+
end
|
|
720
|
+
def prev_menu
|
|
721
|
+
#$log.debug "prev meu: #{@active_index} "
|
|
722
|
+
if @active_index > 0
|
|
723
|
+
set_menu @active_index-1
|
|
724
|
+
else
|
|
725
|
+
set_menu @items.length-1
|
|
726
|
+
end
|
|
727
|
+
end
|
|
728
|
+
def set_menu index
|
|
729
|
+
#$log.debug "set meu: #{@active_index} #{index}"
|
|
730
|
+
menu = @items[@active_index]
|
|
731
|
+
menu.on_leave # hide its window, if open
|
|
732
|
+
@active_index = index
|
|
733
|
+
menu = @items[@active_index]
|
|
734
|
+
menu.on_enter #display window, if previous was displayed
|
|
735
|
+
@window.wmove menu.row, menu.col
|
|
736
|
+
# menu.show
|
|
737
|
+
# menu.window.wrefresh # XXX we need this
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
def keep_visible flag=nil
|
|
741
|
+
return @keep_visible unless flag
|
|
742
|
+
@keep_visible = flag
|
|
743
|
+
@visible = flag
|
|
744
|
+
self
|
|
745
|
+
end
|
|
746
|
+
# menubar LEFT, RIGHT, DOWN
|
|
747
|
+
def handle_keys
|
|
748
|
+
@selected = false
|
|
749
|
+
@repaint_required = true # added 2011-12-12 otherwise keeps repainting and you see a flicker
|
|
750
|
+
@toggle_key ||= 27 # default switch off with ESC, if nothing else defined
|
|
751
|
+
set_menu 0
|
|
752
|
+
begin
|
|
753
|
+
catch(:menubarclose) do
|
|
754
|
+
while((ch = @window.getchar()) != @toggle_key )
|
|
755
|
+
#$log.debug "menuubar inside handle_keys : #{ch}" if ch != -1
|
|
756
|
+
case ch
|
|
757
|
+
when -1
|
|
758
|
+
next
|
|
759
|
+
when KEY_DOWN
|
|
760
|
+
#$log.debug "insdie keyDOWN : #{ch}"
|
|
761
|
+
if !@selected
|
|
762
|
+
current_menu.fire
|
|
763
|
+
else
|
|
764
|
+
current_menu.handle_key ch
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
@selected = true
|
|
768
|
+
when KEY_ENTER, 10, 13, 32
|
|
769
|
+
@selected = true
|
|
770
|
+
#$log.debug " mb insdie ENTER : #{current_menu}"
|
|
771
|
+
ret = current_menu.handle_key ch
|
|
772
|
+
#$log.debug "ret = #{ret} mb insdie ENTER : #{current_menu}"
|
|
773
|
+
#break; ## 2008-12-29 18:00 This will close after firing
|
|
774
|
+
#anything
|
|
775
|
+
break if ret == :CLOSE
|
|
776
|
+
when KEY_UP
|
|
777
|
+
#$log.debug " mb insdie keyUPP : #{ch}"
|
|
778
|
+
current_menu.handle_key ch
|
|
779
|
+
when KEY_LEFT
|
|
780
|
+
#$log.debug " mb insdie KEYLEFT : #{ch}"
|
|
781
|
+
ret = current_menu.handle_key ch
|
|
782
|
+
prev_menu if ret == :UNHANDLED
|
|
783
|
+
#display_items if @selected
|
|
784
|
+
when KEY_RIGHT
|
|
785
|
+
#$log.debug " mb insdie KEYRIGHT : #{ch}"
|
|
786
|
+
ret = current_menu.handle_key ch
|
|
787
|
+
next_menu if ret == :UNHANDLED
|
|
788
|
+
when ?\C-g.getbyte(0) # abort
|
|
789
|
+
throw :menubarclose
|
|
790
|
+
else
|
|
791
|
+
#$log.debug " mb insdie ELSE : #{ch}"
|
|
792
|
+
ret = current_menu.handle_key ch
|
|
793
|
+
if ret == :UNHANDLED
|
|
794
|
+
Ncurses.beep
|
|
795
|
+
else
|
|
796
|
+
break # we handled a menu action, close menubar (THIS WORKS FOR MNEMONICS ONLY and always)
|
|
797
|
+
end
|
|
798
|
+
end
|
|
799
|
+
Ncurses::Panel.update_panels();
|
|
800
|
+
Ncurses.doupdate();
|
|
801
|
+
|
|
802
|
+
@window.wrefresh
|
|
803
|
+
end
|
|
804
|
+
end # catch
|
|
805
|
+
ensure
|
|
806
|
+
#ensure is required becos one can throw a :close
|
|
807
|
+
$log.debug " DESTROY IN ENSURE"
|
|
808
|
+
current_menu.clear_menus #@@menus = [] # added 2009-01-23 13:21
|
|
809
|
+
@repaint_required = false
|
|
810
|
+
destroy # Note that we destroy the menu bar upon exit
|
|
811
|
+
end
|
|
812
|
+
end
|
|
813
|
+
def current_menu
|
|
814
|
+
@items[@active_index]
|
|
815
|
+
end
|
|
816
|
+
# called by set_menu_bar in widget.rb (class Form).
|
|
817
|
+
def toggle
|
|
818
|
+
# added keeping it visible, 2011-10-7 being tested in dbdemo
|
|
819
|
+
if @keep_visible
|
|
820
|
+
init_vars
|
|
821
|
+
show
|
|
822
|
+
@items[0].highlight
|
|
823
|
+
@window.ungetch(KEY_DOWN)
|
|
824
|
+
return
|
|
825
|
+
end
|
|
826
|
+
#@items.each { |i| $log.debug " ITEM DDD : #{i.text}" }
|
|
827
|
+
@visible = !@visible
|
|
828
|
+
if !@visible
|
|
829
|
+
hide
|
|
830
|
+
else
|
|
831
|
+
init_vars
|
|
832
|
+
show
|
|
833
|
+
end
|
|
834
|
+
end
|
|
835
|
+
def hide
|
|
836
|
+
@visible = false
|
|
837
|
+
@window.hide if !@window.nil? # seems to cause auto-firing when we resume toggle 2011-09-26
|
|
838
|
+
end
|
|
839
|
+
def show
|
|
840
|
+
@visible = true
|
|
841
|
+
if @window.nil?
|
|
842
|
+
repaint # XXX FIXME
|
|
843
|
+
else
|
|
844
|
+
@window.show
|
|
845
|
+
end
|
|
846
|
+
end
|
|
847
|
+
## menubar
|
|
848
|
+
# TODO: check for menu to be flush right (only for last one).
|
|
849
|
+
# TODO: repaint only if needed
|
|
850
|
+
def repaint
|
|
851
|
+
return if !@visible
|
|
852
|
+
return unless @repaint_required
|
|
853
|
+
@repaint_required = false
|
|
854
|
+
@color_pair = get_color($reversecolor, @color, @bgcolor)
|
|
855
|
+
@window ||= create_window_menubar
|
|
856
|
+
#@window.printstring( 0, 0, "%-*s" % [@cols," "], @color_pair) # this becomes blank in some terms
|
|
857
|
+
c = 1; r = 0;
|
|
858
|
+
@items.each do |item|
|
|
859
|
+
item.row = r; item.col = c; item.coffset = c; item.parent = self
|
|
860
|
+
item.color = @color
|
|
861
|
+
item.bgcolor = @bgcolor
|
|
862
|
+
@window.printstring( r, c, " %s " % item.text, @color_pair)
|
|
863
|
+
# 2011-09-26 V1.3.1 quick dirty highlighting of first menu on menubar
|
|
864
|
+
# on opening since calling highlight was giving bug in parent.width
|
|
865
|
+
#if c == 1
|
|
866
|
+
#att = Ncurses::A_REVERSE
|
|
867
|
+
#@window.mvchgat(y=r, x=c+1, item.text.length+1, att, @color_pair, nil)
|
|
868
|
+
#end
|
|
869
|
+
c += (item.text.length + 2)
|
|
870
|
+
end
|
|
871
|
+
#@items[0].on_enter # 2011-09-25 V1.3.1 caused issues when toggling, first item fired on DOWN
|
|
872
|
+
@items[0].highlight unless @keep_visible # 2011-09-26 V1.3.1 fixed to take both cases into account
|
|
873
|
+
@window.wrefresh
|
|
874
|
+
end
|
|
875
|
+
def create_window_menubar
|
|
876
|
+
@layout = { :height => 1, :width => 0, :top => 0, :left => 0 }
|
|
877
|
+
@win = VER::Window.new(@layout)
|
|
878
|
+
@window = @win
|
|
879
|
+
att = get_attrib @attr
|
|
880
|
+
@win.bkgd(Ncurses.COLOR_PAIR(5)); # <---- FIXME
|
|
881
|
+
len = @window.width
|
|
882
|
+
len = Ncurses.COLS-0 if len == 0
|
|
883
|
+
# print a bar across the screen , which hopefully will not go blank in some terms
|
|
884
|
+
@window.attron(Ncurses.COLOR_PAIR(@color_pair) | att)
|
|
885
|
+
@window.mvhline(0, 0, 1, len)
|
|
886
|
+
@window.attroff(Ncurses.COLOR_PAIR(@color_pair) | att)
|
|
887
|
+
@panel = @win.panel
|
|
888
|
+
return @window
|
|
889
|
+
end
|
|
890
|
+
def destroy
|
|
891
|
+
$log.debug "DESTRY menubar "
|
|
892
|
+
|
|
893
|
+
# when we close, but keep visible, we don't want menu to still be hightlighted
|
|
894
|
+
# added on 2011-12-12
|
|
895
|
+
menu = @items[@active_index]
|
|
896
|
+
menu.on_leave # hide its window, if open
|
|
897
|
+
|
|
898
|
+
@items.each do |item|
|
|
899
|
+
item.destroy
|
|
900
|
+
end
|
|
901
|
+
# TODO the current menu should not be highlighted
|
|
902
|
+
return if @keep_visible
|
|
903
|
+
@visible = false
|
|
904
|
+
panel = @window.panel
|
|
905
|
+
Ncurses::Panel.del_panel(panel.pointer) if !panel.nil?
|
|
906
|
+
@window.delwin if !@window.nil?
|
|
907
|
+
@window = nil
|
|
908
|
+
end
|
|
909
|
+
end # menubar
|
|
910
|
+
|
|
911
|
+
class CheckBoxMenuItem < MenuItem
|
|
912
|
+
attr_reader :checkbox
|
|
913
|
+
def initialize text, mnemonic=nil, &block
|
|
914
|
+
@checkbox = CheckBox.new nil
|
|
915
|
+
@checkbox.text text
|
|
916
|
+
super
|
|
917
|
+
end
|
|
918
|
+
def onvalue
|
|
919
|
+
@checkbox.onvalue onvalue
|
|
920
|
+
end
|
|
921
|
+
def offvalue
|
|
922
|
+
@checkbox.onvalue offvalue
|
|
923
|
+
end
|
|
924
|
+
def text=(t) # stack level too deep if no = .????
|
|
925
|
+
@checkbox.text t
|
|
926
|
+
end
|
|
927
|
+
def to_s
|
|
928
|
+
" #{text} "
|
|
929
|
+
end
|
|
930
|
+
def getvalue
|
|
931
|
+
checkbox.getvalue
|
|
932
|
+
end
|
|
933
|
+
def getvalue_for_paint
|
|
934
|
+
"|%-*s|" % [@width, checkbox.getvalue_for_paint]
|
|
935
|
+
end
|
|
936
|
+
def fire
|
|
937
|
+
checkbox.toggle
|
|
938
|
+
super
|
|
939
|
+
repaint
|
|
940
|
+
highlight true
|
|
941
|
+
end
|
|
942
|
+
def repaint # checkbox
|
|
943
|
+
# FIXME need @color_pair here
|
|
944
|
+
@color_pair ||= get_color($reversecolor, @color, @bgcolor)
|
|
945
|
+
@parent.window.printstring( row, 0, getvalue_for_paint, @color_pair)
|
|
946
|
+
parent.window.wrefresh
|
|
947
|
+
end
|
|
948
|
+
def method_missing(sym, *args)
|
|
949
|
+
if checkbox.respond_to? sym
|
|
950
|
+
#$log.debug("calling CHECKBOXMENU #{sym} called #{args[0]}")
|
|
951
|
+
checkbox.send(sym, args)
|
|
952
|
+
else
|
|
953
|
+
$log.error("ERROR CHECKBOXMENU #{sym} called")
|
|
954
|
+
end
|
|
955
|
+
end
|
|
956
|
+
end # class
|
|
957
|
+
|
|
958
|
+
end # modul
|