rbhex-core 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,913 @@
|
|
1
|
+
# ----------------------------------------------------------------------------- #
|
2
|
+
# File: window.rb
|
3
|
+
# Description: A wrapper over window
|
4
|
+
# Author: rkumar http://github.com/rkumar/rbcurse/
|
5
|
+
# Date: Around for a long time
|
6
|
+
# License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
7
|
+
# Last update: 2013-03-25 12:38
|
8
|
+
#
|
9
|
+
# == CHANGED
|
10
|
+
# removed Pad and Subwin to lib/ver/rpad.rb - hopefully I've seen the last of both
|
11
|
+
#
|
12
|
+
# == TODO
|
13
|
+
# strip and remove cruft. Now that I've stopped using pad, can we remove
|
14
|
+
# the prv_printstring nonsense.
|
15
|
+
# ----------------------------------------------------------------------------- #
|
16
|
+
#
|
17
|
+
require 'rbhex/core/system/ncurses'
|
18
|
+
require 'rbhex/core/system/panel'
|
19
|
+
require 'rbhex/core/include/chunk'
|
20
|
+
# this is since often windows are declared with 0 height or width and this causes
|
21
|
+
# crashes in the most unlikely places. This prevceents me from having to write ternary
|
22
|
+
# e.g.
|
23
|
+
# @layout[:width].ifzero(FFI::NCurses::LINES-2)
|
24
|
+
class Fixnum
|
25
|
+
def ifzero v
|
26
|
+
return self if self != 0
|
27
|
+
return v
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module VER
|
32
|
+
class Window
|
33
|
+
attr_reader :width, :height, :top, :left
|
34
|
+
attr_accessor :layout # hash containing hwtl
|
35
|
+
attr_reader :panel # reader requires so he can del it in end
|
36
|
+
attr_reader :window_type # window or pad to distinguish 2009-11-02 23:11
|
37
|
+
attr_accessor :name # more for debugging log files. 2010-02-02 19:58
|
38
|
+
attr_accessor :modified # has it been modified and may need a refresh
|
39
|
+
|
40
|
+
# @param [Array, Hash] window coordinates (ht, w, top, left)
|
41
|
+
# or
|
42
|
+
# @param [int, int, int, int] window coordinates (ht, w, top, left)
|
43
|
+
# 2011-09-21 allowing array, or 4 ints, in addition to hash @since 1.3.1
|
44
|
+
def initialize(*args)
|
45
|
+
|
46
|
+
case args.size
|
47
|
+
when 1
|
48
|
+
case args[0]
|
49
|
+
when Array, Hash
|
50
|
+
layout = args[0]
|
51
|
+
else
|
52
|
+
raise ArgumentError, "Window expects 4 ints, array of 4 ints, or Hash in constructor"
|
53
|
+
end
|
54
|
+
when 4
|
55
|
+
layout = { :height => args[0], :width => args[1], :top => args[2], :left => args[3] }
|
56
|
+
end
|
57
|
+
|
58
|
+
@visible = true
|
59
|
+
reset_layout(layout)
|
60
|
+
|
61
|
+
#$log.debug "XXX:WINDOW got h #{@height}, w #{@width}, t #{@top}, l #{@left} "
|
62
|
+
|
63
|
+
@height = FFI::NCurses.LINES if @height == 0 # 2011-11-14 added since tired of checking for zero
|
64
|
+
@width = FFI::NCurses.COLS if @width == 0
|
65
|
+
|
66
|
+
@window = FFI::NCurses.newwin(@height, @width, @top, @left) # added FFI 2011-09-6
|
67
|
+
@panel = Ncurses::Panel.new(@window) # added FFI 2011-09-6
|
68
|
+
#$error_message_row = $status_message_row = Ncurses.LINES-1
|
69
|
+
$error_message_row ||= Ncurses.LINES-1
|
70
|
+
$error_message_col ||= 1 # ask (bottomline) uses 0 as default so you can have mismatch. XXX
|
71
|
+
$status_message ||= RubyCurses::Variable.new # in case not an App
|
72
|
+
|
73
|
+
$key_map ||= :vim
|
74
|
+
$esc_esc = true; # gove me double esc as 2727 so i can map it.
|
75
|
+
init_vars
|
76
|
+
|
77
|
+
|
78
|
+
end
|
79
|
+
def init_vars
|
80
|
+
@window_type = :WINDOW
|
81
|
+
Ncurses::keypad(@window, true)
|
82
|
+
# Added this so we can get Esc, and also C-c pressed in succession does not crash system
|
83
|
+
# 2011-12-20 half-delay crashes system as does cbreak
|
84
|
+
#This causes us to be unable to process gg qq since getch won't wait.
|
85
|
+
#Ncurses::nodelay(@window, bf = true)
|
86
|
+
# wtimeout was causing RESIZE sigwinch to only happen after pressing a key
|
87
|
+
#Ncurses::wtimeout(@window, $ncurses_timeout || 500) # will wait a second on wgetch so we can get gg and qq
|
88
|
+
@stack = []
|
89
|
+
@name ||="#{self}"
|
90
|
+
@modified = true
|
91
|
+
$catch_alt_digits ||= false # is this where is should put globals ? 2010-03-14 14:00 XXX
|
92
|
+
end
|
93
|
+
##
|
94
|
+
# this is an alternative constructor
|
95
|
+
def self.root_window(layout = { :height => 0, :width => 0, :top => 0, :left => 0 })
|
96
|
+
#VER::start_ncurses
|
97
|
+
@layout = layout
|
98
|
+
@window = Window.new(@layout)
|
99
|
+
@window.name = "Window::ROOTW"
|
100
|
+
@window.wrefresh
|
101
|
+
Ncurses::Panel.update_panels
|
102
|
+
return @window
|
103
|
+
end
|
104
|
+
# 2009-10-13 12:24
|
105
|
+
# not used as yet
|
106
|
+
# this is an alternative constructor
|
107
|
+
# created if you don't want to create a hash first
|
108
|
+
# 2011-09-21 V1.3.1 You can now send an array to Window constructor
|
109
|
+
def self.create_window(h=0, w=0, t=0, l=0)
|
110
|
+
layout = { :height => h, :width => w, :top => t, :left => l }
|
111
|
+
@window = Window.new(layout)
|
112
|
+
return @window
|
113
|
+
end
|
114
|
+
|
115
|
+
def resize_with(layout)
|
116
|
+
$log.debug " DARN ! This awready duz a resize!! if h or w or even top or left changed!!! XXX"
|
117
|
+
reset_layout(layout)
|
118
|
+
#@window.wresize(height, width)
|
119
|
+
wresize(height, width)
|
120
|
+
#FFI::NCurses.wresize(@window,height, width)
|
121
|
+
# this is dicey since we often change top and left in pads only for panning !! XXX
|
122
|
+
#@window.mvwin(top, left)
|
123
|
+
mvwin(top, left)
|
124
|
+
#FFI::NCurses.mvwin(@window, top, left)
|
125
|
+
end
|
126
|
+
|
127
|
+
%w[width height top left].each do |side|
|
128
|
+
eval(
|
129
|
+
"def #{side}=(n)
|
130
|
+
return if n == #{side}
|
131
|
+
@layout[:#{side}] = n
|
132
|
+
resize_with @layout
|
133
|
+
end"
|
134
|
+
)
|
135
|
+
end
|
136
|
+
# ADDED DUE TO FFI
|
137
|
+
def wrefresh
|
138
|
+
Ncurses.wrefresh(@window)
|
139
|
+
end
|
140
|
+
def delwin # 2011-09-7
|
141
|
+
Ncurses.delwin(@window)
|
142
|
+
end
|
143
|
+
def attron *args
|
144
|
+
FFI::NCurses.wattron @window, *args
|
145
|
+
end
|
146
|
+
def attroff *args
|
147
|
+
FFI::NCurses.wattroff @window, *args
|
148
|
+
end
|
149
|
+
#
|
150
|
+
# ## END FFI
|
151
|
+
|
152
|
+
def resize
|
153
|
+
resize_with(@layout)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Ncurses
|
157
|
+
|
158
|
+
def pos
|
159
|
+
return y, x
|
160
|
+
end
|
161
|
+
|
162
|
+
def y
|
163
|
+
Ncurses.getcury(@window)
|
164
|
+
end
|
165
|
+
|
166
|
+
def x
|
167
|
+
Ncurses.getcurx(@window)
|
168
|
+
end
|
169
|
+
|
170
|
+
def x=(n) move(y, n) end
|
171
|
+
def y=(n) move(n, x) end
|
172
|
+
|
173
|
+
#def move(y, x)
|
174
|
+
#return unless @visible
|
175
|
+
## Log.debug([y, x] => caller[0,4])
|
176
|
+
##@window.wmove(y, x) # bombing since ffi-ncurses 0.4.0 (maybe it was never called
|
177
|
+
##earlier. was crashing in appemail.rb testchoose.
|
178
|
+
#wmove y,x # can alias it
|
179
|
+
#end
|
180
|
+
# since include FFI is taking over, i need to force it here. not going into
|
181
|
+
# method_missing
|
182
|
+
def wmove y,x
|
183
|
+
#Ncurses.wmove @window, y, x
|
184
|
+
FFI::NCurses.wmove @window, y, x
|
185
|
+
end
|
186
|
+
alias :move :wmove
|
187
|
+
|
188
|
+
# while moving from ncurses-ruby to FFI need to pass window pointer
|
189
|
+
# for w methods as well as mvw - NOT COMING HERE due to include FFI
|
190
|
+
def OLDmethod_missing(meth, *args)
|
191
|
+
$log.debug " WWWW method missing #{meth} "
|
192
|
+
if meth[0,1]=="w" || meth[0,3] == "mvw"
|
193
|
+
$log.debug " WWWW method missing #{meth} adding window in call "
|
194
|
+
#return @window.send(meth, @window, *args)
|
195
|
+
return FFI::NCurses.send(meth, @window, *args)
|
196
|
+
else
|
197
|
+
end
|
198
|
+
if @window
|
199
|
+
if @window.respond_to? meth
|
200
|
+
@window.send(meth, *args)
|
201
|
+
else
|
202
|
+
FFI::NCurses.send( meth, *args)
|
203
|
+
end
|
204
|
+
else
|
205
|
+
FFI::NCurses.send( meth, *args)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def method_missing(name, *args)
|
210
|
+
name = name.to_s
|
211
|
+
if (name[0,2] == "mv")
|
212
|
+
test_name = name.dup
|
213
|
+
test_name[2,0] = "w" # insert "w" after"mv"
|
214
|
+
if (FFI::NCurses.respond_to?(test_name))
|
215
|
+
return FFI::NCurses.send(test_name, @window, *args)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
test_name = "w" + name
|
219
|
+
if (FFI::NCurses.respond_to?(test_name))
|
220
|
+
return FFI::NCurses.send(test_name, @window, *args)
|
221
|
+
end
|
222
|
+
FFI::NCurses.send(name, @window, *args)
|
223
|
+
end
|
224
|
+
def respond_to?(name)
|
225
|
+
name = name.to_s
|
226
|
+
if (name[0,2] == "mv" && FFI::NCurses.respond_to?("mvw" + name[2..-1]))
|
227
|
+
return true
|
228
|
+
end
|
229
|
+
FFI::NCurses.respond_to?("w" + name) || FFI::NCurses.respond_to?(name)
|
230
|
+
end
|
231
|
+
|
232
|
+
# NOTE: many of these methods using width will not work since root windows width
|
233
|
+
# is 0
|
234
|
+
def print(string, width = width)
|
235
|
+
return unless visible?
|
236
|
+
w = width == 0? Ncurses.COLS : width
|
237
|
+
waddnstr(string.to_s, w) # changed 2011 dts
|
238
|
+
end
|
239
|
+
|
240
|
+
# NOTE: many of these methods using width will not work since root windows width
|
241
|
+
# is 0
|
242
|
+
def print_yx(string, y = 0, x = 0)
|
243
|
+
w = width == 0? Ncurses.COLS : width
|
244
|
+
mvwaddnstr(y, x, string, w) # changed 2011 dts
|
245
|
+
end
|
246
|
+
|
247
|
+
# NOTE: many of these methods using width will not work since root windows width
|
248
|
+
# is 0
|
249
|
+
def print_empty_line
|
250
|
+
return unless visible?
|
251
|
+
w = getmaxx == 0? Ncurses.COLS : getmaxx
|
252
|
+
printw(' ' * w)
|
253
|
+
end
|
254
|
+
|
255
|
+
# NOTE: many of these methods using width will not work since root windows width
|
256
|
+
# is 0
|
257
|
+
def print_line(string)
|
258
|
+
w = getmaxx == 0? Ncurses.COLS : getmaxx
|
259
|
+
print(string.ljust(w))
|
260
|
+
end
|
261
|
+
|
262
|
+
# returns the actual width in case you've used a root window
|
263
|
+
# which returns a 0 for wid and ht
|
264
|
+
# NOTE: this does not work when resize , use getmaxx instead
|
265
|
+
#
|
266
|
+
def actual_width
|
267
|
+
width == 0? Ncurses.COLS : width
|
268
|
+
end
|
269
|
+
|
270
|
+
#
|
271
|
+
# returns the actual ht in case you've used a root window
|
272
|
+
# which returns a 0 for wid and ht
|
273
|
+
#
|
274
|
+
def actual_height
|
275
|
+
height == 0? Ncurses.LINES : height
|
276
|
+
end
|
277
|
+
|
278
|
+
# NOTE: many of these methods using width will not work since root windows width
|
279
|
+
# is 0
|
280
|
+
# Previously this printed a chunk as a full line, I've modified it to print on
|
281
|
+
# one line. This can be used for running text.
|
282
|
+
# NOTE 2013-03-08 - 17:02 added width so we don't overflow
|
283
|
+
def show_colored_chunks(chunks, defcolor = nil, defattr = nil, wid = 999, pcol = 0)
|
284
|
+
return unless visible?
|
285
|
+
ww = 0
|
286
|
+
chunks.each do |chunk| #|color, chunk, attrib|
|
287
|
+
case chunk
|
288
|
+
when Chunks::Chunk
|
289
|
+
color = chunk.color
|
290
|
+
attrib = chunk.attrib
|
291
|
+
text = chunk.text
|
292
|
+
|
293
|
+
## 2013-03-08 - 19:11 take care of scrolling by means of pcol
|
294
|
+
if pcol > 0
|
295
|
+
if pcol > text.length
|
296
|
+
# ignore entire chunk and reduce pcol
|
297
|
+
pcol -= text.length
|
298
|
+
next
|
299
|
+
else
|
300
|
+
# print portion of chunk and zero pcol
|
301
|
+
text = text[pcol..-1]
|
302
|
+
pcol = 0
|
303
|
+
end
|
304
|
+
end
|
305
|
+
oldw = ww
|
306
|
+
ww += text.length
|
307
|
+
if ww > wid
|
308
|
+
# if we are exceeding the width then by howmuch
|
309
|
+
rem = wid - oldw
|
310
|
+
if rem > 0
|
311
|
+
# take only as much as we are allowed
|
312
|
+
text = text[0,rem]
|
313
|
+
else
|
314
|
+
break
|
315
|
+
end
|
316
|
+
end
|
317
|
+
when Array
|
318
|
+
# for earlier demos that used an array
|
319
|
+
color = chunk[0]
|
320
|
+
attrib = chunk[2]
|
321
|
+
text = chunk[1]
|
322
|
+
end
|
323
|
+
|
324
|
+
color ||= defcolor
|
325
|
+
attrib ||= defattr
|
326
|
+
|
327
|
+
cc, bg = ColorMap.get_colors_for_pair color
|
328
|
+
#$log.debug "XXX: CHUNK window #{text}, cp #{color} , attrib #{attrib}. #{cc}, #{bg} "
|
329
|
+
color_set(color,nil) if color
|
330
|
+
wattron(attrib) if attrib
|
331
|
+
print(text)
|
332
|
+
wattroff(attrib) if attrib
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
def puts(*strings)
|
337
|
+
print(strings.join("\n") << "\n")
|
338
|
+
end
|
339
|
+
|
340
|
+
def _refresh
|
341
|
+
return unless visible?
|
342
|
+
@window.refresh
|
343
|
+
end
|
344
|
+
|
345
|
+
def wnoutrefresh
|
346
|
+
return unless visible?
|
347
|
+
@window.wnoutrefresh
|
348
|
+
end
|
349
|
+
|
350
|
+
def color=(color)
|
351
|
+
@color = color
|
352
|
+
@window.color_set(color, nil)
|
353
|
+
end
|
354
|
+
|
355
|
+
def highlight_line(color, y, x, max)
|
356
|
+
@window.mvchgat(y, x, max, Ncurses::A_NORMAL, color, nil)
|
357
|
+
end
|
358
|
+
|
359
|
+
def ungetch(ch)
|
360
|
+
Ncurses.ungetch(ch)
|
361
|
+
end
|
362
|
+
|
363
|
+
def getch
|
364
|
+
#c = @window.getch
|
365
|
+
c = FFI::NCurses.wgetch(@window)
|
366
|
+
# the only reason i am doing this is so ESC can be returned if no key is pressed
|
367
|
+
# after that, not sure how this effects everything. most likely I should just
|
368
|
+
# go back to using a wtimeout, and not worry about resize requiring a keystroke
|
369
|
+
if c == 27
|
370
|
+
Ncurses::wtimeout(@window, $ncurses_timeout || 500) # will wait a second on wgetch so we can get gg and qq
|
371
|
+
else
|
372
|
+
Ncurses::nowtimeout(@window, true)
|
373
|
+
end
|
374
|
+
c
|
375
|
+
# 2011-12-20 - i am trying setting a timer on wgetch, see timeout
|
376
|
+
#c = FFI::NCurses.getch # this will keep waiting, nodelay won't be used on it, since
|
377
|
+
# we've put nodelay on window
|
378
|
+
#if c == Ncurses::KEY_RESIZE
|
379
|
+
|
380
|
+
rescue SystemExit, Interrupt
|
381
|
+
#FFI::NCurses.flushinp
|
382
|
+
3 # is C-c
|
383
|
+
rescue StandardError
|
384
|
+
-1 # is C-c
|
385
|
+
end
|
386
|
+
|
387
|
+
# 2011-09-23 @since 1.3.1
|
388
|
+
# Added more combinations here. These 2 are just indicative
|
389
|
+
SPECIAL_KEYS = {
|
390
|
+
[27, 79, 50, 81] => 20014, # 'F14',
|
391
|
+
[27, 79, 50, 82] => 20015 # 'F15',
|
392
|
+
}
|
393
|
+
|
394
|
+
# returns control, alt, alt+ctrl, alt+control+shift, F1 .. etc
|
395
|
+
# ALT combinations also send a 27 before the actual key
|
396
|
+
# Please test with above combinations before using on your terminal
|
397
|
+
# added by rkumar 2008-12-12 23:07
|
398
|
+
# 2011-09-23 Redone Control-left, right, and Shift-F5..F10.
|
399
|
+
# Checking for quick press of Alt-Sh-O followed by Alt or printable char
|
400
|
+
# Checking for quick press of Alt-[ followed by Alt or printable char
|
401
|
+
# I attempted keeping a hash of combination arrays but it fails in the above
|
402
|
+
# 2 cases, so abandoned.
|
403
|
+
def getchar
|
404
|
+
while 1
|
405
|
+
ch = self.getch
|
406
|
+
#$log.debug "window getchar() GOT: #{ch}" if ch != -1
|
407
|
+
sf = @stack.first
|
408
|
+
if ch == -1
|
409
|
+
# the returns escape 27 if no key followed it, so its SLOW if you want only esc
|
410
|
+
if @stack.first == 27
|
411
|
+
#$log.debug " -1 stack sizze #{@stack.size}: #{@stack.inspect}, ch #{ch}"
|
412
|
+
case @stack.size
|
413
|
+
when 1
|
414
|
+
@stack.clear
|
415
|
+
return 27
|
416
|
+
when 2 # basically a ALT-O, or alt-[ (79 or 91) this will be really slow since it waits for -1
|
417
|
+
ch = 128 + @stack.last
|
418
|
+
$log.warn "XXX: WARN #{ch} CLEARING stack #{@stack} "
|
419
|
+
@stack.clear
|
420
|
+
return ch
|
421
|
+
else
|
422
|
+
# check up a hash of special keys
|
423
|
+
ret = SPECIAL_KEYS(@stack)
|
424
|
+
return ret if ret
|
425
|
+
$log.warn "INVALID UNKNOWN KEY: SHOULD NOT COME HERE getchar():#{@stack}"
|
426
|
+
end
|
427
|
+
end
|
428
|
+
# possibly a 49 left over from M3-1
|
429
|
+
unless @stack.empty?
|
430
|
+
if @stack.size == 1
|
431
|
+
@stack.clear
|
432
|
+
return sf
|
433
|
+
end
|
434
|
+
$log.warn "something on stack getchar(): #{@stack} "
|
435
|
+
end
|
436
|
+
# comemnt after testing keys since this will be called a lot, even stack.clear is called a lot
|
437
|
+
$log.warn "ERROR CLEARING STACK WITH STUFF ON IT getchar():#{@stack}" if ($log.debug? && !@stack.empty?)
|
438
|
+
@stack.clear
|
439
|
+
next
|
440
|
+
end # -1
|
441
|
+
# this is the ALT combination
|
442
|
+
if @stack.first == 27
|
443
|
+
# experimental. 2 escapes in quick succession to make exit faster
|
444
|
+
if @stack.size == 1 && ch == 27
|
445
|
+
@stack.clear
|
446
|
+
return 2727 if $esc_esc # this is double-esc if you wanna trap it, trying out
|
447
|
+
return 27
|
448
|
+
end
|
449
|
+
# possible F1..F3 on xterm-color
|
450
|
+
if ch == 79 || ch == 91
|
451
|
+
#$log.debug " got 27, #{ch}, waiting for one more"
|
452
|
+
@stack << ch
|
453
|
+
next
|
454
|
+
end
|
455
|
+
#$log.debug "stack SIZE #{@stack.size}, #{@stack.inspect}, ch: #{ch}"
|
456
|
+
if @stack == [27,79]
|
457
|
+
# xterm-color
|
458
|
+
case ch
|
459
|
+
when 80
|
460
|
+
ch = FFI::NCurses::KEY_F1
|
461
|
+
when 81
|
462
|
+
ch = FFI::NCurses::KEY_F2
|
463
|
+
when 82
|
464
|
+
ch = FFI::NCurses::KEY_F3
|
465
|
+
when 83
|
466
|
+
ch = FFI::NCurses::KEY_F4
|
467
|
+
#when 27 # another alt-char following Alt-Sh-O
|
468
|
+
else
|
469
|
+
## iterm2 uses these for HOME END num keyboard keys
|
470
|
+
@stack.clear
|
471
|
+
#@stack << ch # earlier we pushed this but it could be of use
|
472
|
+
#return 128 + 79
|
473
|
+
return 128 + 79 + ch
|
474
|
+
|
475
|
+
end
|
476
|
+
@stack.clear
|
477
|
+
return ch
|
478
|
+
elsif @stack == [27, 91]
|
479
|
+
# XXX 27, 91 also is Alt-[
|
480
|
+
if ch == 90
|
481
|
+
@stack.clear
|
482
|
+
return KEY_BTAB # backtab
|
483
|
+
elsif ch == 53 || ch == 50 || ch == 51
|
484
|
+
# control left, right and shift function
|
485
|
+
@stack << ch
|
486
|
+
next
|
487
|
+
elsif ch == 27 # another alt-char immediately after Alt-[
|
488
|
+
$log.debug "getchar in 27, will return 128+91 " if $log.debug?
|
489
|
+
@stack.clear
|
490
|
+
@stack << ch
|
491
|
+
return 128 + 91
|
492
|
+
else
|
493
|
+
$log.debug "getchar in other, will return 128+91: #{ch} " if $log.debug?
|
494
|
+
# other cases Alt-[ followed by some char or key - merge with previous
|
495
|
+
@stack.clear
|
496
|
+
@stack << ch
|
497
|
+
return 128 + 91
|
498
|
+
end
|
499
|
+
elsif @stack == [27, 91, 53]
|
500
|
+
if ch == 68
|
501
|
+
@stack.clear
|
502
|
+
return C_LEFT # control-left
|
503
|
+
elsif ch == 67
|
504
|
+
@stack.clear
|
505
|
+
return C_RIGHT # -control-rt
|
506
|
+
end
|
507
|
+
elsif @stack == [27, 91, 51]
|
508
|
+
if ch == 49 && getch()== 126
|
509
|
+
@stack.clear
|
510
|
+
return 20009 # sh_f9
|
511
|
+
end
|
512
|
+
elsif @stack == [27, 91, 50]
|
513
|
+
if ch == 50 && getch()== 126
|
514
|
+
@stack.clear
|
515
|
+
return 20010 # sh-F10
|
516
|
+
end
|
517
|
+
if ch == 57 && getch()== 126
|
518
|
+
@stack.clear
|
519
|
+
return 20008 # sh-F8
|
520
|
+
elsif ch == 56 && getch()== 126
|
521
|
+
@stack.clear
|
522
|
+
return 20007 # sh-F7
|
523
|
+
elsif ch == 54 && getch()== 126
|
524
|
+
@stack.clear
|
525
|
+
return 20006 # sh-F6
|
526
|
+
elsif ch == 53 && getch()== 126
|
527
|
+
@stack.clear
|
528
|
+
return 20005 # sh-F5
|
529
|
+
end
|
530
|
+
end
|
531
|
+
# the usual Meta combos. (alt) - this is screwing it up, just return it in some way
|
532
|
+
ch = 128 + ch
|
533
|
+
@stack.clear
|
534
|
+
return ch
|
535
|
+
end # stack.first == 27
|
536
|
+
# append a 27 to stack, actually one can use a flag too
|
537
|
+
if ch == 27
|
538
|
+
@stack << 27
|
539
|
+
next
|
540
|
+
end
|
541
|
+
return ch
|
542
|
+
end # while
|
543
|
+
end # def
|
544
|
+
|
545
|
+
# doesn't seem to work, clears first line, not both
|
546
|
+
def clear
|
547
|
+
# return unless visible?
|
548
|
+
move 0, 0
|
549
|
+
puts *Array.new(height){ ' ' * (width - 1) }
|
550
|
+
end
|
551
|
+
|
552
|
+
# setup and reset
|
553
|
+
|
554
|
+
## allow user to send an array
|
555
|
+
# I am tired of the hash layout (taken from ver).
|
556
|
+
def reset_layout(layout)
|
557
|
+
case layout
|
558
|
+
when Array
|
559
|
+
$log.error "NIL in window constructor" if layout.include? nil
|
560
|
+
raise ArgumentError, "Nil in window constructor" if layout.include? nil
|
561
|
+
@height, @width, @top, @left = *layout
|
562
|
+
raise ArgumentError, "Nil in window constructor" if @top.nil? || @left.nil?
|
563
|
+
|
564
|
+
@layout = { :height => @height, :width => @width, :top => @top, :left => @top }
|
565
|
+
when Hash
|
566
|
+
@layout = layout
|
567
|
+
|
568
|
+
[:height, :width, :top, :left].each do |name|
|
569
|
+
instance_variable_set("@#{name}", layout_value(name))
|
570
|
+
end
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
574
|
+
# removed ref to default_for since giving error in FFI 2011-09-8
|
575
|
+
def layout_value(name)
|
576
|
+
value = @layout[name]
|
577
|
+
default = default_for(name)
|
578
|
+
|
579
|
+
value = value.call(default) if value.respond_to?(:call)
|
580
|
+
return (value || default).to_i
|
581
|
+
end
|
582
|
+
|
583
|
+
# this gives error since stdscr is only a pointer at this time
|
584
|
+
def default_for(name)
|
585
|
+
case name
|
586
|
+
when :height, :top
|
587
|
+
#Ncurses.stdscr.getmaxy(stdscr)
|
588
|
+
FFI::NCurses.LINES
|
589
|
+
when :width, :left
|
590
|
+
#Ncurses.stdscr.getmaxx(stdscr)
|
591
|
+
FFI::NCurses.COLS
|
592
|
+
else
|
593
|
+
0
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
# Ncurses panel
|
598
|
+
|
599
|
+
def hide
|
600
|
+
#return unless visible? # added 2011-10-14 these 2 are not behaving properly
|
601
|
+
Ncurses::Panel.hide_panel @panel.pointer
|
602
|
+
#Ncurses.refresh # wnoutrefresh
|
603
|
+
Ncurses::Panel.update_panels # added so below window does not need to do this 2011-10-1
|
604
|
+
@visible = false
|
605
|
+
end
|
606
|
+
|
607
|
+
def show
|
608
|
+
#return if visible? # added 2011-10-14 these 2 are not behaving properly
|
609
|
+
Ncurses::Panel.show_panel @panel.pointer
|
610
|
+
#Ncurses.refresh # wnoutrefresh
|
611
|
+
Ncurses::Panel.update_panels # added so below window does not need to do this 2011-10-1
|
612
|
+
@visible = true
|
613
|
+
end
|
614
|
+
|
615
|
+
def on_top
|
616
|
+
Ncurses::Panel.top_panel @panel.pointer
|
617
|
+
wnoutrefresh
|
618
|
+
end
|
619
|
+
|
620
|
+
def visible?
|
621
|
+
@visible
|
622
|
+
end
|
623
|
+
|
624
|
+
##
|
625
|
+
# destroy window, panel and any pads that were requested
|
626
|
+
#
|
627
|
+
def destroy
|
628
|
+
# typically the ensure block should have this
|
629
|
+
|
630
|
+
#$log.debug "win destroy start"
|
631
|
+
|
632
|
+
Ncurses::Panel.del_panel(@panel.pointer) if @panel
|
633
|
+
delwin() if @window
|
634
|
+
Ncurses::Panel.update_panels # added so below window does not need to do this 2011-10-1
|
635
|
+
|
636
|
+
# destroy any pads that were created by widgets using get_pad
|
637
|
+
@pads.each { |pad|
|
638
|
+
FFI::NCurses.delwin(pad) if pad
|
639
|
+
pad = nil
|
640
|
+
} if @pads
|
641
|
+
#$log.debug "win destroy end"
|
642
|
+
end
|
643
|
+
|
644
|
+
#
|
645
|
+
# 2011-11-13 since 1.4.1
|
646
|
+
# Widgets can get window to create a pad for them. This way when the window
|
647
|
+
# is destroyed, it will delete all the pads. A widget wold not be able to do this.
|
648
|
+
# The destroy method of the widget will be called.
|
649
|
+
def get_pad content_rows, content_cols
|
650
|
+
pad = FFI::NCurses.newpad(content_rows, content_cols)
|
651
|
+
@pads ||= []
|
652
|
+
@pads << pad
|
653
|
+
## added 2013-03-05 - 19:21 without next line how was pad being returned
|
654
|
+
return pad
|
655
|
+
end
|
656
|
+
|
657
|
+
#
|
658
|
+
# Allows user to send data as normal string or chunks for printing
|
659
|
+
# An array is assumed to be a chunk containing color and attrib info
|
660
|
+
#
|
661
|
+
def printstring_or_chunks(r,c,content, color, att = Ncurses::A_NORMAL)
|
662
|
+
if content.is_a? String
|
663
|
+
printstring(r,c,content, color, att)
|
664
|
+
elsif content.is_a? Chunks::ChunkLine
|
665
|
+
#$log.debug "XXX: using chunkline" # 2011-12-10 12:40:13
|
666
|
+
wmove r, c
|
667
|
+
a = get_attrib att
|
668
|
+
# please add width to avoid overflow
|
669
|
+
show_colored_chunks content, color, a
|
670
|
+
elsif content.is_a? Array
|
671
|
+
# several chunks in one row - NOTE Very experimental may change
|
672
|
+
if content[0].is_a? Array
|
673
|
+
$log.warn "XXX: WARNING outdated should send in a chunkline"
|
674
|
+
wmove r, c
|
675
|
+
a = get_attrib att
|
676
|
+
# please add width to avoid overflow
|
677
|
+
show_colored_chunks content, color, a
|
678
|
+
else
|
679
|
+
# a single row chunk - NOTE Very experimental may change
|
680
|
+
text = content[1].dup
|
681
|
+
printstring r, c, text, content[0] || color, content[2] || att
|
682
|
+
end
|
683
|
+
end
|
684
|
+
end
|
685
|
+
#
|
686
|
+
# prints a string formatted in our new experimental coloring format
|
687
|
+
# taken from tmux. Currently, since i have chunks workings, i convert
|
688
|
+
# to chunks and use the existing print function. This could change.
|
689
|
+
# An example of a formatted string is:
|
690
|
+
# s="#[fg=green]testing chunks #[fg=yellow, bg=red, bold]yellow #[reverse] reverseme \
|
691
|
+
# #[normal]normal#[bg = black]just yellow#[fg=blue],blue now #[underline] underlined text"
|
692
|
+
# Ideally I should push and pop colors which the shell does not do with ansi terminal sequences.
|
693
|
+
# That way i can have a line in red,
|
694
|
+
# with some word in yellow, and then the line continues in red.
|
695
|
+
#
|
696
|
+
def printstring_formatted(r,c,content, color, att = Ncurses::A_NORMAL)
|
697
|
+
att = get_attrib att unless att.is_a? Fixnum
|
698
|
+
chunkline = convert_to_chunk(content, color, att)
|
699
|
+
printstring_or_chunks r,c, chunkline, color, att
|
700
|
+
end # print
|
701
|
+
#
|
702
|
+
# print a formatted line right aligned
|
703
|
+
# c (col) is ignored and calculated based on width and unformatted string length
|
704
|
+
#
|
705
|
+
def printstring_formatted_right(r,c,content, color, att = Ncurses::A_NORMAL)
|
706
|
+
clean = content.gsub /#\[[^\]]*\]/,'' # clean out all markup
|
707
|
+
#c = actual_width() - clean.length # actual width not working if resize
|
708
|
+
c = getmaxx() - clean.length
|
709
|
+
printstring_formatted(r,c,content, color, att )
|
710
|
+
end
|
711
|
+
|
712
|
+
private
|
713
|
+
def get_default_color_parser
|
714
|
+
require 'rbhex/core/util/colorparser'
|
715
|
+
@color_parser || DefaultColorParser.new
|
716
|
+
end
|
717
|
+
# supply with a color parser, if you supplied formatted text
|
718
|
+
public
|
719
|
+
def color_parser f
|
720
|
+
$log.debug "XXX: color_parser setting in window to #{f} "
|
721
|
+
if f == :tmux
|
722
|
+
@color_parser = get_default_color_parser()
|
723
|
+
else
|
724
|
+
@color_parser = f
|
725
|
+
end
|
726
|
+
end
|
727
|
+
#
|
728
|
+
# Takes a formatted string and converts the parsed parts to chunks.
|
729
|
+
#
|
730
|
+
# @param [String] takes the entire line or string and breaks into an array of chunks
|
731
|
+
# @yield chunk if block
|
732
|
+
# @return [ChunkLine] # [Array] array of chunks
|
733
|
+
# @since 1.4.1 2011-11-3 experimental, can change
|
734
|
+
public
|
735
|
+
def convert_to_chunk s, colorp=$datacolor, att=FFI::NCurses::A_NORMAL
|
736
|
+
unless @color_parser
|
737
|
+
@color_parser = get_default_color_parser()
|
738
|
+
@converter = Chunks::ColorParser.new @color_parser
|
739
|
+
end
|
740
|
+
@converter.convert_to_chunk s, colorp, att
|
741
|
+
end
|
742
|
+
|
743
|
+
##
|
744
|
+
# prints a string at row, col, with given color and attribute
|
745
|
+
# added by rk 2008-11-29 19:01
|
746
|
+
# I usually use this, not the others ones here
|
747
|
+
# @param r - row
|
748
|
+
# @param c - col
|
749
|
+
# @param string - text to print
|
750
|
+
# @param color - color pair
|
751
|
+
# @ param att - ncurses attribute: normal, bold, reverse, blink,
|
752
|
+
# underline
|
753
|
+
public
|
754
|
+
def printstring(r,c,string, color, att = Ncurses::A_NORMAL)
|
755
|
+
raise "Nil passed to peintstring row:#{r}, col:#{c}, #{color} " if r.nil? || c.nil? || color.nil?
|
756
|
+
#raise "Zero or less passed to printstring row:#{r}, col:#{c} " if $log.debug? && (r <=0 || c <=0)
|
757
|
+
prv_printstring(r,c,string, color, att )
|
758
|
+
end
|
759
|
+
|
760
|
+
## name changed from printstring to prv_prinstring
|
761
|
+
def prv_printstring(r,c,string, color, att = Ncurses::A_NORMAL)
|
762
|
+
|
763
|
+
#$log.debug " #{@name} inside window printstring r #{r} c #{c} #{string} "
|
764
|
+
if att.nil?
|
765
|
+
att = Ncurses::A_NORMAL
|
766
|
+
else
|
767
|
+
att = get_attrib att
|
768
|
+
end
|
769
|
+
#att = att.downcase.to_sym if att.is_a? String
|
770
|
+
#case att
|
771
|
+
#when :normal
|
772
|
+
#att = Ncurses::A_NORMAL
|
773
|
+
#when :underline
|
774
|
+
#att = Ncurses::A_UNDERLINE
|
775
|
+
#when :bold
|
776
|
+
#att = Ncurses::A_BOLD
|
777
|
+
#when :reverse
|
778
|
+
#att = Ncurses::A_REVERSE
|
779
|
+
#when :dim
|
780
|
+
#att = Ncurses::A_DIM
|
781
|
+
#when :blink
|
782
|
+
#att = Ncurses::A_BLINK # unlikely to work
|
783
|
+
#end
|
784
|
+
|
785
|
+
wattron(Ncurses.COLOR_PAIR(color) | att)
|
786
|
+
mvwprintw(r, c, "%s", :string, string);
|
787
|
+
wattroff(Ncurses.COLOR_PAIR(color) | att)
|
788
|
+
end
|
789
|
+
##
|
790
|
+
# NOTE : FOR MESSAGEBOXES ONLY !!!!
|
791
|
+
def print_border_mb row, col, height, width, color, attr
|
792
|
+
# the next is for xterm-256
|
793
|
+
att = get_attrib attr
|
794
|
+
len = width
|
795
|
+
len = Ncurses.COLS-0 if len == 0
|
796
|
+
# print a bar across the screen
|
797
|
+
#attron(Ncurses.COLOR_PAIR(color) | att)
|
798
|
+
# this works for newmessagebox but not for old one.
|
799
|
+
# Even now in some cases some black shows through, if the widget is printing spaces
|
800
|
+
# such as field or textview on a messagebox.
|
801
|
+
(row-1).upto(row+height-1) do |r|
|
802
|
+
mvwhline(r, col, 1, len)
|
803
|
+
end
|
804
|
+
#attroff(Ncurses.COLOR_PAIR(color) | att)
|
805
|
+
|
806
|
+
mvwaddch row, col, Ncurses::ACS_ULCORNER
|
807
|
+
mvwhline( row, col+1, Ncurses::ACS_HLINE, width-6)
|
808
|
+
mvwaddch row, col+width-5, Ncurses::ACS_URCORNER
|
809
|
+
mvwvline( row+1, col, Ncurses::ACS_VLINE, height-4)
|
810
|
+
|
811
|
+
mvwaddch row+height-3, col, Ncurses::ACS_LLCORNER
|
812
|
+
mvwhline(row+height-3, col+1, Ncurses::ACS_HLINE, width-6)
|
813
|
+
mvwaddch row+height-3, col+width-5, Ncurses::ACS_LRCORNER
|
814
|
+
mvwvline( row+1, col+width-5, Ncurses::ACS_VLINE, height-4)
|
815
|
+
end
|
816
|
+
##
|
817
|
+
# prints a border around a widget, CLEARING the area.
|
818
|
+
# If calling with a pad, you would typically use 0,0, h-1, w-1.
|
819
|
+
def print_border row, col, height, width, color, att=Ncurses::A_NORMAL
|
820
|
+
raise "height needs to be supplied." if height.nil?
|
821
|
+
raise "width needs to be supplied." if width.nil?
|
822
|
+
att ||= Ncurses::A_NORMAL
|
823
|
+
|
824
|
+
#$log.debug " inside window print_border r #{row} c #{col} h #{height} w #{width} "
|
825
|
+
|
826
|
+
# 2009-11-02 00:45 made att nil for blanking out
|
827
|
+
# FIXME - in tabbedpanes this clears one previous line ??? XXX when using a textarea/view
|
828
|
+
# when using a pad this calls pads printstring which again reduces top and left !!! 2010-01-26 23:53
|
829
|
+
ww=width-2
|
830
|
+
(row+1).upto(row+height-1) do |r|
|
831
|
+
prv_printstring( r, col+1," "*ww , color, att)
|
832
|
+
end
|
833
|
+
prv_print_border_only row, col, height, width, color, att
|
834
|
+
end
|
835
|
+
def print_border_only row, col, height, width, color, att=Ncurses::A_NORMAL
|
836
|
+
prv_print_border_only row, col, height, width, color, att
|
837
|
+
end
|
838
|
+
|
839
|
+
|
840
|
+
## print just the border, no cleanup
|
841
|
+
#+ Earlier, we would clean up. Now in some cases, i'd like
|
842
|
+
#+ to print border over what's been done.
|
843
|
+
# XXX this reduces 1 from width but not height !!! FIXME
|
844
|
+
def prv_print_border_only row, col, height, width, color, att=Ncurses::A_NORMAL
|
845
|
+
if att.nil?
|
846
|
+
att = Ncurses::A_NORMAL
|
847
|
+
else
|
848
|
+
att = get_attrib att
|
849
|
+
end
|
850
|
+
wattron(Ncurses.COLOR_PAIR(color) | att)
|
851
|
+
mvwaddch row, col, Ncurses::ACS_ULCORNER
|
852
|
+
mvwhline( row, col+1, Ncurses::ACS_HLINE, width-2)
|
853
|
+
mvwaddch row, col+width-1, Ncurses::ACS_URCORNER
|
854
|
+
mvwvline( row+1, col, Ncurses::ACS_VLINE, height-1)
|
855
|
+
|
856
|
+
mvwaddch row+height-0, col, Ncurses::ACS_LLCORNER
|
857
|
+
mvwhline(row+height-0, col+1, Ncurses::ACS_HLINE, width-2)
|
858
|
+
mvwaddch row+height-0, col+width-1, Ncurses::ACS_LRCORNER
|
859
|
+
mvwvline( row+1, col+width-1, Ncurses::ACS_VLINE, height-1)
|
860
|
+
wattroff(Ncurses.COLOR_PAIR(color) | att)
|
861
|
+
end
|
862
|
+
# This used to return an Ncurses window object, and you could call methods on it
|
863
|
+
# Now it returns a FFI::NCurses.window pointer which you cannot call methods on.
|
864
|
+
# You have to pass it to FFI::NCurses.<method>
|
865
|
+
def get_window; @window; end
|
866
|
+
def to_s; @name || self; end
|
867
|
+
# use in place of mvwhline if your widget could be using a pad or window
|
868
|
+
def rb_mvwhline row, col, char, width
|
869
|
+
mvwhline row, col, char, width
|
870
|
+
end
|
871
|
+
# use in place of mvwvline if your widget could be using a pad or window
|
872
|
+
def rb_mvwvline row, col, char, width
|
873
|
+
mvwvline row, col, char, width
|
874
|
+
end
|
875
|
+
# use in place of mvaddch if your widget could be using a pad or window
|
876
|
+
def rb_mvaddch row, col, char
|
877
|
+
mvaddch row, col, char
|
878
|
+
end
|
879
|
+
def close_command *args, &block
|
880
|
+
@close_command ||= []
|
881
|
+
@close_args ||= []
|
882
|
+
@close_command << block
|
883
|
+
@close_args << args
|
884
|
+
end
|
885
|
+
alias :command :close_command
|
886
|
+
|
887
|
+
# set a single command to confirm whether window shoud close or not
|
888
|
+
# Block should return true or false for closing or not
|
889
|
+
def confirm_close_command *args, &block
|
890
|
+
@confirm_close_command = block
|
891
|
+
@confirm_close_args = args
|
892
|
+
end
|
893
|
+
|
894
|
+
# need a way of lettign user decide whether he wishes to close
|
895
|
+
# in which case we return false. However, there could be several commands
|
896
|
+
# mapped. how do we know which is the one that has this authority
|
897
|
+
def fire_close_handler
|
898
|
+
if @confirm_close_command
|
899
|
+
comm = @confirm_close_command
|
900
|
+
ret = comm.call(self, *@confirm_close_args)
|
901
|
+
return ret unless ret # only return if false returned
|
902
|
+
end
|
903
|
+
if @close_command
|
904
|
+
@close_command.each_with_index do |comm, ix|
|
905
|
+
comm.call(self, *@close_args[ix]) if comm
|
906
|
+
end
|
907
|
+
end
|
908
|
+
@close_command = nil
|
909
|
+
@close_args = nil
|
910
|
+
return true
|
911
|
+
end
|
912
|
+
end
|
913
|
+
end
|