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,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
|