rbcurse 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Makefile +21 -0
- data/Manifest.txt +6 -0
- data/README.markdown +6 -4
- data/TODO +372 -0
- data/TODO2.txt +121 -0
- data/VERSION +1 -1
- data/examples/README.txt +67 -0
- data/examples/abasiclist.rb +33 -0
- data/examples/alpmenu.rb +42 -0
- data/examples/app.rb +859 -0
- data/examples/app.sample +17 -0
- data/examples/appdirtree.rb +74 -0
- data/examples/appemail.rb +191 -0
- data/examples/appemaillb.rb +308 -0
- data/examples/appgcompose.rb +315 -0
- data/examples/atree.rb +64 -0
- data/examples/common/file.rb +40 -0
- data/examples/common/rmail.rb +257 -0
- data/examples/data.txt +683 -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/tasks.txt +27 -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 +495 -0
- data/examples/deprecated/appgmail.rb +952 -0
- data/examples/deprecated/splitp.rb +56 -0
- data/examples/deprecated/testscrolllb.rb +86 -0
- data/examples/deprecated/testscrollp.rb +88 -0
- data/examples/deprecated/testscrollta.rb +80 -0
- data/examples/deprecated/testscrolltable.rb +165 -0
- data/examples/deprecated/testsplit.rb +87 -0
- data/examples/deprecated/testsplit2.rb +123 -0
- data/examples/deprecated/testsplit3.rb +215 -0
- data/examples/deprecated/testsplit3_1.rb +244 -0
- data/examples/deprecated/testsplit3a.rb +215 -0
- data/examples/deprecated/testsplit3b.rb +237 -0
- data/examples/deprecated/testsplitta.rb +148 -0
- data/examples/deprecated/testsplittv.rb +142 -0
- data/examples/deprecated/testsplittvv.rb +144 -0
- data/examples/deprecated/testtpane.rb +215 -0
- data/examples/deprecated/testtpane2.rb +145 -0
- data/examples/deprecated/testtpanetable.rb +203 -0
- data/examples/dirtree.rb +88 -0
- data/examples/experimental/resultsetdemo.rb +280 -0
- data/examples/experimental/testmform.rb +35 -0
- data/examples/experimental/testscroller.rb +117 -0
- data/examples/experimental/teststackflow.rb +111 -0
- data/examples/menu1.rb +112 -0
- data/examples/multispl.rb +86 -0
- data/examples/newmessagebox.rb +131 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +121 -0
- data/examples/qdfilechooser.rb +68 -0
- data/examples/rfe.rb +1239 -0
- data/examples/rfe_renderer.rb +121 -0
- data/examples/sqlc.rb +454 -0
- data/examples/sqlm.rb +437 -0
- data/examples/sqlt.rb +408 -0
- data/examples/status.txt +68 -0
- data/examples/table1.rb +24 -0
- data/examples/term2.rb +84 -0
- data/examples/test1.rb +239 -0
- data/examples/test2.rb +674 -0
- data/examples/testapp.rb +44 -0
- data/examples/testapp2.rb +58 -0
- data/examples/testchars.rb +137 -0
- data/examples/testcombo.rb +91 -0
- data/examples/testkeypress.rb +66 -0
- data/examples/testlistbox.rb +113 -0
- data/examples/testmenu.rb +101 -0
- data/examples/testmulticomp.rb +70 -0
- data/examples/testmulticontainer.rb +94 -0
- data/examples/testmultispl.rb +199 -0
- data/examples/testree.rb +106 -0
- data/examples/testtable.rb +264 -0
- data/examples/testtabp.rb +107 -0
- data/examples/testtodo.rb +584 -0
- data/examples/testvimsplit.rb +112 -0
- data/examples/testwsshortcuts.rb +64 -0
- data/examples/testwsshortcuts2.rb +126 -0
- data/examples/todo.db +0 -0
- data/examples/todo.yml +191 -0
- data/examples/viewtodo.rb +574 -0
- data/lib/rbcurse/deprecated/README.markdown +12 -0
- data/lib/rbcurse/deprecated/rpad.rb +375 -0
- data/lib/rbcurse/deprecated/rscrollpane.rb +512 -0
- data/lib/rbcurse/deprecated/rsplitpane.rb +894 -0
- data/lib/rbcurse/deprecated/rsplitpane2.rb +1009 -0
- data/lib/rbcurse/deprecated/rviewport.rb +204 -0
- data/lib/rbcurse/deprecated/widgets/mapper.rb +130 -0
- data/lib/rbcurse/deprecated/widgets/rmessagebox.rb +348 -0
- data/lib/rbcurse/deprecated/widgets/rtabbedpane.rb +1158 -0
- data/lib/rbcurse/deprecated/widgets/rtabbedwindow.rb +167 -0
- data/lib/rbcurse/deprecated/widgets/scrollable.rb +301 -0
- data/lib/rbcurse/deprecated/widgets/stdscrwindow.rb +309 -0
- data/lib/ver/keyboard2.rb +170 -0
- data/test/test_rbcurse.rb +0 -0
- metadata +131 -9
@@ -0,0 +1,204 @@
|
|
1
|
+
=begin
|
2
|
+
* Name: Viewport
|
3
|
+
* $Id$
|
4
|
+
* Description: a viewport thru which you see an underlying form or widget. Scrolling
|
5
|
+
the viewport reveals new sections of the underlying object.
|
6
|
+
* Author: rkumar arunachala
|
7
|
+
TODO
|
8
|
+
* file created 2009-10-27 18:05
|
9
|
+
Major change 2010-02-11 23:32
|
10
|
+
* removed buffering, was totally unnecessary
|
11
|
+
* FIXME avoid repaint and handle_keys totally, let scrollpane talk to child.
|
12
|
+
Do we really need this ?
|
13
|
+
If we do strip it down to its major function - nothign extraneous. Currently its a huge layer in between.
|
14
|
+
--------
|
15
|
+
* License:
|
16
|
+
Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
17
|
+
|
18
|
+
=end
|
19
|
+
#require 'rubygems'
|
20
|
+
#require 'ncurses'
|
21
|
+
require 'logger'
|
22
|
+
require 'rbcurse'
|
23
|
+
require 'rbcurse/core/include/rchangeevent'
|
24
|
+
|
25
|
+
#include Ncurses # FFI 2011-09-8
|
26
|
+
include RubyCurses
|
27
|
+
module RubyCurses
|
28
|
+
extend self
|
29
|
+
|
30
|
+
##
|
31
|
+
# A viewport or porthole throgh which one can see portions of underlying object
|
32
|
+
# such as textarea, table or a form, usually the underlying data is larger
|
33
|
+
# than what can be displayed and thus must be seen through a viewport.
|
34
|
+
# TODO -
|
35
|
+
|
36
|
+
class Viewport < Widget
|
37
|
+
# row and col also present int widget
|
38
|
+
dsl_accessor :child # component that is being viewed
|
39
|
+
attr_accessor :cascade_changes
|
40
|
+
#attr_reader :top_margin, :left_margin
|
41
|
+
|
42
|
+
def initialize form, config={}, &block
|
43
|
+
@focusable = false
|
44
|
+
@editable = false
|
45
|
+
#@top_margin = @left_margin = 1 # 2010-02-06 23:27 reduce in scrollpane
|
46
|
+
@row = 1 # 1 # 0 2010-02-06 22:46 so we don't write on scrollpanes border
|
47
|
+
@col = 1 # 1 # 0 2010-02-06 22:47
|
48
|
+
super
|
49
|
+
#@row_offset = @col_offset = 1
|
50
|
+
#@orig_col = @col
|
51
|
+
init_vars
|
52
|
+
@_events.push :STATE_CHANGE
|
53
|
+
end
|
54
|
+
def init_vars
|
55
|
+
#@curpos = @pcol = @toprow = @current_index = 0
|
56
|
+
should_create_buffer = true
|
57
|
+
@border_width = 2
|
58
|
+
end
|
59
|
+
# set the component to be viewed
|
60
|
+
def set_view ch
|
61
|
+
@child = ch
|
62
|
+
end
|
63
|
+
def set_view_size h,w
|
64
|
+
# calling the property shoudl uniformally trigger fire_property_change
|
65
|
+
$log.debug " setting viewport to h #{h} , w #{w} "
|
66
|
+
height(h)
|
67
|
+
width(w)
|
68
|
+
fire_state_changed
|
69
|
+
#fire_handler :PROPERTY_CHANGE, self # XXX should it be an event STATE_CHANGE with details
|
70
|
+
end
|
71
|
+
##
|
72
|
+
# Set the row and col of the child, that the viewport starts displaying.
|
73
|
+
# Used to initialize the view, and later if scrolling.
|
74
|
+
# Initially would be set to 0,0.
|
75
|
+
#
|
76
|
+
def set_view_position r,c
|
77
|
+
return false if r < 0 or c < 0
|
78
|
+
# 2010-02-04 19:29 TRYING -2 for borders
|
79
|
+
$log.debug " set_view if #{r} +1+ #{@height} - #{@border_width} )} >=#{@child.height} "
|
80
|
+
# 2010-02-12 15:33 XXX made > into >= and added +1 since -1 in set_buffering
|
81
|
+
# testscrollp was crashing out when child height exceeded
|
82
|
+
if r+ (@height+1-@border_width) >= @child.height
|
83
|
+
# basically r + (:bottom - :screen_top) < @child.height
|
84
|
+
#if r+ (@height) >= @child.height
|
85
|
+
$log.debug " set_view_position : trying to exceed ht #{r} + #{@height} > #{@child.height} returned false"
|
86
|
+
return false
|
87
|
+
end
|
88
|
+
# testscrollp was printing junk on right end. Why the 1?
|
89
|
+
if c+ (@width+1-@border_width) >=@child.width
|
90
|
+
#if c+ (@width) >=@child.width
|
91
|
+
$log.debug " set_view_position : trying to exceed width #{c} + #{@width} . returned false"
|
92
|
+
return false
|
93
|
+
end
|
94
|
+
$log.debug " VP row #{@row} col #{@col}, now will be #{r} , #{c} "
|
95
|
+
row(r) # commnting off 2010-02-06 22:47
|
96
|
+
col(c) # commnting off 2010-02-06 22:47
|
97
|
+
# next call sets pminrow and pmincol
|
98
|
+
$log.debug " VP setting child buffer pmin to #{r} #{c} "
|
99
|
+
@child.get_buffer().set_pad_top_left(r, c)
|
100
|
+
# replaced this on 2010-02-26 11:49 HOPE IT WORKS XXX
|
101
|
+
#@child.fire_property_change("row", r, r) # XXX quick dirty, this should happen
|
102
|
+
@child.repaint_required(true)
|
103
|
+
@repaint_required = true
|
104
|
+
#fire_handler :PROPERTY_CHANGE, self
|
105
|
+
fire_state_changed
|
106
|
+
return true
|
107
|
+
end
|
108
|
+
# instead of using row and col to increment, try using this, since this is what's actually incremented.
|
109
|
+
def get_pad_top_left
|
110
|
+
p = @child.get_buffer()
|
111
|
+
return p.pminrow, p.pmincol
|
112
|
+
end
|
113
|
+
def repaint # viewport
|
114
|
+
return unless @repaint_required
|
115
|
+
# should call child's repaint onto pad
|
116
|
+
# then this should return clipped pad
|
117
|
+
$log.debug "VP calling child #{@child.name} repaint"
|
118
|
+
#x @graphic.wclear # required otherwise bottom of scrollpane had old rows still repeated. 2010-01-17 22:51
|
119
|
+
@child.repaint_all
|
120
|
+
@child.repaint
|
121
|
+
paint
|
122
|
+
end
|
123
|
+
def getvalue
|
124
|
+
# TODO ???
|
125
|
+
end
|
126
|
+
## most likely should just return an unhandled and not try being intelligent
|
127
|
+
# should viewport handle keys or should parent do so directly to child
|
128
|
+
def handle_key ch
|
129
|
+
# if this gets key it should just hand it to child
|
130
|
+
if @child != nil
|
131
|
+
ret = @child.handle_key ch
|
132
|
+
# 2010-01-19 19:26 commenting off repaint to see.
|
133
|
+
return :UNHANDLED if ret == :UNHANDLED
|
134
|
+
# moved below return so only if table handles
|
135
|
+
@repaint_required=true # added 2009-12-27 22:25 BUFFERED WHY ??
|
136
|
+
else
|
137
|
+
return :UNHANDLED
|
138
|
+
end
|
139
|
+
return 0
|
140
|
+
#$log.debug "TV after loop : curpos #{@curpos} blen: #{@buffer.length}"
|
141
|
+
end
|
142
|
+
def paint
|
143
|
+
@repaint_required = false
|
144
|
+
@repaint_all = false
|
145
|
+
end
|
146
|
+
# set height
|
147
|
+
# a container must pass down changes in size to it's children
|
148
|
+
#+ 2010-02-04 18:06 - i am not sure about this. When viewport is set then it passes down
|
149
|
+
#+ changes to child which user did not intend. Maybe in splitpane it is okay but other cases?
|
150
|
+
#+ Perhaps its okay if scrollpane gets larger than child, not otherwise.
|
151
|
+
# added 2010-01-16 23:55
|
152
|
+
def height(*val)
|
153
|
+
return @height if val.empty?
|
154
|
+
oldvalue = @height || 0
|
155
|
+
super
|
156
|
+
@height = val[0]
|
157
|
+
return if @child == nil
|
158
|
+
delta = @height - oldvalue
|
159
|
+
return if delta == 0
|
160
|
+
@repaint_required = true
|
161
|
+
if @child.height.nil?
|
162
|
+
@child.height = @height
|
163
|
+
$log.warn " viewport setting child #{@child.name} to default h of #{@height} -- child is usually larger. "
|
164
|
+
else
|
165
|
+
if @cascade_changes
|
166
|
+
$log.debug "warn!! viewport adding #{delta} to child ht #{child.height} "
|
167
|
+
@child.height += delta
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
# set width
|
172
|
+
# a container must pass down changes in size to it's children
|
173
|
+
# added 2010-01-16 23:55
|
174
|
+
def width(*val)
|
175
|
+
return @width if val.empty?
|
176
|
+
oldvalue = @width || 0
|
177
|
+
super
|
178
|
+
@width = val[0]
|
179
|
+
return if @child == nil
|
180
|
+
delta = @width - oldvalue
|
181
|
+
return if delta == 0
|
182
|
+
@repaint_required = true
|
183
|
+
# another safeguard if user did not enter. usesomething sensible 2010-01-17 15:23
|
184
|
+
if @child.width.nil?
|
185
|
+
@child.width = @width
|
186
|
+
$log.warn " viewport setting child #{@child.name} to default w of #{@width}. Usually child is larger. "
|
187
|
+
else
|
188
|
+
## sometime we are needless increasing. this happens when we set viewport and
|
189
|
+
##+ child has been set. Or may do only if scrollpane is getting larger than child
|
190
|
+
##+ largely a situation with splitpanes.
|
191
|
+
if @cascade_changes
|
192
|
+
$log.debug "warn!! viewport adding #{delta} to child wt #{child.width} "
|
193
|
+
@child.width += delta
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
# should this be in widget ?
|
198
|
+
# inform listeners that state has changed
|
199
|
+
def fire_state_changed
|
200
|
+
@sce = ChangeEvent.new(self) if @sce.nil?
|
201
|
+
fire_handler :STATE_CHANGE, @sce
|
202
|
+
end
|
203
|
+
end # class viewport
|
204
|
+
end # module
|
@@ -0,0 +1,130 @@
|
|
1
|
+
## this class allows us to do multiple key mappings such as emacs
|
2
|
+
# See the example keytest.rb
|
3
|
+
# However, integrating this into our library seems a little difficult now
|
4
|
+
# since each widget handles keys and often there are heirachies of widgets.
|
5
|
+
# However, this being a terminal app, mouseless, we really need to make it key-friendly.
|
6
|
+
require 'rbcurse/core/include/orderedhash'
|
7
|
+
class Mapper
|
8
|
+
attr_reader :keymap
|
9
|
+
attr_reader :view
|
10
|
+
attr_accessor :mode
|
11
|
+
attr_reader :keys
|
12
|
+
def initialize handler
|
13
|
+
#@handler = handler
|
14
|
+
@view = handler # caller program
|
15
|
+
@keys = {}
|
16
|
+
@mode = nil # used when defining
|
17
|
+
@pendingkeys = nil
|
18
|
+
@prevkey = nil # in case of a key sequence such as C-x C-c, will have C-x
|
19
|
+
@arg = nil # regex matched this key.
|
20
|
+
end
|
21
|
+
def let mode, &block
|
22
|
+
h = OrderedHash.new
|
23
|
+
@keys[mode] = h
|
24
|
+
@mode = mode
|
25
|
+
instance_eval(&block)
|
26
|
+
$log.debug("KEYS: #{@keys[mode].inspect}")
|
27
|
+
end
|
28
|
+
|
29
|
+
## mapping keys to blocks or symbols
|
30
|
+
# 2010-02-23 19:17 added check for string, so no required to use getbyte everywhere, esp for existing app
|
31
|
+
# However, this means that we can't map an actual string, which we may want to for commands
|
32
|
+
# which cuold be passed outside keys, or as aliases.
|
33
|
+
def map(*args, &block)
|
34
|
+
if block_given?
|
35
|
+
|
36
|
+
# We check for cases like C-x C-c etc. Only 2 levels.
|
37
|
+
#args = arg.split(/ +/)
|
38
|
+
arg0 = args[0]
|
39
|
+
arg0 = args[0].getbyte(0) if args[0].class.to_s == 'String'
|
40
|
+
if args.length == 2
|
41
|
+
arg1 = args[1]
|
42
|
+
arg1 = args[1].getbyte(0) if args[1].class.to_s == 'String'
|
43
|
+
$log.debug " KEY2 #{args[0]} , #{args[0].class}, #{args[1]} , #{args[1].class} "
|
44
|
+
@keys[@mode][arg0] ||= OrderedHash.new
|
45
|
+
@keys[@mode][arg0][arg1]=block
|
46
|
+
else
|
47
|
+
# single key or control key
|
48
|
+
$log.debug " KEY #{args[0]} , #{args[0].class} "
|
49
|
+
@keys[@mode][arg0]=block
|
50
|
+
end
|
51
|
+
else
|
52
|
+
#no block, last arg shold be a symbol
|
53
|
+
symb = args.pop
|
54
|
+
raise "If block not passed, last arg should be a method symbol" if !symb.is_a? Symbol
|
55
|
+
arg0 = args[0]
|
56
|
+
arg0 = args[0].getbyte(0) if args[0].class.to_s == 'String'
|
57
|
+
if args.length == 2
|
58
|
+
arg1 = args[1]
|
59
|
+
arg1 = args[1].getbyte(0) if args[1].class.to_s == 'String'
|
60
|
+
@keys[@mode][arg0] ||= OrderedHash.new
|
61
|
+
@keys[@mode][arg0][arg1]=symb
|
62
|
+
else
|
63
|
+
# single key or control key
|
64
|
+
@keys[@mode][arg0]=symb
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
## manages key pressing
|
70
|
+
# takes care of multiple key combos too
|
71
|
+
def press key
|
72
|
+
#$log.debug("press Got: #{key}")
|
73
|
+
# for a double key combination such as C-x C-c this has the set of pending keys to check against
|
74
|
+
if @pendingkeys != nil
|
75
|
+
blk = @pendingkeys[key]
|
76
|
+
else
|
77
|
+
# this is the regular single key mode
|
78
|
+
#blk = @keys[@view.mode][key]
|
79
|
+
blk = match(key)
|
80
|
+
end
|
81
|
+
# this means this key expects more keys to follow such as C-x could
|
82
|
+
if blk.is_a? OrderedHash
|
83
|
+
@pendingkeys = blk
|
84
|
+
@prevkey = key
|
85
|
+
return
|
86
|
+
end
|
87
|
+
if blk.nil? # this should go up XXX
|
88
|
+
if !@pendingkeys.nil?
|
89
|
+
# this error message to be modified if using numeric keys -- need to convert to char
|
90
|
+
view.info("%p not valid in %p. Try: #{@pendingkeys.keys.join(', ')}" % [key, @prevkey]) # XXX
|
91
|
+
else
|
92
|
+
view.info("%p not valid in %p. " % [key, @view.mode])
|
93
|
+
end
|
94
|
+
return
|
95
|
+
end
|
96
|
+
# call the block or symbol - our user defined key mappings use symbols
|
97
|
+
if blk.is_a? Symbol
|
98
|
+
@view.send(blk)
|
99
|
+
else
|
100
|
+
blk.call
|
101
|
+
end
|
102
|
+
@prevkey = nil
|
103
|
+
@pendingkeys = nil
|
104
|
+
end
|
105
|
+
def match key
|
106
|
+
#$log.debug "MATCH #{key} "
|
107
|
+
#blk = @keys[@view.mode][key]
|
108
|
+
@keys[@view.mode].each_pair do |k,v|
|
109
|
+
#$log.debug "LOOP #{k.class}, #{k}, #{v} "
|
110
|
+
case k.class.to_s
|
111
|
+
when "String"
|
112
|
+
return v if k == key
|
113
|
+
when "Fixnum" # for keyboard2
|
114
|
+
#$log.debug "FIXNUM LOOP #{k.class}, #{k}, #{v} "
|
115
|
+
return v if k == key
|
116
|
+
when "Regexp"
|
117
|
+
# $log.debug "REGEX #key , #k, #{k.match(key)}"
|
118
|
+
key1 = key.chr if key.is_a? Fixnum
|
119
|
+
if !k.match(key1).nil?
|
120
|
+
@arg = key1
|
121
|
+
return v
|
122
|
+
end
|
123
|
+
else
|
124
|
+
$log.error "MATCH: Unhandled class #{k.class} "
|
125
|
+
end
|
126
|
+
end
|
127
|
+
$log.debug "MATCH #{key} ret nil "
|
128
|
+
return nil
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,348 @@
|
|
1
|
+
=begin
|
2
|
+
* Name: rmessagebox: creates messageboxes
|
3
|
+
* Description
|
4
|
+
* Author: rkumar (arunachalesha)
|
5
|
+
* Date: 2008-11-19 12:49
|
6
|
+
* License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
7
|
+
* file separated on 2009-01-13 22:39
|
8
|
+
|
9
|
+
=end
|
10
|
+
require 'rbcurse/core/widgets/rwidget'
|
11
|
+
require 'rbcurse/extras/widgets/rlistbox'
|
12
|
+
|
13
|
+
module RubyCurses
|
14
|
+
##
|
15
|
+
# dimensions of window should be derived on content
|
16
|
+
#
|
17
|
+
class MessageBox
|
18
|
+
include RubyCurses::Utils
|
19
|
+
dsl_accessor :title
|
20
|
+
dsl_accessor :message
|
21
|
+
dsl_accessor :type # :ok, :ok_cancel :yes_no :yes_no_cancel :custom
|
22
|
+
dsl_accessor :default_button # TODO - currently first
|
23
|
+
dsl_accessor :layout
|
24
|
+
dsl_accessor :buttons # used if type :custom
|
25
|
+
dsl_accessor :underlines # offsets of each button to underline
|
26
|
+
attr_reader :config
|
27
|
+
attr_reader :selected_index # button index selected by user
|
28
|
+
attr_reader :window # required for keyboard
|
29
|
+
dsl_accessor :list_selection_mode # true or false allow multiple selection
|
30
|
+
dsl_accessor :list # 2009-01-05 23:59
|
31
|
+
dsl_accessor :button_type # ok, ok_cancel, yes_no
|
32
|
+
dsl_accessor :default_value #
|
33
|
+
dsl_accessor :default_values # # 2009-01-06 00:05 after removing meth missing
|
34
|
+
dsl_accessor :height, :width, :top, :left # 2009-01-06 00:05 after removing meth missing
|
35
|
+
|
36
|
+
dsl_accessor :message_height
|
37
|
+
|
38
|
+
|
39
|
+
def initialize form=nil, aconfig={}, &block
|
40
|
+
@form = form
|
41
|
+
@config = aconfig
|
42
|
+
@buttons = []
|
43
|
+
#@keys = {}
|
44
|
+
@bcol = 5
|
45
|
+
@selected_index = -1
|
46
|
+
@config.each_pair { |k,v| instance_variable_set("@#{k}",v) }
|
47
|
+
instance_eval &block if block_given?
|
48
|
+
if @layout.nil?
|
49
|
+
case @type.to_s
|
50
|
+
when "input"
|
51
|
+
layout(10,60, 10, 20)
|
52
|
+
when "list"
|
53
|
+
height = [5, @list.length].min
|
54
|
+
layout(10+height, 60, 5, 20)
|
55
|
+
when "field_list"
|
56
|
+
height = @field_list.length
|
57
|
+
layout(10+height, 60, 5, 20)
|
58
|
+
when "override"
|
59
|
+
$log.debug " override: #{@height},#{@width}, #{@top}, #{@left} "
|
60
|
+
layout(@height,@width, @top, @left)
|
61
|
+
$log.debug " override: #{@layout.inspect}"
|
62
|
+
else
|
63
|
+
height = @form && @form.widgets.length ## quick fix. FIXME
|
64
|
+
height ||= 0
|
65
|
+
layout(10+height,60, 10, 20)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
@window = VER::Window.new(@layout)
|
69
|
+
if @form.nil?
|
70
|
+
@form = RubyCurses::Form.new @window
|
71
|
+
else
|
72
|
+
@form.window = @window
|
73
|
+
end
|
74
|
+
acolor = get_color $reversecolor # this implicitly uses color and bgcolor fooling me often
|
75
|
+
$log.debug " MESSAGE BOX #{@bgcolor} , #{@color} , #{acolor}"
|
76
|
+
@window.bkgd(Ncurses.COLOR_PAIR(acolor));
|
77
|
+
@window.wrefresh
|
78
|
+
@panel = @window.panel
|
79
|
+
Ncurses::Panel.update_panels
|
80
|
+
process_field_list
|
81
|
+
print_borders
|
82
|
+
print_title
|
83
|
+
print_message unless @message.nil?
|
84
|
+
print_input
|
85
|
+
create_buttons
|
86
|
+
@form.repaint
|
87
|
+
@window.wrefresh
|
88
|
+
handle_keys
|
89
|
+
end
|
90
|
+
##
|
91
|
+
# takes care of a field list sent in
|
92
|
+
def process_field_list
|
93
|
+
return if @field_list.nil? or @field_list.length == 0
|
94
|
+
@field_list.each do |f|
|
95
|
+
f.set_form @form
|
96
|
+
end
|
97
|
+
end
|
98
|
+
def default_button offset0
|
99
|
+
@selected_index = offset0
|
100
|
+
end
|
101
|
+
##
|
102
|
+
# value entered by user if type = input
|
103
|
+
def input_value
|
104
|
+
return @input.buffer if !@input.nil?
|
105
|
+
return @listbox.getvalue if !@listbox.nil?
|
106
|
+
end
|
107
|
+
def create_buttons
|
108
|
+
case @button_type.to_s.downcase
|
109
|
+
when "ok"
|
110
|
+
make_buttons ["&OK"]
|
111
|
+
when "ok_cancel" #, "input", "list", "field_list"
|
112
|
+
make_buttons %w[&OK &Cancel]
|
113
|
+
# experience 2009-02-22 12:52 trapping y and n - hopefully wont cause an edit problem
|
114
|
+
@form.bind_key(?o){ press(?\M-o) } # called method takes care of getbyte 1.9
|
115
|
+
@form.bind_key(?c){ press(?\M-c) } # called method takes care of getbyte 1.9
|
116
|
+
when "yes_no"
|
117
|
+
make_buttons %w[&Yes &No]
|
118
|
+
# experience 2009-02-22 12:52 trapping y and n - hopefully wont cause an edit problem
|
119
|
+
@form.bind_key(?y){ press(?\M-y) } # called method takes care of getbyte 1.9
|
120
|
+
@form.bind_key(?n){ press(?\M-n) } # called method takes care of getbyte 1.9
|
121
|
+
when "yes_no_cancel"
|
122
|
+
make_buttons ["&Yes", "&No", "&Cancel"]
|
123
|
+
when "custom"
|
124
|
+
raise "Blank list of buttons passed to custom" if @buttons.nil? or @buttons.size == 0
|
125
|
+
make_buttons @buttons
|
126
|
+
else
|
127
|
+
$log.debug "No type passed for creating messagebox. Using default (OK)"
|
128
|
+
make_buttons ["&OK"]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
def make_buttons names
|
132
|
+
total = names.inject(0) {|total, item| total + item.length + 4}
|
133
|
+
bcol = center_column total
|
134
|
+
|
135
|
+
brow = @layout[:height]-3
|
136
|
+
button_ct=0
|
137
|
+
names.each_with_index do |bname, ix|
|
138
|
+
text = bname
|
139
|
+
#underline = @underlines[ix] if !@underlines.nil?
|
140
|
+
|
141
|
+
button = Button.new @form do
|
142
|
+
text text
|
143
|
+
name bname
|
144
|
+
row brow
|
145
|
+
col bcol
|
146
|
+
#underline underline
|
147
|
+
highlight_background $datacolor
|
148
|
+
color $reversecolor
|
149
|
+
bgcolor $reversecolor
|
150
|
+
end
|
151
|
+
index = button_ct
|
152
|
+
button.command { |form| @selected_index = index; @stop = true; $log.debug "Pressed Button #{bname}";}
|
153
|
+
button_ct += 1
|
154
|
+
bcol += text.length+6
|
155
|
+
end
|
156
|
+
end
|
157
|
+
## message box
|
158
|
+
def stopping?
|
159
|
+
@stop
|
160
|
+
end
|
161
|
+
def handle_keys
|
162
|
+
begin
|
163
|
+
while((ch = @window.getchar()) != 999 )
|
164
|
+
case ch
|
165
|
+
when -1
|
166
|
+
next
|
167
|
+
else
|
168
|
+
press ch
|
169
|
+
break if @stop
|
170
|
+
end
|
171
|
+
end
|
172
|
+
ensure
|
173
|
+
destroy
|
174
|
+
end
|
175
|
+
return @selected_index
|
176
|
+
end
|
177
|
+
def press ch
|
178
|
+
ch = ch.getbyte(0) if ch.class==String ## 1.9
|
179
|
+
case ch
|
180
|
+
when -1
|
181
|
+
return
|
182
|
+
when KEY_F1, 27, ?\C-q.getbyte(0)
|
183
|
+
@selected_index = -1
|
184
|
+
@stop = true
|
185
|
+
return
|
186
|
+
when KEY_ENTER, 10, 13
|
187
|
+
field = @form.get_current_field
|
188
|
+
if field.respond_to? :fire
|
189
|
+
field.fire
|
190
|
+
end
|
191
|
+
#$log.debug "popup ENTER : #{@selected_index} "
|
192
|
+
#$log.debug "popup ENTER : #{field.name}" if !field.nil?
|
193
|
+
@stop = true
|
194
|
+
return
|
195
|
+
when KEY_TAB
|
196
|
+
@form.select_next_field
|
197
|
+
when KEY_BTAB
|
198
|
+
@form.select_prev_field
|
199
|
+
else
|
200
|
+
# fields must return unhandled else we will miss hotkeys.
|
201
|
+
# On messageboxes, often if no edit field, then O and C are hot.
|
202
|
+
field = @form.get_current_field
|
203
|
+
handled = field.handle_key ch
|
204
|
+
|
205
|
+
if handled == :UNHANDLED
|
206
|
+
ret = @form.process_key ch, self ## trying out trigger button
|
207
|
+
end
|
208
|
+
end
|
209
|
+
@form.repaint
|
210
|
+
Ncurses::Panel.update_panels();
|
211
|
+
Ncurses.doupdate();
|
212
|
+
@window.wrefresh
|
213
|
+
end
|
214
|
+
def print_borders
|
215
|
+
width = @layout[:width]
|
216
|
+
height = @layout[:height]
|
217
|
+
@window.print_border_mb 1,2, height, width, $normalcolor, FFI::NCurses::A_REVERSE
|
218
|
+
=begin
|
219
|
+
start = 2
|
220
|
+
hline = "+%s+" % [ "-"*(width-((start+1)*2)) ]
|
221
|
+
hline2 = "|%s|" % [ " "*(width-((start+1)*2)) ]
|
222
|
+
@window.printstring(row=1, col=start, hline, color=$reversecolor)
|
223
|
+
(start).upto(height-2) do |row|
|
224
|
+
@window.printstring row, col=start, hline2, color=$normalcolor, A_REVERSE
|
225
|
+
end
|
226
|
+
@window.printstring(height-2, col=start, hline, color=$reversecolor)
|
227
|
+
=end
|
228
|
+
end
|
229
|
+
def print_title title=@title
|
230
|
+
width = @layout[:width]
|
231
|
+
title = " "+title+" "
|
232
|
+
@window.printstring(row=1,col=(width-title.length)/2,title, color=$normalcolor)
|
233
|
+
end
|
234
|
+
def center_column textlen
|
235
|
+
width = @layout[:width]
|
236
|
+
return (width-textlen)/2
|
237
|
+
end
|
238
|
+
def print_message message=@message, row=nil
|
239
|
+
@message_row = @message_col = 2
|
240
|
+
display_length = @layout[:width]-8
|
241
|
+
$log.debug " print_message: dl:#{display_length} "
|
242
|
+
# XXX this needs to go up and decide height of window
|
243
|
+
if @message_height.nil?
|
244
|
+
@message_height = (message.length/display_length)+2
|
245
|
+
#$log.debug " print_message: mh:#{@message_height}, ml: #{message.length}"
|
246
|
+
end
|
247
|
+
@message_height ||= 1
|
248
|
+
width = @layout[:width]
|
249
|
+
return if message.nil?
|
250
|
+
case @type.to_s
|
251
|
+
when "input"
|
252
|
+
row=(@layout[:height]/3) if row.nil?
|
253
|
+
@message_col = 4
|
254
|
+
when "list"
|
255
|
+
row=3
|
256
|
+
@message_col = 4
|
257
|
+
else
|
258
|
+
row=(@layout[:height]/3) if row.nil?
|
259
|
+
@message_col = (width-message.length)/2
|
260
|
+
@message_col = 4 if @message.is_a? Array
|
261
|
+
@message_col = 4 if @message_col < 4 # this was often disappearing 2010-10-17 13:00
|
262
|
+
#$log.debug "XX ALERT col #{@message_col} w: #{width} len: #{message.length} "
|
263
|
+
end
|
264
|
+
@message_row = row
|
265
|
+
# added 2009-11-05 14:53 to fix erasure of border
|
266
|
+
display_length -= @message_col
|
267
|
+
# 2008-12-30 19:45 experimenting with label so we can get justify and wrapping.
|
268
|
+
# 2011-09-20 trying to take care of when user changes color and bgcolor while calling.
|
269
|
+
clr = @color || :black
|
270
|
+
bgclr = @bgcolor || :white
|
271
|
+
message_label = RubyCurses::Label.new @form, {'text' => message, "name"=>"message_label","row" => row, "col" => @message_col, "display_length" => display_length, "height" => @message_height, 'bgcolor' => bgclr , 'color' => clr}
|
272
|
+
|
273
|
+
end
|
274
|
+
def print_input
|
275
|
+
#return if @type.to_s != "input"
|
276
|
+
@message_height ||= 0
|
277
|
+
@message_row ||= 2
|
278
|
+
@message_col ||= 2
|
279
|
+
r = @message_row + @message_height + 1
|
280
|
+
c = @message_col
|
281
|
+
disp_len = @layout[:width]-8
|
282
|
+
defaultvalue = @default_value || ""
|
283
|
+
input_config = @config["input_config"] || {} # see test1.rb for usage example
|
284
|
+
case @type.to_s
|
285
|
+
when "input"
|
286
|
+
@input = RubyCurses::Field.new @form, input_config do
|
287
|
+
name "input"
|
288
|
+
row r
|
289
|
+
col c
|
290
|
+
display_length disp_len
|
291
|
+
set_buffer defaultvalue
|
292
|
+
end
|
293
|
+
when "list"
|
294
|
+
list = @list
|
295
|
+
selection_mode = @list_selection_mode
|
296
|
+
default_values = @default_values
|
297
|
+
$log.debug " value of select_mode #{selection_mode}"
|
298
|
+
@listbox = RubyCurses::Listbox.new @form do
|
299
|
+
name "input"
|
300
|
+
row r
|
301
|
+
col c
|
302
|
+
|
303
|
+
color 'black'
|
304
|
+
bgcolor 'white'
|
305
|
+
# now listcellrenderer only uses BOLD for selected, with a white bgcolor
|
306
|
+
# so here it won't show up on white bg
|
307
|
+
selected_color 'red'
|
308
|
+
selected_bgcolor 'black'
|
309
|
+
# just added 2010-10-14 21:24
|
310
|
+
border_attrib :reverse
|
311
|
+
width 30
|
312
|
+
height 6
|
313
|
+
list list
|
314
|
+
# ?? display_length 30
|
315
|
+
#set_buffer defaultvalue
|
316
|
+
selection_mode selection_mode
|
317
|
+
default_values default_values
|
318
|
+
is_popup false
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
def configure(*val , &block)
|
323
|
+
case val.size
|
324
|
+
when 1
|
325
|
+
return @config[val[0]]
|
326
|
+
when 2
|
327
|
+
@config[val[0]] = val[1]
|
328
|
+
instance_variable_set("@#{val[0]}", val[1])
|
329
|
+
end
|
330
|
+
instance_eval &block if block_given?
|
331
|
+
end
|
332
|
+
def cget param
|
333
|
+
@config[param]
|
334
|
+
end
|
335
|
+
|
336
|
+
def layout(height=0, width=0, top=0, left=0)
|
337
|
+
@layout = { :height => height, :width => width, :top => top, :left => left }
|
338
|
+
end
|
339
|
+
def destroy
|
340
|
+
$log.debug "DESTROY : messagebox"
|
341
|
+
panel = @window.panel
|
342
|
+
#Ncurses::Panel.del_panel(panel) if !panel.nil?
|
343
|
+
panel.del_panel if !panel.nil?
|
344
|
+
@window.delwin if !@window.nil?
|
345
|
+
Ncurses::Panel.update_panels # 2011-10-1 so window below doesn't have a black rectangle
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|