rbcurse 0.1.3 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +126 -0
- data/Manifest.txt +53 -20
- data/README.markdown +423 -0
- data/Rakefile +3 -1
- data/examples/keytest.rb +177 -0
- data/examples/mpad2.rb +156 -0
- data/examples/newtesttabp.rb +121 -0
- data/examples/rfe.rb +48 -10
- data/examples/rfe_renderer.rb +4 -4
- data/examples/rvimsplit.rb +376 -0
- data/examples/sqlc.rb +97 -106
- data/examples/sqlm.rb +446 -0
- data/examples/test1.rb +4 -4
- data/examples/test2.rb +12 -12
- data/examples/testchars.rb +140 -0
- data/examples/testkeypress.rb +9 -4
- data/examples/testmulticomp.rb +72 -0
- data/examples/testscroller.rb +136 -0
- data/examples/testscrolllb.rb +86 -0
- data/examples/testscrollp.rb +87 -0
- data/examples/testscrollta.rb +80 -0
- data/examples/testscrolltable.rb +166 -0
- data/examples/testsplit.rb +87 -0
- data/examples/testsplit2.rb +123 -0
- data/examples/testsplit3.rb +215 -0
- data/examples/testsplit3_1.rb +244 -0
- data/examples/testsplit3a.rb +215 -0
- data/examples/testsplit3b.rb +237 -0
- data/examples/testsplitta.rb +148 -0
- data/examples/testsplittv.rb +142 -0
- data/examples/testsplittvv.rb +144 -0
- data/examples/testtable.rb +1 -1
- data/examples/testtabp.rb +3 -2
- data/examples/testtestw.rb +69 -0
- data/examples/testtodo.rb +5 -3
- data/examples/testtpane.rb +203 -0
- data/examples/testtpane2.rb +145 -0
- data/examples/testtpanetable.rb +199 -0
- data/examples/viewtodo.rb +5 -3
- data/lib/rbcurse.rb +1 -1
- data/lib/rbcurse/celleditor.rb +2 -2
- data/lib/rbcurse/colormap.rb +5 -5
- data/lib/rbcurse/defaultlistselectionmodel.rb +3 -3
- data/lib/rbcurse/io.rb +663 -0
- data/lib/rbcurse/listeditable.rb +306 -0
- data/lib/rbcurse/listkeys.rb +15 -15
- data/lib/rbcurse/listscrollable.rb +168 -27
- data/lib/rbcurse/mapper.rb +35 -13
- data/lib/rbcurse/rchangeevent.rb +28 -0
- data/lib/rbcurse/rform.rb +845 -0
- data/lib/rbcurse/rlistbox.rb +144 -34
- data/lib/rbcurse/rmessagebox.rb +10 -5
- data/lib/rbcurse/rmulticontainer.rb +325 -0
- data/lib/rbcurse/rmultitextview.rb +306 -0
- data/lib/rbcurse/rscrollform.rb +369 -0
- data/lib/rbcurse/rscrollpane.rb +511 -0
- data/lib/rbcurse/rsplitpane.rb +820 -0
- data/lib/rbcurse/rtabbedpane.rb +737 -109
- data/lib/rbcurse/rtabbedwindow.rb +326 -0
- data/lib/rbcurse/rtable.rb +220 -64
- data/lib/rbcurse/rtextarea.rb +340 -181
- data/lib/rbcurse/rtextview.rb +237 -101
- data/lib/rbcurse/rviewport.rb +203 -0
- data/lib/rbcurse/rwidget.rb +919 -95
- data/lib/rbcurse/scrollable.rb +7 -7
- data/lib/rbcurse/selectable.rb +4 -4
- data/lib/rbcurse/table/tablecellrenderer.rb +3 -0
- data/lib/rbcurse/undomanager.rb +181 -0
- data/lib/rbcurse/vieditable.rb +100 -0
- data/lib/ver/window.rb +471 -21
- metadata +66 -22
- data/README.txt +0 -312
- data/examples/testd.db +0 -0
- data/examples/todocsv.csv +0 -28
@@ -0,0 +1,203 @@
|
|
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/rchangeevent'
|
24
|
+
|
25
|
+
include Ncurses
|
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
|
+
end
|
53
|
+
def init_vars
|
54
|
+
#@curpos = @pcol = @toprow = @current_index = 0
|
55
|
+
should_create_buffer = true
|
56
|
+
@border_width = 2
|
57
|
+
end
|
58
|
+
# set the component to be viewed
|
59
|
+
def set_view ch
|
60
|
+
@child = ch
|
61
|
+
end
|
62
|
+
def set_view_size h,w
|
63
|
+
# calling the property shoudl uniformally trigger fire_property_change
|
64
|
+
$log.debug " setting viewport to h #{h} , w #{w} "
|
65
|
+
height(h)
|
66
|
+
width(w)
|
67
|
+
fire_state_changed
|
68
|
+
#fire_handler :PROPERTY_CHANGE, self # XXX should it be an event STATE_CHANGED with details
|
69
|
+
end
|
70
|
+
##
|
71
|
+
# Set the row and col of the child, that the viewport starts displaying.
|
72
|
+
# Used to initialize the view, and later if scrolling.
|
73
|
+
# Initially would be set to 0,0.
|
74
|
+
#
|
75
|
+
def set_view_position r,c
|
76
|
+
return false if r < 0 or c < 0
|
77
|
+
# 2010-02-04 19:29 TRYING -2 for borders
|
78
|
+
$log.debug " set_view if #{r} +1+ #{@height} - #{@border_width} )} >=#{@child.height} "
|
79
|
+
# 2010-02-12 15:33 XXX made > into >= and added +1 since -1 in set_buffering
|
80
|
+
# testscrollp was crashing out when child height exceeded
|
81
|
+
if r+ (@height+1-@border_width) >= @child.height
|
82
|
+
# basically r + (:bottom - :screen_top) < @child.height
|
83
|
+
#if r+ (@height) >= @child.height
|
84
|
+
$log.debug " set_view_position : trying to exceed ht #{r} + #{@height} > #{@child.height} returned false"
|
85
|
+
return false
|
86
|
+
end
|
87
|
+
# testscrollp was printing junk on right end. Why the 1?
|
88
|
+
if c+ (@width+1-@border_width) >=@child.width
|
89
|
+
#if c+ (@width) >=@child.width
|
90
|
+
$log.debug " set_view_position : trying to exceed width #{c} + #{@width} . returned false"
|
91
|
+
return false
|
92
|
+
end
|
93
|
+
$log.debug " VP row #{@row} col #{@col}, now will be #{r} , #{c} "
|
94
|
+
row(r) # commnting off 2010-02-06 22:47
|
95
|
+
col(c) # commnting off 2010-02-06 22:47
|
96
|
+
# next call sets pminrow and pmincol
|
97
|
+
$log.debug " VP setting child buffer pmin to #{r} #{c} "
|
98
|
+
@child.get_buffer().set_pad_top_left(r, c)
|
99
|
+
# replaced this on 2010-02-26 11:49 HOPE IT WORKS XXX
|
100
|
+
#@child.fire_property_change("row", r, r) # XXX quick dirty, this should happen
|
101
|
+
@child.repaint_required(true)
|
102
|
+
@repaint_required = true
|
103
|
+
#fire_handler :PROPERTY_CHANGE, self
|
104
|
+
fire_state_changed
|
105
|
+
return true
|
106
|
+
end
|
107
|
+
# instead of using row and col to increment, try using this, since this is what's actually incremented.
|
108
|
+
def get_pad_top_left
|
109
|
+
p = @child.get_buffer()
|
110
|
+
return p.pminrow, p.pmincol
|
111
|
+
end
|
112
|
+
def repaint # viewport
|
113
|
+
return unless @repaint_required
|
114
|
+
# should call child's repaint onto pad
|
115
|
+
# then this should return clipped pad
|
116
|
+
$log.debug "VP calling child #{@child.name} repaint"
|
117
|
+
#x @graphic.wclear # required otherwise bottom of scrollpane had old rows still repeated. 2010-01-17 22:51
|
118
|
+
@child.repaint_all
|
119
|
+
@child.repaint
|
120
|
+
paint
|
121
|
+
end
|
122
|
+
def getvalue
|
123
|
+
# TODO ???
|
124
|
+
end
|
125
|
+
## most likely should just return an unhandled and not try being intelligent
|
126
|
+
# should viewport handle keys or should parent do so directly to child
|
127
|
+
def handle_key ch
|
128
|
+
# if this gets key it should just hand it to child
|
129
|
+
if @child != nil
|
130
|
+
ret = @child.handle_key ch
|
131
|
+
# 2010-01-19 19:26 commenting off repaint to see.
|
132
|
+
return :UNHANDLED if ret == :UNHANDLED
|
133
|
+
# moved below return so only if table handles
|
134
|
+
@repaint_required=true # added 2009-12-27 22:25 BUFFERED WHY ??
|
135
|
+
else
|
136
|
+
return :UNHANDLED
|
137
|
+
end
|
138
|
+
return 0
|
139
|
+
#$log.debug "TV after loop : curpos #{@curpos} blen: #{@buffer.length}"
|
140
|
+
end
|
141
|
+
def paint
|
142
|
+
@repaint_required = false
|
143
|
+
@repaint_all = false
|
144
|
+
end
|
145
|
+
# set height
|
146
|
+
# a container must pass down changes in size to it's children
|
147
|
+
#+ 2010-02-04 18:06 - i am not sure about this. When viewport is set then it passes down
|
148
|
+
#+ changes to child which user did not intend. Maybe in splitpane it is okay but other cases?
|
149
|
+
#+ Perhaps its okay if scrollpane gets larger than child, not otherwise.
|
150
|
+
# added 2010-01-16 23:55
|
151
|
+
def height(*val)
|
152
|
+
return @height if val.empty?
|
153
|
+
oldvalue = @height || 0
|
154
|
+
super
|
155
|
+
@height = val[0]
|
156
|
+
return if @child == nil
|
157
|
+
delta = @height - oldvalue
|
158
|
+
return if delta == 0
|
159
|
+
@repaint_required = true
|
160
|
+
if @child.height.nil?
|
161
|
+
@child.height = @height
|
162
|
+
$log.warn " viewport setting child #{@child.name} to default h of #{@height} -- child is usually larger. "
|
163
|
+
else
|
164
|
+
if @cascade_changes
|
165
|
+
$log.debug "warn!! viewport adding #{delta} to child ht #{child.height} "
|
166
|
+
@child.height += delta
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
# set width
|
171
|
+
# a container must pass down changes in size to it's children
|
172
|
+
# added 2010-01-16 23:55
|
173
|
+
def width(*val)
|
174
|
+
return @width if val.empty?
|
175
|
+
oldvalue = @width || 0
|
176
|
+
super
|
177
|
+
@width = val[0]
|
178
|
+
return if @child == nil
|
179
|
+
delta = @width - oldvalue
|
180
|
+
return if delta == 0
|
181
|
+
@repaint_required = true
|
182
|
+
# another safeguard if user did not enter. usesomething sensible 2010-01-17 15:23
|
183
|
+
if @child.width.nil?
|
184
|
+
@child.width = @width
|
185
|
+
$log.warn " viewport setting child #{@child.name} to default w of #{@width}. Usually child is larger. "
|
186
|
+
else
|
187
|
+
## sometime we are needless increasing. this happens when we set viewport and
|
188
|
+
##+ child has been set. Or may do only if scrollpane is getting larger than child
|
189
|
+
##+ largely a situation with splitpanes.
|
190
|
+
if @cascade_changes
|
191
|
+
$log.debug "warn!! viewport adding #{delta} to child wt #{child.width} "
|
192
|
+
@child.width += delta
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
# should this be in widget ?
|
197
|
+
# inform listeners that state has changed
|
198
|
+
def fire_state_changed
|
199
|
+
@sce = ChangeEvent.new(self) if @sce.nil?
|
200
|
+
fire_handler :STATE_CHANGE, @sce
|
201
|
+
end
|
202
|
+
end # class viewport
|
203
|
+
end # module
|
data/lib/rbcurse/rwidget.rb
CHANGED
@@ -23,10 +23,10 @@ TODO
|
|
23
23
|
require 'rubygems'
|
24
24
|
require 'ncurses'
|
25
25
|
require 'logger'
|
26
|
-
require 'rbcurse/mapper'
|
26
|
+
#require 'rbcurse/mapper'
|
27
27
|
require 'rbcurse/colormap'
|
28
|
-
|
29
|
-
|
28
|
+
require 'rbcurse/orderedhash'
|
29
|
+
require 'rbcurse/io'
|
30
30
|
|
31
31
|
module DSL
|
32
32
|
## others may not want this, if = sent, it creates DSL and sets
|
@@ -85,6 +85,18 @@ class Module
|
|
85
85
|
|
86
86
|
end
|
87
87
|
|
88
|
+
# 2009-10-04 14:13 added RK after suggestion on http://www.ruby-forum.com/topic/196618#856703
|
89
|
+
# these are for 1.8 compatibility
|
90
|
+
class Fixnum
|
91
|
+
def ord
|
92
|
+
self
|
93
|
+
end
|
94
|
+
## mostly for control and meta characters
|
95
|
+
def getbyte(n)
|
96
|
+
self
|
97
|
+
end
|
98
|
+
end unless "a"[0] == "a"
|
99
|
+
|
88
100
|
include Ncurses
|
89
101
|
module RubyCurses
|
90
102
|
extend self
|
@@ -92,6 +104,14 @@ module RubyCurses
|
|
92
104
|
class FieldValidationException < RuntimeError
|
93
105
|
end
|
94
106
|
module Utils
|
107
|
+
## this is the numeric argument used to repeat and action by repeatm()
|
108
|
+
$multiplier = 0
|
109
|
+
|
110
|
+
# 2010-03-04 18:01
|
111
|
+
## this may come in handy for methods to know whether they are inside a batch action or not
|
112
|
+
# e.g. a single call of foo() may set a var, a repeated call of foo() may append to var
|
113
|
+
$inside_multiplier_action = true
|
114
|
+
|
95
115
|
##
|
96
116
|
# wraps text given max length, puts newlines in it.
|
97
117
|
# it does not take into account existing newlines
|
@@ -111,19 +131,19 @@ module RubyCurses
|
|
111
131
|
case keycode
|
112
132
|
when 33..126
|
113
133
|
return keycode.chr
|
114
|
-
when ?\C-a .. ?\C-z
|
115
|
-
return "C-" + (keycode + ?a -1).chr
|
116
|
-
when ?\M-A..?\M-z
|
134
|
+
when ?\C-a.getbyte(0) .. ?\C-z.getbyte(0)
|
135
|
+
return "C-" + (keycode + ?a.getbyte(0) -1).chr
|
136
|
+
when ?\M-A.getbyte(0)..?\M-z.getbyte(0)
|
117
137
|
return "M-"+ (keycode - 128).chr
|
118
|
-
when ?\M-\C-A..?\M-\C-Z
|
138
|
+
when ?\M-\C-A.getbyte(0)..?\M-\C-Z.getbyte(0)
|
119
139
|
return "M-C-"+ (keycode - 32).chr
|
120
|
-
when ?\M-0..?\M-9
|
121
|
-
return "M-"+ (keycode-?\M-0).to_s
|
122
|
-
when 32
|
140
|
+
when ?\M-0.getbyte(0)..?\M-9.getbyte(0)
|
141
|
+
return "M-"+ (keycode-?\M-0.getbyte(0)).to_s
|
142
|
+
when 32
|
123
143
|
return "Space"
|
124
|
-
when 27
|
144
|
+
when 27
|
125
145
|
return "Esc"
|
126
|
-
when ?\C-]
|
146
|
+
when ?\C-].getbyte(0)
|
127
147
|
return "C-]"
|
128
148
|
when 258
|
129
149
|
return "down"
|
@@ -145,8 +165,11 @@ module RubyCurses
|
|
145
165
|
return "M-S-tab"
|
146
166
|
when 393..402
|
147
167
|
return "M-F"+ (keycode-392).to_s
|
168
|
+
when 0
|
169
|
+
return "C-space" # i hope this is correct, just guessing
|
148
170
|
else
|
149
171
|
others=[?\M--,?\M-+,?\M-=,?\M-',?\M-",?\M-;,?\M-:,?\M-\,, ?\M-.,?\M-<,?\M->,?\M-?,?\M-/]
|
172
|
+
others.collect! {|x| x.getbyte(0) } ## added 2009-10-04 14:25 for 1.9
|
150
173
|
s_others=%w[M-- M-+ M-= M-' M-" M-; M-: M-, M-. M-< M-> M-? M-/ ]
|
151
174
|
if others.include? keycode
|
152
175
|
index = others.index keycode
|
@@ -165,13 +188,91 @@ module RubyCurses
|
|
165
188
|
end
|
166
189
|
return acolor
|
167
190
|
end
|
191
|
+
## repeats the given action based on how value of universal numerica argument
|
192
|
+
##+ set using the C-u key. Or in vim-mode using numeric keys
|
193
|
+
def repeatm
|
194
|
+
$inside_multiplier_action = true
|
195
|
+
_multiplier = ( ($multiplier.nil? || $multiplier == 0) ? 1 : $multiplier )
|
196
|
+
_multiplier.times { yield }
|
197
|
+
$multiplier = 0
|
198
|
+
$inside_multiplier_action = false
|
199
|
+
end
|
200
|
+
|
201
|
+
##
|
202
|
+
# bind an action to a key, required if you create a button which has a hotkey
|
203
|
+
# or a field to be focussed on a key, or any other user defined action based on key
|
204
|
+
# e.g. bind_key ?\C-x, object, block
|
205
|
+
# added 2009-01-06 19:13 since widgets need to handle keys properly
|
206
|
+
# 2010-02-24 12:43 trying to take in multiple key bindings, TODO unbind
|
207
|
+
# TODO add symbol so easy to map from config file or mapping file
|
208
|
+
def bind_key keycode, *args, &blk
|
209
|
+
@key_handler ||= {}
|
210
|
+
if !block_given?
|
211
|
+
blk = args.pop
|
212
|
+
raise "If block not passed, last arg should be a method symbol" if !blk.is_a? Symbol
|
213
|
+
$log.debug " #{@name} bind_key received a symbol #{blk} "
|
214
|
+
end
|
215
|
+
case keycode
|
216
|
+
when String
|
217
|
+
keycode = keycode.getbyte(0) #if keycode.class==String ## 1.9 2009-10-05 19:40
|
218
|
+
$log.debug " #{name} Widg String called bind_key BIND #{keycode}, #{keycode_tos(keycode)} "
|
219
|
+
@key_handler[keycode] = blk
|
220
|
+
when Array
|
221
|
+
# for starters lets try with 2 keys only
|
222
|
+
a0 = keycode[0]
|
223
|
+
a0 = keycode[0].getbyte(0) if keycode[0].class == String
|
224
|
+
a1 = keycode[1]
|
225
|
+
a1 = keycode[1].getbyte(0) if keycode[1].class == String
|
226
|
+
@key_handler[a0] ||= OrderedHash.new
|
227
|
+
@key_handler[a0][a1] = blk
|
228
|
+
else
|
229
|
+
@key_handler[keycode] = blk
|
230
|
+
end
|
231
|
+
@key_args ||= {}
|
232
|
+
@key_args[keycode] = args
|
233
|
+
end
|
234
|
+
# e.g. process_key ch, self
|
235
|
+
# returns UNHANDLED if no block for it
|
236
|
+
# after form handles basic keys, it gives unhandled key to current field, if current field returns
|
237
|
+
# unhandled, then it checks this map.
|
238
|
+
# added 2009-01-06 19:13 since widgets need to handle keys properly
|
239
|
+
# added 2009-01-18 12:58 returns ret val of blk.call
|
240
|
+
# so that if block does not handle, the key can still be handled
|
241
|
+
# e.g. table last row, last col does not handle, so it will auto go to next field
|
242
|
+
# 2010-02-24 13:45 handles 2 key combinations, copied from Form, must be identical in logic
|
243
|
+
# except maybe for window pointer. TODO not tested
|
244
|
+
def _process_key keycode, object, window
|
245
|
+
return :UNHANDLED if @key_handler.nil?
|
246
|
+
blk = @key_handler[keycode]
|
247
|
+
return :UNHANDLED if blk.nil?
|
248
|
+
if blk.is_a? OrderedHash
|
249
|
+
ch = window.getch
|
250
|
+
if ch < 0 || ch > 255
|
251
|
+
#next
|
252
|
+
return nil
|
253
|
+
end
|
254
|
+
$log.debug " process_key: got #{keycode} , #{ch} "
|
255
|
+
yn = ch.chr
|
256
|
+
blk1 = blk[ch]
|
257
|
+
return nil if blk1.nil?
|
258
|
+
$log.debug " process_key: found block for #{keycode} , #{ch} "
|
259
|
+
blk = blk1
|
260
|
+
end
|
261
|
+
#$log.debug "called process_key #{object}, kc: #{keycode}, args #{@key_args[keycode]}"
|
262
|
+
if blk.is_a? Symbol
|
263
|
+
return send(blk, *@key_args[keycode])
|
264
|
+
else
|
265
|
+
return blk.call object, *@key_args[keycode]
|
266
|
+
end
|
267
|
+
#0
|
268
|
+
end
|
168
269
|
end
|
169
270
|
|
170
271
|
module EventHandler
|
171
272
|
##
|
172
273
|
# bind an event to a block, optional args will also be passed when calling
|
173
274
|
def bind event, *xargs, &blk
|
174
|
-
|
275
|
+
#$log.debug "#{self} called EventHandler BIND #{event}, args:#{xargs} "
|
175
276
|
@handler ||= {}
|
176
277
|
@event_args ||= {}
|
177
278
|
#@handler[event] = blk
|
@@ -192,7 +293,7 @@ module RubyCurses
|
|
192
293
|
# currently object usually contains self which is perhaps a bit of a waste,
|
193
294
|
# could contain an event object with source, and some relevant methods or values
|
194
295
|
def fire_handler event, object
|
195
|
-
|
296
|
+
$log.debug " def fire_handler evt:#{event}, o: #{object.class}, hdnler:#{@handler}"
|
196
297
|
if !@handler.nil?
|
197
298
|
#blk = @handler[event]
|
198
299
|
ablk = @handler[event]
|
@@ -200,6 +301,7 @@ module RubyCurses
|
|
200
301
|
aeve = @event_args[event]
|
201
302
|
ablk.each_with_index do |blk, ix|
|
202
303
|
#$log.debug "#{self} called EventHandler firehander #{@name}, #{event}, obj: #{object},args: #{aeve[ix]}"
|
304
|
+
$log.debug "#{self} called EventHandler firehander #{@name}, #{event}"
|
203
305
|
blk.call object, *aeve[ix]
|
204
306
|
end
|
205
307
|
end # if
|
@@ -207,10 +309,16 @@ module RubyCurses
|
|
207
309
|
end
|
208
310
|
## added on 2009-01-08 00:33
|
209
311
|
# goes with dsl_property
|
210
|
-
# Need to inform listeners
|
312
|
+
# Need to inform listeners - done 2010-02-25 23:09
|
211
313
|
def fire_property_change text, oldvalue, newvalue
|
212
314
|
#$log.debug " FPC #{self}: #{text} #{oldvalue}, #{newvalue}"
|
213
|
-
@
|
315
|
+
if @pce.nil?
|
316
|
+
@pce = PropertyChangeEvent.new(self, text, oldvalue, newvalue)
|
317
|
+
else
|
318
|
+
@pce.set( self, text, oldvalue, newvalue)
|
319
|
+
end
|
320
|
+
fire_handler :PROPERTY_CHANGE, @pce
|
321
|
+
@repaint_required = true # this was a hack and shoudl go, someone wanted to set this so it would repaint (viewport line 99 fire_prop
|
214
322
|
end
|
215
323
|
|
216
324
|
end # module eventh
|
@@ -252,11 +360,8 @@ module RubyCurses
|
|
252
360
|
include EventHandler
|
253
361
|
include ConfigSetup
|
254
362
|
include RubyCurses::Utils
|
363
|
+
include Io # added 2010-03-06 13:05
|
255
364
|
dsl_property :text
|
256
|
-
#dsl_accessor :text_variable
|
257
|
-
#dsl_accessor :underline # offset of text to underline DEPRECATED
|
258
|
-
dsl_property :width # desired width of text
|
259
|
-
#dsl_accessor :wrap_length # wrap length of text, if applic UNUSED
|
260
365
|
|
261
366
|
# next 3 to be checked if used or not. Copied from TK.
|
262
367
|
dsl_property :select_foreground, :select_background # color init_pair
|
@@ -270,7 +375,7 @@ module RubyCurses
|
|
270
375
|
dsl_property :attr # attribute bold, normal, reverse
|
271
376
|
dsl_accessor :name # name to refr to or recall object by_name
|
272
377
|
attr_accessor :id #, :zorder
|
273
|
-
attr_accessor :curpos # cursor position inside object
|
378
|
+
attr_accessor :curpos # cursor position inside object - column, not row.
|
274
379
|
attr_reader :config # COULD GET AXED SOON NOTE
|
275
380
|
attr_accessor :form # made accessor 2008-11-27 22:32 so menu can set
|
276
381
|
attr_accessor :state # normal, selected, highlighted
|
@@ -278,11 +383,31 @@ module RubyCurses
|
|
278
383
|
dsl_property :visible # boolean # 2008-12-09 11:29
|
279
384
|
#attr_accessor :modified # boolean, value modified or not (moved from field 2009-01-18 00:14 )
|
280
385
|
dsl_accessor :help_text # added 2009-01-22 17:41 can be used for status/tooltips
|
386
|
+
|
387
|
+
dsl_property :preferred_width # added 2009-10-28 13:40 for splitpanes and better resizing
|
388
|
+
dsl_property :preferred_height # added 2009-10-28 13:40 for splitpanes and better resizing
|
389
|
+
dsl_property :min_width # added 2009-10-28 13:40 for splitpanes and better resizing
|
390
|
+
dsl_property :min_height # added 2009-10-28 13:40 for splitpanes and better resizing
|
391
|
+
|
392
|
+
## 2010-01-05 13:27 create buffer conditionally, if enclosing component asks. Needs to be passed down
|
393
|
+
##+ to further children or editor components. Default false.
|
394
|
+
attr_accessor :should_create_buffer # added 2010-01-05 13:16 BUFFERED, trying to create buffersonly where required.
|
281
395
|
|
396
|
+
## I think parent_form was not a good idea since i can't add parent widget offsets
|
397
|
+
##+ thus we should use parent_comp and push up.
|
398
|
+
attr_accessor :parent_component # added 2010-01-12 23:28 BUFFERED - to bubble up
|
399
|
+
# tired of getting the cursor wrong and guessing, i am now going to try to get absolute
|
400
|
+
# coordinates - 2010-02-07 20:17 this should be updated by parent.
|
401
|
+
attr_accessor :ext_col_offset, :ext_row_offset # 2010-02-07 20:16 to get abs position for cursor
|
402
|
+
#attr_accessor :manages_cursor # does this widget manage cursor, or should form handle it 2010-02-07 20:54
|
403
|
+
attr_accessor :rows_panned # moved from form, how many rows scrolled.panned 2010-02-11 15:26
|
404
|
+
attr_accessor :cols_panned # moved from form, how many cols scrolled.panned 2010-02-11 15:26
|
405
|
+
|
282
406
|
def initialize form, aconfig={}, &block
|
283
407
|
@form = form
|
284
408
|
@bgcolor ||= "black" # 0
|
285
409
|
@row_offset = @col_offset = 0
|
410
|
+
@ext_row_offset = @ext_col_offset = 0 # 2010-02-07 20:18
|
286
411
|
@state = :NORMAL
|
287
412
|
@color ||= "white" # $datacolor
|
288
413
|
@attr = nil
|
@@ -296,6 +421,8 @@ module RubyCurses
|
|
296
421
|
def init_vars
|
297
422
|
# just in case anyone does a super. Not putting anything here
|
298
423
|
# since i don't want anyone accidentally overriding
|
424
|
+
@buffer_modified = false
|
425
|
+
#@manages_cursor = false # form should manage it, I will pass row and col to it. XXX ?
|
299
426
|
end
|
300
427
|
|
301
428
|
# modified
|
@@ -330,6 +457,10 @@ module RubyCurses
|
|
330
457
|
def on_leave
|
331
458
|
fire_handler :LEAVE, self
|
332
459
|
end
|
460
|
+
##
|
461
|
+
# @return row and col of a widget where painting data actually starts
|
462
|
+
# row and col is where a widget starts. offsets usually take into account borders.
|
463
|
+
# the offsets typically are where the cursor should be positioned inside, upon on_enter.
|
333
464
|
def rowcol
|
334
465
|
# $log.debug "widgte rowcol : #{@row+@row_offset}, #{@col+@col_offset}"
|
335
466
|
return @row+@row_offset, @col+@col_offset
|
@@ -356,18 +487,19 @@ module RubyCurses
|
|
356
487
|
else
|
357
488
|
acolor = $datacolor
|
358
489
|
end
|
359
|
-
@
|
490
|
+
@graphic.printstring r, c, "%-*s" % [len, value], acolor, @attr
|
360
491
|
# next line should be in same color but only have @att so we can change att is nec
|
361
492
|
#@form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, @bgcolor, nil)
|
493
|
+
@buffer_modified = true # required for form to call buffer_to_screen
|
362
494
|
end
|
363
495
|
|
364
496
|
def destroy
|
365
|
-
$log.debug "DESTROY : widget"
|
497
|
+
$log.debug "DESTROY : widget #{@name} "
|
366
498
|
panel = @window.panel
|
367
499
|
Ncurses::Panel.del_panel(panel) if !panel.nil?
|
368
500
|
@window.delwin if !@window.nil?
|
369
501
|
end
|
370
|
-
# @
|
502
|
+
# @deprecated pls call windows method
|
371
503
|
def printstring(win, r,c,string, color, att = Ncurses::A_NORMAL)
|
372
504
|
|
373
505
|
att = Ncurses::A_NORMAL if att.nil?
|
@@ -399,6 +531,14 @@ module RubyCurses
|
|
399
531
|
raise "Form is nil in set_form" if form.nil?
|
400
532
|
@form = form
|
401
533
|
@id = form.add_widget(self) if !form.nil? and form.respond_to? :add_widget
|
534
|
+
# 2009-10-29 15:04 use form.window, unless buffer created
|
535
|
+
# should not use form.window so explicitly everywhere.
|
536
|
+
# added 2009-12-27 20:05 BUFFERED in case child object needs a form.
|
537
|
+
# We don;t wish to overwrite the graphic object
|
538
|
+
if @graphic.nil?
|
539
|
+
$log.debug " setting graphic to form window for #{self.class}, #{form} "
|
540
|
+
@graphic = form.window unless form.nil? # use screen for writing, not buffer
|
541
|
+
end
|
402
542
|
end
|
403
543
|
# puts cursor on correct row.
|
404
544
|
def set_form_row
|
@@ -407,9 +547,13 @@ module RubyCurses
|
|
407
547
|
@form.row = @row + 1
|
408
548
|
end
|
409
549
|
# set cursor on correct column, widget
|
410
|
-
|
411
|
-
|
412
|
-
@
|
550
|
+
# Ideally, this should be overriden, as it is not likely to be correct.
|
551
|
+
def set_form_col col1=@curpos
|
552
|
+
@curpos = col1 || 0 # 2010-01-14 21:02
|
553
|
+
#@form.col = @col + @col_offset + @curpos
|
554
|
+
c = @col + @col_offset + @curpos
|
555
|
+
$log.debug " #{@name} widget WARNING super set_form_col #{c}, #{@form} "
|
556
|
+
setrowcol nil, c
|
413
557
|
end
|
414
558
|
def hide
|
415
559
|
@visible = false
|
@@ -446,11 +590,32 @@ module RubyCurses
|
|
446
590
|
# or a field to be focussed on a key, or any other user defined action based on key
|
447
591
|
# e.g. bind_key ?\C-x, object, block
|
448
592
|
# added 2009-01-06 19:13 since widgets need to handle keys properly
|
449
|
-
|
450
|
-
|
593
|
+
# 2010-02-24 12:43 trying to take in multiple key bindings, TODO unbind
|
594
|
+
# TODO add symbol so easy to map from config file or mapping file
|
595
|
+
def OLDbind_key keycode, *args, &blk
|
451
596
|
@key_handler ||= {}
|
597
|
+
if !block_given?
|
598
|
+
blk = args.pop
|
599
|
+
raise "If block not passed, last arg should be a method symbol" if !blk.is_a? Symbol
|
600
|
+
$log.debug " #{@name} bind_key received a symbol #{blk} "
|
601
|
+
end
|
602
|
+
case keycode
|
603
|
+
when String
|
604
|
+
$log.debug "Widg String called bind_key BIND #{keycode} #{keycode_tos(keycode)} "
|
605
|
+
keycode = keycode.getbyte(0) #if keycode.class==String ## 1.9 2009-10-05 19:40
|
606
|
+
@key_handler[keycode] = blk
|
607
|
+
when Array
|
608
|
+
# for starters lets try with 2 keys only
|
609
|
+
a0 = keycode[0]
|
610
|
+
a0 = keycode[0].getbyte(0) if keycode[0].class == String
|
611
|
+
a1 = keycode[1]
|
612
|
+
a1 = keycode[1].getbyte(0) if keycode[1].class == String
|
613
|
+
@key_handler[a0] ||= OrderedHash.new
|
614
|
+
@key_handler[a0][a1] = blk
|
615
|
+
else
|
616
|
+
@key_handler[keycode] = blk
|
617
|
+
end
|
452
618
|
@key_args ||= {}
|
453
|
-
@key_handler[keycode] = blk
|
454
619
|
@key_args[keycode] = args
|
455
620
|
end
|
456
621
|
##
|
@@ -468,13 +633,10 @@ module RubyCurses
|
|
468
633
|
# added 2009-01-18 12:58 returns ret val of blk.call
|
469
634
|
# so that if block does not handle, the key can still be handled
|
470
635
|
# e.g. table last row, last col does not handle, so it will auto go to next field
|
636
|
+
# 2010-02-24 13:45 handles 2 key combinations, copied from Form, must be identical in logic
|
637
|
+
# except maybe for window pointer. TODO not tested
|
471
638
|
def process_key keycode, object
|
472
|
-
return
|
473
|
-
blk = @key_handler[keycode]
|
474
|
-
return :UNHANDLED if blk.nil?
|
475
|
-
#$log.debug "called process_key #{object}, #{@key_args[keycode]}"
|
476
|
-
return blk.call object, *@key_args[keycode]
|
477
|
-
#0
|
639
|
+
return _process_key keycode, object, @graphic
|
478
640
|
end
|
479
641
|
##
|
480
642
|
# to be added at end of handle_key of widgets so instlalled actions can be checked
|
@@ -482,6 +644,346 @@ module RubyCurses
|
|
482
644
|
ret = process_key ch, self
|
483
645
|
return :UNHANDLED if ret == :UNHANDLED
|
484
646
|
end
|
647
|
+
# @since 0.1.3
|
648
|
+
def get_preferred_size
|
649
|
+
return @preferred_height, @preferred_width
|
650
|
+
end
|
651
|
+
##
|
652
|
+
# creates a buffer for the widget to write to.
|
653
|
+
# This is typically called in the constructor. Sometimes, the constructor
|
654
|
+
# does not have a height or width, since the object will be resized based on parents
|
655
|
+
# size, as in splitpane
|
656
|
+
# Please use this only if embedding this object in another object/s that would wish
|
657
|
+
# to crop this. Otherwise, you could have many pads in your app.
|
658
|
+
# Sets @graphic which can be used in place of @form.window
|
659
|
+
#
|
660
|
+
# @return [buffer] returns pad created
|
661
|
+
# @since 0.1.3
|
662
|
+
# NOTE: 2010-01-12 11:14 there are some parent widgets that may want this w to have a larger top and left.
|
663
|
+
# Setting it later, means that the first repaint can be off.
|
664
|
+
|
665
|
+
def create_buffer()
|
666
|
+
$log.debug " #{self.class} CB called with #{@should_create_buffer} H: #{@height} W #{@width} "
|
667
|
+
if @should_create_buffer
|
668
|
+
@height or $log.warn " CB height is nil, setting to 1. This may not be what you want"
|
669
|
+
mheight = @height || 1 # some widgets don't have height XXX
|
670
|
+
mwidth = @width || 30 # some widgets don't have width as yet
|
671
|
+
mrow = @row || 0
|
672
|
+
mcol = @col || 0
|
673
|
+
layout = { :height => mheight, :width => mwidth, :top => mrow, :left => mcol }
|
674
|
+
$log.debug " cb .. #{@name} create_buffer #{mrow} #{mcol} #{mheight} #{mwidth}"
|
675
|
+
@screen_buffer = VER::Pad.create_with_layout(layout)
|
676
|
+
@is_double_buffered = true # will be checked prior to blitting
|
677
|
+
@buffer_modified = true # set this in repaint
|
678
|
+
@repaint_all = true # added 2010-01-08 19:02
|
679
|
+
else
|
680
|
+
## NOTE: if form has not been set, you could run into problems
|
681
|
+
## Typically a form MUST be set by now, unless you are buffering, in which
|
682
|
+
##+ case it should go in above block.
|
683
|
+
@screen_buffer = @form.window if @form
|
684
|
+
end
|
685
|
+
|
686
|
+
@graphic = @screen_buffer # use buffer for writing, not screen window
|
687
|
+
return @screen_buffer
|
688
|
+
end # create_buffer
|
689
|
+
|
690
|
+
##
|
691
|
+
# checks if buffer not created already, and figures
|
692
|
+
# out dimensions.
|
693
|
+
# Preferable to use this instead of directly using create_buffer.
|
694
|
+
#
|
695
|
+
def safe_create_buffer
|
696
|
+
if @screen_buffer == nil
|
697
|
+
if @height == nil
|
698
|
+
@height = @preferred_height || @min_height
|
699
|
+
end
|
700
|
+
if @width == nil
|
701
|
+
@width = @preferred_width || @min_width
|
702
|
+
end
|
703
|
+
create_buffer
|
704
|
+
end
|
705
|
+
return @screen_buffer
|
706
|
+
end
|
707
|
+
##
|
708
|
+
# Inform the system that the buffer has been modified
|
709
|
+
# and should be blitted over the screen or copied to parent.
|
710
|
+
def set_buffer_modified(tf=true)
|
711
|
+
@buffer_modified = tf
|
712
|
+
end
|
713
|
+
|
714
|
+
|
715
|
+
##
|
716
|
+
# copy the buffer to the screen, or given window/pad.
|
717
|
+
# Relevant only in double_buffered case since pad has to be written
|
718
|
+
# to screen. Should be called only by outer form, not by widgets as a widget
|
719
|
+
# could be inside another widget.
|
720
|
+
# Somewhere we need to clear screen if scrolling.???
|
721
|
+
# aka b2s
|
722
|
+
# @param [Window, #get_window, nil] screen to write to, if nil then write to phys screen
|
723
|
+
# @return 0 - copy success, -1 copy failure, 1 - did nothing, usually since buffer_modified false
|
724
|
+
|
725
|
+
def buffer_to_screen(screen=nil, pminrow=0, pmincol=0)
|
726
|
+
raise "deprecated b2s "
|
727
|
+
return 1 unless @is_double_buffered and @buffer_modified
|
728
|
+
# screen is nil when form calls this to write to physical screen
|
729
|
+
$log.debug " screen inside buffer_to_screen b2s :#{screen} "
|
730
|
+
$log.error "ERROR !I have moved away fomr this method. Your program is broken and will not be working"
|
731
|
+
## 2010-01-03 19:38 i think its wrong to put the pad onto the screen
|
732
|
+
##+ since wrefreshing the window will cause this to be overwriting
|
733
|
+
##+ so i put current window here.
|
734
|
+
if screen == nil
|
735
|
+
#$log.debug " XXX calling graphic.wrefresh 2010-01-03 12:27 (parent_buffer was nil) "
|
736
|
+
$log.debug " XXX 2010-01-03 20:47 now copying pad #{@graphic} onto form.window"
|
737
|
+
ret = @graphic.wrefresh
|
738
|
+
## 2010-01-03 20:45 rather than writing to phys screen, i write to forms window
|
739
|
+
##+ so later updates to that window do not overwrite this widget.
|
740
|
+
## We need to check this out with scrollpane and splitpane.
|
741
|
+
#ret = @graphic.copywin(@form.window.get_window, 0, 0, @row, @col, @row+@height-1, @col+@width-1,0)
|
742
|
+
else
|
743
|
+
# screen is passed when a parent object calls this to copy child buffer to itself
|
744
|
+
@graphic.set_backing_window(screen)
|
745
|
+
$log.debug " #{@name} #{@graphic} calling copy pad to win COPY"
|
746
|
+
ret = @graphic.copy_pad_to_win
|
747
|
+
end
|
748
|
+
@buffer_modified = false
|
749
|
+
return ret
|
750
|
+
end # buffer_to_screen
|
751
|
+
##
|
752
|
+
# returns screen_buffer or nil
|
753
|
+
#
|
754
|
+
# @return [screen_buffer, nil] screen_buffer earlier created
|
755
|
+
# @since 0.1.3
|
756
|
+
|
757
|
+
def get_buffer()
|
758
|
+
@screen_buffer
|
759
|
+
end # get_buffer
|
760
|
+
|
761
|
+
##
|
762
|
+
# destroys screen_buffer if present
|
763
|
+
#
|
764
|
+
# @return
|
765
|
+
# @since 0.1.3
|
766
|
+
|
767
|
+
def destroy_buffer()
|
768
|
+
if @screen_buffer != nil
|
769
|
+
@screen_buffer.destroy # ???
|
770
|
+
end
|
771
|
+
end # destroy_buffer
|
772
|
+
|
773
|
+
##
|
774
|
+
# Does the widget buffer its output in a pad
|
775
|
+
#
|
776
|
+
# @return [true, false] comment
|
777
|
+
|
778
|
+
def is_double_buffered?()
|
779
|
+
@is_double_buffered
|
780
|
+
end # is_double_buffered
|
781
|
+
|
782
|
+
##
|
783
|
+
# getter and setter for width - 2009-10-29 22:45
|
784
|
+
# Using dsl_property style
|
785
|
+
#
|
786
|
+
# @param [val, nil] value to set
|
787
|
+
# @return [val] earlier value if nil param
|
788
|
+
# @since 0.1.3
|
789
|
+
#
|
790
|
+
def width(*val)
|
791
|
+
#$log.debug " inside XXX width() #{val[0]}"
|
792
|
+
if val.empty?
|
793
|
+
return @width
|
794
|
+
else
|
795
|
+
#$log.debug " inside XXX width()"
|
796
|
+
oldvalue = @width || 0 # is this default okay, else later nil cries
|
797
|
+
@width = val.size == 1 ? val[0] : val
|
798
|
+
newvalue = @width
|
799
|
+
@config["width"]=@width
|
800
|
+
if oldvalue != newvalue
|
801
|
+
fire_property_change("width", oldvalue, newvalue)
|
802
|
+
repaint_all(true) # added 2010-01-08 18:51 so widgets can redraw everything.
|
803
|
+
end
|
804
|
+
if is_double_buffered? and newvalue != oldvalue
|
805
|
+
$log.debug " #{@name} w calling resize of screen buffer with #{newvalue}. WARNING: does not change buffering_params"
|
806
|
+
@screen_buffer.resize(0, newvalue)
|
807
|
+
end
|
808
|
+
end
|
809
|
+
end
|
810
|
+
def width=val
|
811
|
+
width(val)
|
812
|
+
end
|
813
|
+
##
|
814
|
+
# getter and setter for height - 2009-10-30 12:25
|
815
|
+
# Using dsl_property style
|
816
|
+
# SO WE've finally succumbed and added height to widget
|
817
|
+
# @param [val, nil] height to set
|
818
|
+
# @return [val] earlier height if nil param
|
819
|
+
# @since 0.1.3
|
820
|
+
#
|
821
|
+
def height(*val)
|
822
|
+
#$log.debug " inside XXX height() #{val[0]}"
|
823
|
+
if val.empty?
|
824
|
+
return @height
|
825
|
+
else
|
826
|
+
#$log.debug " inside #{@name} height()"
|
827
|
+
oldvalue = @height || 0 # is this default okay, else later nil cries
|
828
|
+
@height = val.size == 1 ? val[0] : val
|
829
|
+
newvalue = @height
|
830
|
+
@config["height"]=@height
|
831
|
+
if oldvalue != newvalue
|
832
|
+
fire_property_change("height", oldvalue, newvalue)
|
833
|
+
$log.debug " widget #{@name} setting repaint_all to true"
|
834
|
+
@repaint_all=true
|
835
|
+
end
|
836
|
+
# XXX this troubles me a lot. gets fired more than we would like
|
837
|
+
# XXX When both h and w change then happens 2 times.
|
838
|
+
if is_double_buffered? and newvalue != oldvalue
|
839
|
+
$log.debug " #{@name} h calling resize of screen buffer with #{newvalue}"
|
840
|
+
@screen_buffer.resize(newvalue, 0)
|
841
|
+
end
|
842
|
+
end
|
843
|
+
end
|
844
|
+
def height=val
|
845
|
+
height(val)
|
846
|
+
end
|
847
|
+
# to give simple access to other components, (eg, parent) to tell a comp to either
|
848
|
+
# paint its data, or to paint all - borders, headers, footers due to a big change (ht/width)
|
849
|
+
def repaint_required(tf=true)
|
850
|
+
@repaint_required = tf
|
851
|
+
end
|
852
|
+
def repaint_all(tf=true)
|
853
|
+
@repaint_all = tf
|
854
|
+
@repaint_required = tf
|
855
|
+
end
|
856
|
+
|
857
|
+
##
|
858
|
+
# When an enclosing component creates a pad (buffer) and the child component
|
859
|
+
#+ should write onto the same pad, then the enclosing component should override
|
860
|
+
#+ the default graphic of child. This applies mainly to editor components in
|
861
|
+
#+ listboxes and tables.
|
862
|
+
# @param graphic graphic object to use for writing contents
|
863
|
+
# @see prepare_editor in rlistbox.
|
864
|
+
# added 2010-01-05 15:25
|
865
|
+
def override_graphic gr
|
866
|
+
@graphic = gr
|
867
|
+
end
|
868
|
+
|
869
|
+
## passing a cursor up and adding col and row offsets
|
870
|
+
## Added 2010-01-13 13:27 I am checking this out.
|
871
|
+
## I would rather pass the value down and store it than do this recursive call
|
872
|
+
##+ for each cursor display
|
873
|
+
# @see Form#setrowcol
|
874
|
+
def setformrowcol r, c
|
875
|
+
@form.row = r unless r.nil?
|
876
|
+
@form.col = c unless c.nil?
|
877
|
+
# this is stupid, going through this route i was losing windows top and left
|
878
|
+
# And this could get repeated if there are mult objects.
|
879
|
+
if !@parent_component.nil? and @parent_component != self
|
880
|
+
r+= @parent_component.form.window.top unless r.nil?
|
881
|
+
c+= @parent_component.form.window.left unless c.nil?
|
882
|
+
$log.debug " (#{@name}) calling parents setformrowcol #{r}, #{c} pa: #{@parent_component.name} self: #{name}, #{self.class}, poff #{@parent_component.row_offset}, #{@parent_component.col_offset}, top:#{@form.window.left} left:#{@form.window.left} "
|
883
|
+
@parent_component.setformrowcol r, c
|
884
|
+
else
|
885
|
+
# no more parents, now set form
|
886
|
+
$log.debug " name NO MORE parents setting #{r}, #{c} in #{@form} "
|
887
|
+
@form.setrowcol r, c
|
888
|
+
end
|
889
|
+
end
|
890
|
+
## widget: i am putting one extra level of indirection so i can switch here
|
891
|
+
# between form#setrowcol and setformrowcol, since i am not convinced either
|
892
|
+
# are giving the accurate result. i am not sure what the issue is.
|
893
|
+
def setrowcol r, c
|
894
|
+
# 2010-02-07 21:32 is this where i should add ext_offsets
|
895
|
+
#$log.debug " #{@name} w.setrowcol #{r} + #{@ext_row_offset}, #{c} + #{@ext_col_offset} "
|
896
|
+
# commented off 2010-02-15 18:22
|
897
|
+
#r += @ext_row_offset unless r.nil?
|
898
|
+
#c += @ext_col_offset unless c.nil?
|
899
|
+
if @form
|
900
|
+
@form.setrowcol r, c
|
901
|
+
else
|
902
|
+
@parent_component.setrowcol r, c
|
903
|
+
end
|
904
|
+
#setformrowcol r,c
|
905
|
+
end
|
906
|
+
|
907
|
+
# move from TextView
|
908
|
+
# parameters relating to buffering - new 2010-02-12 12:09 RFED16
|
909
|
+
# I am merging so i can call multiple times
|
910
|
+
# WARNING NOTE : this does not set Pad's top and left since Pad may not be created yet, or at all
|
911
|
+
def set_buffering params
|
912
|
+
@buffer_params ||= {}
|
913
|
+
#@should_create_buffer = params[:should_create_buffer] || true
|
914
|
+
@target_window ||= params[:target_window]
|
915
|
+
# trying out, 2010-02-12 19:40 sometimes no form even with parent.
|
916
|
+
@form = params[:form] unless @form
|
917
|
+
## XXX trying this out.
|
918
|
+
# what if container does not ask child to buffer, as in splitpane
|
919
|
+
# then graphic could be nil
|
920
|
+
if @graphic.nil? # and should_create_buffer not set or false XXX
|
921
|
+
@graphic = @target_window
|
922
|
+
end
|
923
|
+
$log.debug " set_buffering #{@name} got target window #{@target_window}, #{@graphic} - THIS DOES NOT UPDATE PAD ... sr:#{params[:screen_top]} sc:#{params[:screen_left]} top:#{params[:top]} left:#{params[:left]} bot:#{params[:bottom]} rt:#{params[:right]} "
|
924
|
+
# @top = params[:top]
|
925
|
+
# @left = params[:left]
|
926
|
+
# @bottom = params[:bottom]
|
927
|
+
# @right = params[:right]
|
928
|
+
# offsets ?
|
929
|
+
# warning, this does not touch @top and left of Pad, often pad will bot yet be created
|
930
|
+
@buffer_params.merge!(params)
|
931
|
+
if !@screen_buffer.nil?
|
932
|
+
# update Pad since some folks take from there such as print_border
|
933
|
+
@screen_buffer.top = params[:screen_top] if !params[:screen_top].nil?
|
934
|
+
@screen_buffer.left = params[:screen_left] if !params[:screen_left].nil?
|
935
|
+
end
|
936
|
+
end
|
937
|
+
|
938
|
+
# copy buffer onto window
|
939
|
+
# RFED16 added 2010-02-12 14:42 0 simpler buffer management
|
940
|
+
def buffer_to_window
|
941
|
+
if @is_double_buffered and @buffer_modified
|
942
|
+
raise " #{@name} @buffer_params not passed. Use set_buffering()" unless @buffer_params
|
943
|
+
# we are notchecking for TV's width exceedingg, could get -1 if TV exceeds parent/
|
944
|
+
$log.debug "RFED16 paint #{@name} calling b2s #{@graphic} "
|
945
|
+
# TODO need to call set_screen_row_col (top, left), set_pad_top_left (pminrow, pmaxrow), set_screen_max_row_col
|
946
|
+
if false
|
947
|
+
# boh these print the pad behind 0,0, later scroll etc cover it and show bars.
|
948
|
+
# adding window was giving error
|
949
|
+
ret = buffer_to_screen #@target_window.get_window
|
950
|
+
#ret = @graphic.wrefresh
|
951
|
+
else
|
952
|
+
# ext gives me parents offset. often the row would be zero, so we still need one extra
|
953
|
+
r1 = @ext_row_offset # XXX NO, i should use top and left
|
954
|
+
c1 = @ext_col_offset
|
955
|
+
r = @graphic.top # 2010-02-12 21:12 TRYING THIS.
|
956
|
+
c = @graphic.left
|
957
|
+
maxr = @buffer_params[:bottom]
|
958
|
+
maxc = @buffer_params[:right]
|
959
|
+
r = @buffer_params[:screen_top] || 0
|
960
|
+
c = @buffer_params[:screen_left] || 0
|
961
|
+
$log.debug " b2w #{r1} #{c1} , #{r} #{c} "
|
962
|
+
## sadly this is bypassing the method that does this stuff in Pad. We need to assimilate it back, so not so much work here
|
963
|
+
pminr = @graphic.pminrow
|
964
|
+
pminc = @graphic.pmincol
|
965
|
+
border_width = 0 # 2 #XXX 2010-02-15 23:40 2 to 0
|
966
|
+
$log.debug " #{@name} ret = @graphic.copywin(@target_window.get_window, #{pminr}, #{pminc}, #{r}, #{c}, #{r}+#{maxr} - #{border_width}, #{c} + #{maxc} - #{border_width} ,0)"
|
967
|
+
# this print the view at 0,0, byt covers the scrllare, bars not shown.
|
968
|
+
# this can crash if textview is smaller than container dimension
|
969
|
+
# can crash/give -1 when panning, giong beyond pad size XXX
|
970
|
+
ret = @graphic.copywin(@target_window.get_window, pminr, pminc, r, c, r+maxr-border_width, c+maxc-border_width,0)
|
971
|
+
if ret == -1
|
972
|
+
$log.debug " copywin #{@name} h #{@height} w #{@width} "
|
973
|
+
if @height <= maxr-border_width
|
974
|
+
$log.warn " h #{@height} is <= :bottom #{maxr} "
|
975
|
+
end
|
976
|
+
if @width <= maxc-border_width
|
977
|
+
$log.warn " h #{@width} is <= :right #{maxc} "
|
978
|
+
end
|
979
|
+
$log.warn "ERROR !!! copywin returns -1 check Target: #{@target_window}, #{@target_window.get_window} " if ret == -1
|
980
|
+
end
|
981
|
+
end
|
982
|
+
$log.debug " copywin ret --> #{ret} "
|
983
|
+
#
|
984
|
+
end
|
985
|
+
end
|
986
|
+
##
|
485
987
|
## ADD HERE WIDGET
|
486
988
|
end
|
487
989
|
|
@@ -506,6 +1008,19 @@ module RubyCurses
|
|
506
1008
|
attr_reader :by_name # hash containing widgets by name for retrieval
|
507
1009
|
attr_reader :menu_bar
|
508
1010
|
attr_accessor :navigation_policy # :CYCLICAL will cycle around. Needed to move to other tabs
|
1011
|
+
## i need some way to move the cursor by telling the main form what the coords are
|
1012
|
+
##+ perhaps this will work
|
1013
|
+
attr_accessor :parent_form # added 2009-12-28 23:01 BUFFERED - to bubble up row col changes
|
1014
|
+
# how many rows the component is panning embedded widget by
|
1015
|
+
attr_accessor :rows_panned # HACK added 2009-12-30 16:01 BUFFERED
|
1016
|
+
# how many cols the component is panning embedded widget by
|
1017
|
+
attr_accessor :cols_panned # HACK added 2009-12-30 16:01 BUFFERED
|
1018
|
+
## next 2 added since tabbedpanes offset needs to be accounted by form inside it.
|
1019
|
+
attr_accessor :add_cols # 2010-01-26 20:23 additional columns due to being placed in some container
|
1020
|
+
attr_accessor :add_rows # 2010-01-26 20:23 additional columns due to being placed in some container
|
1021
|
+
attr_accessor :name # for debugging 2010-02-02 20:12
|
1022
|
+
attr_accessor :ext_col_offset, :ext_row_offset # 2010-02-07 20:16 to get abs position for cursor
|
1023
|
+
# attr_accessor :allow_alt_digits # catch Alt-1-9 as digit_argument
|
509
1024
|
def initialize win, &block
|
510
1025
|
@window = win
|
511
1026
|
@widgets = []
|
@@ -513,12 +1028,26 @@ module RubyCurses
|
|
513
1028
|
@active_index = -1
|
514
1029
|
@padx = @pady = 0
|
515
1030
|
@row = @col = -1
|
1031
|
+
@ext_row_offset = @ext_col_offset = 0 # 2010-02-07 20:18
|
1032
|
+
@add_cols = @add_rows = 0 # 2010-01-26 20:28
|
516
1033
|
@handler = {}
|
517
1034
|
@modified = false
|
518
1035
|
@focusable = true
|
519
1036
|
@navigation_policy ||= :CYCLICAL
|
520
1037
|
instance_eval &block if block_given?
|
521
1038
|
@firsttime = true # internal, don't touch
|
1039
|
+
## I need some counter so a widget knows it has been panned and can send a correct
|
1040
|
+
##+ cursor coordinate to system.
|
1041
|
+
@rows_panned = @cols_panned = 0 # how many rows were panned, typically at a higher level
|
1042
|
+
@firsttime = true; # added on 2010-01-02 19:21 to prevent scrolling crash !
|
1043
|
+
@name ||= ""
|
1044
|
+
$kill_ring ||= [] # 2010-03-09 22:42 so textarea and others can copy and paste
|
1045
|
+
$kill_ring_pointer = 0 # needs to be incremented with each append, moved with yank-pop
|
1046
|
+
$append_next_kill = false
|
1047
|
+
$kill_last_pop_size = 0 # size of last pop which has to be cleared
|
1048
|
+
|
1049
|
+
#@allow_alt_digits = true ; # capture Alt-1-9 as digit_args. Set to false if you wish to map
|
1050
|
+
# Alt-1-9 to buttons of tabs
|
522
1051
|
end
|
523
1052
|
##
|
524
1053
|
# set this menubar as the form's menu bar.
|
@@ -549,9 +1078,21 @@ module RubyCurses
|
|
549
1078
|
@by_name[widget.name] = widget
|
550
1079
|
end
|
551
1080
|
|
1081
|
+
|
1082
|
+
$log.debug " #{self} adding a widget #{@widgets.length} .. #{widget} "
|
552
1083
|
@widgets << widget
|
1084
|
+
# add form offsets to widget's external offsets - 2010-02-07 20:22
|
1085
|
+
if widget.is_a? RubyCurses::Widget
|
1086
|
+
if @window # ext seems redundant
|
1087
|
+
widget.ext_col_offset += @window.left # just hope window aint undef!! XXX
|
1088
|
+
$log.debug " #{@name} add widget ( #{widget.name} ) ext_row #{widget.ext_row_offset} += #{@window.top} "
|
1089
|
+
widget.ext_row_offset += @window.top
|
1090
|
+
end
|
1091
|
+
end
|
553
1092
|
return @widgets.length-1
|
554
|
-
|
1093
|
+
end
|
1094
|
+
alias :add :add_widget
|
1095
|
+
|
555
1096
|
# remove a widget
|
556
1097
|
# added 2008-12-09 12:18
|
557
1098
|
def remove_widget widget
|
@@ -564,31 +1105,69 @@ module RubyCurses
|
|
564
1105
|
# form repaint
|
565
1106
|
# to be called at some interval, such as after each keypress.
|
566
1107
|
def repaint
|
1108
|
+
$log.debug " form repaint:#{self}, #{@name} , r #{@row} c #{@col} "
|
567
1109
|
@widgets.each do |f|
|
568
1110
|
next if f.visible == false # added 2008-12-09 12:17
|
569
1111
|
f.repaint
|
1112
|
+
# added 2009-10-29 20:11 for double buffered widgets
|
1113
|
+
# this should only happen if painting actually happened
|
1114
|
+
#$log.debug " #{self} form repaint parent_buffer (#{@parent_buffer}) if #{f.is_double_buffered?} : #{f.name} "
|
1115
|
+
pb = @parent_buffer #|| @window
|
1116
|
+
# is next line used 2010-02-05 00:04 its wiping off top in scrollpane in tabbedpane
|
1117
|
+
# RFED16 - the next line should never execute now, since no outer object is buffered
|
1118
|
+
#+ only those within containers are.
|
1119
|
+
# Drat - this line is happeing since components inside a TP are double_buffered
|
1120
|
+
#x f.buffer_to_screen(pb) if f.is_double_buffered?
|
570
1121
|
end
|
571
|
-
@window.clear_error
|
1122
|
+
@window.clear_error # suddenly throwing up on a small pad 2010-03-02 15:22 TPNEW
|
572
1123
|
@window.print_status_message $status_message unless $status_message.nil?
|
573
1124
|
@window.print_error_message $error_message unless $error_message.nil?
|
574
1125
|
$error_message = $status_message = nil
|
575
1126
|
# this can bomb if someone sets row. We need a better way!
|
576
|
-
if @row == -1
|
1127
|
+
if @row == -1 and @firsttime == true
|
577
1128
|
#set_field_cursor 0
|
578
|
-
|
1129
|
+
# this part caused an endless loop on 2010-01-02 19:20 when scrollpane scrolled up
|
1130
|
+
$log.debug "form repaint calling select field 0 SHOULD HAPPEN FIRST TIME ONLY"
|
579
1131
|
#select_field 0
|
580
1132
|
req_first_field
|
581
|
-
|
1133
|
+
@firsttime = false
|
582
1134
|
end
|
583
1135
|
setpos
|
584
|
-
|
1136
|
+
# XXX this creates a problem if window is a pad
|
1137
|
+
# although this does show cursor movement etc.
|
1138
|
+
### XXX@window.wrefresh
|
1139
|
+
if @window.window_type == :WINDOW
|
1140
|
+
$log.debug " formrepaint #{@name} calling window.wrefresh #{@window} "
|
1141
|
+
@window.wrefresh
|
1142
|
+
else
|
1143
|
+
# UGLY HACK TO MAKE TABBEDPANES WORK !!
|
1144
|
+
# If the form is based on a Pad, then it would come here to write the Pad onto the parent_buffer
|
1145
|
+
# However, I've obviated the need to handle anything here by adding a display_form after handle_key
|
1146
|
+
# in TP.
|
1147
|
+
#x if @parent_buffer!=nil
|
1148
|
+
#x $log.debug " formrep coming to set backing window part #{@window} , type:#{@window.window_type}, #{@parent_buffer}, #{@parent_buffer.window_type} "
|
1149
|
+
# XXX RFED19 do we need at all 2010-02-19 15:26
|
1150
|
+
# this is required so that each key stroke registers on tabbedpane
|
1151
|
+
# for this to work both have to be pads
|
1152
|
+
#x @window.set_backing_window(@parent_buffer)
|
1153
|
+
#x @window.copy_pad_to_win
|
1154
|
+
#x @window.wrefresh #since the pads are writing onto window directly, i don't think we need this
|
1155
|
+
#x $log.debug " DO I NEED TO DO SOMETHING HERE FOR TABBEDPANES now ? WARN ?? YES, else keystrokes won't be updated "
|
1156
|
+
#x end
|
1157
|
+
end
|
585
1158
|
end
|
586
1159
|
##
|
587
1160
|
# move cursor to where the fields row and col are
|
588
1161
|
# private
|
589
1162
|
def setpos r=@row, c=@col
|
590
|
-
|
591
|
-
|
1163
|
+
# next 2 lines added, only do cursor if current field doesn't manage it.
|
1164
|
+
#curr = get_current_field
|
1165
|
+
#return if curr.manages_cursor
|
1166
|
+
$log.debug "setpos : (#{self}) #{r} #{c}"
|
1167
|
+
## adding just in case things are going out of bounds of a parent and no cursor to be shown
|
1168
|
+
return if r.nil? or c.nil? # added 2009-12-29 23:28 BUFFERED
|
1169
|
+
return if r<0 or c<0 # added 2010-01-02 18:49 stack too deep coming if goes above screen
|
1170
|
+
@window.wmove r,c
|
592
1171
|
end
|
593
1172
|
def get_current_field
|
594
1173
|
select_next_field if @active_index == -1
|
@@ -628,17 +1207,23 @@ module RubyCurses
|
|
628
1207
|
f.on_enter if f.respond_to? :on_enter
|
629
1208
|
fire_handler :ENTER, f
|
630
1209
|
end
|
1210
|
+
## is a field focusable
|
1211
|
+
# Added a method here, so forms can extend this to avoid focussing on off-screen components
|
1212
|
+
def focusable?(f)
|
1213
|
+
return f.focusable
|
1214
|
+
end
|
631
1215
|
##
|
632
1216
|
# puts focus on the given field/widget index
|
633
1217
|
# XXX if called externally will not run a on_leave of previous field
|
634
1218
|
def select_field ix0
|
635
|
-
return if @widgets.nil? or @widgets.empty? or !@widgets[ix0].focusable
|
636
|
-
|
1219
|
+
#return if @widgets.nil? or @widgets.empty? or !@widgets[ix0].focusable
|
1220
|
+
return if @widgets.nil? or @widgets.empty? or !focusable?(@widgets[ix0])
|
1221
|
+
#$log.debug "insdie select field : #{ix0} ai #{@active_index}"
|
637
1222
|
f = @widgets[ix0]
|
638
|
-
if f
|
1223
|
+
if focusable?(f)
|
639
1224
|
@active_index = ix0
|
640
1225
|
@row, @col = f.rowcol
|
641
|
-
|
1226
|
+
#$log.debug " WMOVE insdie sele nxt field : ROW #{@row} COL #{@col} "
|
642
1227
|
@window.wmove @row, @col
|
643
1228
|
on_enter f
|
644
1229
|
f.curpos = 0
|
@@ -669,7 +1254,7 @@ module RubyCurses
|
|
669
1254
|
# in which case returns :NO_NEXT_FIELD.
|
670
1255
|
def select_next_field
|
671
1256
|
return if @widgets.nil? or @widgets.empty?
|
672
|
-
|
1257
|
+
$log.debug "insdie sele nxt field : #{@active_index} WL:#{@widgets.length}"
|
673
1258
|
if @active_index.nil?
|
674
1259
|
@active_index = -1
|
675
1260
|
else
|
@@ -687,7 +1272,8 @@ module RubyCurses
|
|
687
1272
|
index = @active_index + 1
|
688
1273
|
index.upto(@widgets.length-1) do |i|
|
689
1274
|
f = @widgets[i]
|
690
|
-
|
1275
|
+
$log.debug "insdie sele nxt field : i #{i} #{index} WL:#{@widgets.length}, field #{f}"
|
1276
|
+
if focusable?(f)
|
691
1277
|
select_field i
|
692
1278
|
return
|
693
1279
|
end
|
@@ -701,12 +1287,13 @@ module RubyCurses
|
|
701
1287
|
#select_next_field
|
702
1288
|
0.upto(index-1) do |i|
|
703
1289
|
f = @widgets[i]
|
704
|
-
if f
|
1290
|
+
if focusable?(f)
|
705
1291
|
select_field i
|
706
1292
|
return
|
707
1293
|
end
|
708
1294
|
end
|
709
1295
|
end
|
1296
|
+
$log.debug "insdie sele nxt field : NO NEXT #{@active_index} WL:#{@widgets.length}"
|
710
1297
|
return :NO_NEXT_FIELD
|
711
1298
|
end
|
712
1299
|
##
|
@@ -732,7 +1319,7 @@ module RubyCurses
|
|
732
1319
|
index = @active_index - 1
|
733
1320
|
(index).downto(0) do |i|
|
734
1321
|
f = @widgets[i]
|
735
|
-
if f
|
1322
|
+
if focusable?(f)
|
736
1323
|
select_field i
|
737
1324
|
return
|
738
1325
|
end
|
@@ -746,7 +1333,7 @@ module RubyCurses
|
|
746
1333
|
total = @widgets.length-1
|
747
1334
|
total.downto(index-1) do |i|
|
748
1335
|
f = @widgets[i]
|
749
|
-
if f
|
1336
|
+
if focusable?(f)
|
750
1337
|
select_field i
|
751
1338
|
return
|
752
1339
|
end
|
@@ -757,61 +1344,231 @@ module RubyCurses
|
|
757
1344
|
alias :req_next_field :select_next_field
|
758
1345
|
alias :req_prev_field :select_prev_field
|
759
1346
|
##
|
760
|
-
# move cursor by num columns
|
1347
|
+
# move cursor by num columns. Form
|
761
1348
|
def addcol num
|
762
1349
|
return if @col.nil? or @col == -1
|
763
1350
|
@col += num
|
764
1351
|
@window.wmove @row, @col
|
1352
|
+
## 2010-01-30 23:45 exchange calling parent with calling this forms setrow
|
1353
|
+
# since in tabbedpane with table i am not gietting this forms offset.
|
1354
|
+
setrowcol nil, col
|
1355
|
+
# added on 2010-01-05 22:26 so component widgets like scrollpane can get the cursor
|
1356
|
+
#if !@parent_form.nil? and @parent_form != self #@form
|
1357
|
+
#$log.debug " #{@name} addcol calling parents setrowcol #{row}, #{col}: #{@parent_form} "
|
1358
|
+
#@parent_form.setrowcol nil, col
|
1359
|
+
#end
|
765
1360
|
end
|
766
1361
|
##
|
767
1362
|
# move cursor by given rows and columns, can be negative.
|
1363
|
+
# 2010-01-30 23:47 FIXME, if this is called we should call setrowcol like in addcol
|
768
1364
|
def addrowcol row,col
|
769
|
-
return if @col.nil? or @col == -1
|
1365
|
+
return if @col.nil? or @col == -1 # contradicts comment on top
|
770
1366
|
return if @row.nil? or @row == -1
|
771
1367
|
@col += col
|
772
1368
|
@row += row
|
773
1369
|
@window.wmove @row, @col
|
1370
|
+
# added on 2010-01-05 22:26 so component widgets like scrollpane can get the cursor
|
1371
|
+
if !@parent_form.nil? and @parent_form != @form
|
1372
|
+
$log.debug " #{@name} addrowcol calling parents setrowcol #{row}, #{col} "
|
1373
|
+
@parent_form.setrowcol row, col
|
1374
|
+
end
|
1375
|
+
end
|
1376
|
+
|
1377
|
+
## added 2009-12-29 15:46 BUFFERED
|
1378
|
+
# Set forms row and col, so that the cursor can be displayed at that point.
|
1379
|
+
# Widgets should call this rather than touch row and col
|
1380
|
+
# directly. This should percolate the row and col
|
1381
|
+
# upwards to parent forms, after comparing to prevent
|
1382
|
+
# infinite recursion.
|
1383
|
+
# This is being done for embedded objects so that the cursor
|
1384
|
+
# can be maintained correctly.
|
1385
|
+
def OLDsetrowcol r, c
|
1386
|
+
@row = r unless r.nil?
|
1387
|
+
@col = c unless c.nil?
|
1388
|
+
r += @add_rows unless r.nil? # 2010-01-26 20:31
|
1389
|
+
c += @add_cols unless c.nil? # 2010-01-26 20:31
|
1390
|
+
$log.debug " addcols #{@add_cols} addrow #{@add_rows} : #{self} "
|
1391
|
+
if !@parent_form.nil? and @parent_form != self
|
1392
|
+
$log.debug " (#{@name}) calling parents setrowcol #{r}, #{c} : pare: #{@parent_form}; self: #{self}, #{self.class} "
|
1393
|
+
r += @parent_form.window.top unless r.nil?
|
1394
|
+
c += @parent_form.window.left unless c.nil?
|
1395
|
+
@parent_form.setrowcol r, c
|
1396
|
+
end
|
1397
|
+
end
|
1398
|
+
## Form
|
1399
|
+
# New attempt at setting cursor using absolute coordinates
|
1400
|
+
# Also, trying NOT to go up. let this pad or window print cursor.
|
1401
|
+
def setrowcol r, c
|
1402
|
+
@row = r unless r.nil?
|
1403
|
+
@col = c unless c.nil?
|
1404
|
+
r += @add_rows unless r.nil? # 2010-01-26 20:31
|
1405
|
+
c += @add_cols unless c.nil? # 2010-01-26 20:31
|
1406
|
+
$log.debug " addcols #{@add_cols} addrow #{@add_rows} : #{self} "
|
1407
|
+
if !@parent_form.nil? and @parent_form != self
|
1408
|
+
$log.debug " (#{@name}) calling parents setrowcol #{r}, #{c} : pare: #{@parent_form}; self: #{self}, #{self.class} "
|
1409
|
+
#r += @parent_form.window.top unless r.nil?
|
1410
|
+
#c += @parent_form.window.left unless c.nil?
|
1411
|
+
@parent_form.setrowcol r, c
|
1412
|
+
end
|
774
1413
|
end
|
775
1414
|
##
|
776
1415
|
# bind an action to a key, required if you create a button which has a hotkey
|
777
1416
|
# or a field to be focussed on a key, or any other user defined action based on key
|
778
1417
|
# e.g. bind_key ?\C-x, object, block
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
1418
|
+
# 1.9 if string passed then getbyte so user does not need to change much and
|
1419
|
+
# less chance of error 2009-10-04 16:08
|
1420
|
+
def OLDbind_key keycode, *args, &blk
|
1421
|
+
@key_handler ||= {}
|
1422
|
+
case keycode
|
1423
|
+
when String
|
1424
|
+
$log.debug "FORM String called bind_key BIND #{keycode} #{keycode_tos(keycode)} "
|
1425
|
+
keycode = keycode.getbyte(0) #if keycode.class==String ## 1.9 2009-10-05 19:40
|
1426
|
+
@key_handler[keycode] = blk
|
1427
|
+
when Array
|
1428
|
+
# for starters lets try with 2 keys only
|
1429
|
+
a0 = keycode[0]
|
1430
|
+
a0 = keycode[0].getbyte(0) if keycode[0].class == String
|
1431
|
+
a1 = keycode[1]
|
1432
|
+
a1 = keycode[1].getbyte(0) if keycode[1].class == String
|
1433
|
+
@key_handler[a0] ||= OrderedHash.new
|
1434
|
+
@key_handler[a0][a1] = blk
|
1435
|
+
else
|
1436
|
+
@key_handler[keycode] = blk
|
1437
|
+
end
|
1438
|
+
@key_args ||= {}
|
1439
|
+
@key_args[keycode] = args
|
785
1440
|
end
|
786
1441
|
|
787
1442
|
# e.g. process_key ch, self
|
788
1443
|
# returns UNHANDLED if no block for it
|
789
1444
|
# after form handles basic keys, it gives unhandled key to current field, if current field returns
|
790
1445
|
# unhandled, then it checks this map.
|
1446
|
+
# Please update widget with any changes here. TODO: match regexes as in mapper
|
791
1447
|
def process_key keycode, object
|
792
|
-
return
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
1448
|
+
return _process_key keycode, object, @window
|
1449
|
+
end
|
1450
|
+
#return :UNHANDLED if @key_handler.nil?
|
1451
|
+
#blk = @key_handler[keycode]
|
1452
|
+
#return :UNHANDLED if blk.nil?
|
1453
|
+
#if blk.is_a? OrderedHash
|
1454
|
+
## Please note that this does not wait too long, you have to press next key fast
|
1455
|
+
## since i have set halfdelay in ncurses.rb, test this with getchar to get more keys TODO
|
1456
|
+
#ch = @window.getch
|
1457
|
+
#if ch < 0 || ch > 255
|
1458
|
+
##next
|
1459
|
+
#return nil
|
1460
|
+
#end
|
1461
|
+
#$log.debug " process_key: got #{keycode} , #{ch} "
|
1462
|
+
#yn = ch.chr
|
1463
|
+
#blk1 = blk[ch]
|
1464
|
+
#return nil if blk1.nil?
|
1465
|
+
#$log.debug " process_key: found block for #{keycode} , #{ch} "
|
1466
|
+
#blk = blk1
|
1467
|
+
#end
|
1468
|
+
#$log.debug "called process_key #{object}, kc: #{keycode}, args #{@key_args[keycode]}"
|
1469
|
+
## return blk.call object, *@key_args[keycode]
|
1470
|
+
#blk.call object, *@key_args[keycode]
|
1471
|
+
#0
|
1472
|
+
#end
|
1473
|
+
# Defines how user can give numeric args to a command even in edit mode
|
1474
|
+
# User either presses universal_argument (C-u) which generates a series of 4 16 64.
|
1475
|
+
# Or he presses C-u and then types some numbers. Followed by the action.
|
1476
|
+
# @returns [0, :UNHANDLED] :UNHANDLED implies that last keystroke is still to evaluated
|
1477
|
+
# by system. ) implies only numeric args were obtained. This method updates $multiplier
|
1478
|
+
def universal_argument
|
1479
|
+
$multiplier = ( ($multiplier.nil? || $multiplier == 0) ? 4 : $multiplier *= 4)
|
1480
|
+
$log.debug " inside UNIV MULT0: #{$multiplier} "
|
1481
|
+
# See if user enters numerics. If so discard existing varaible and take only
|
1482
|
+
#+ entered values
|
1483
|
+
_m = 0
|
1484
|
+
while true
|
1485
|
+
ch = @window.getchar()
|
1486
|
+
case ch
|
1487
|
+
when -1
|
1488
|
+
next
|
1489
|
+
when ?0.getbyte(0)..?9.getbyte(0)
|
1490
|
+
_m *= 10 ; _m += (ch-48)
|
1491
|
+
$multiplier = _m
|
1492
|
+
$log.debug " inside UNIV MULT #{$multiplier} "
|
1493
|
+
when ?\C-u.getbyte(0)
|
1494
|
+
if _m == 0
|
1495
|
+
# user is incrementally hitting C-u
|
1496
|
+
$multiplier *= 4
|
1497
|
+
else
|
1498
|
+
# user is terminating some numbers so he can enter a numeric command next
|
1499
|
+
return 0
|
1500
|
+
end
|
1501
|
+
else
|
1502
|
+
$log.debug " inside UNIV MULT else got #{ch} "
|
1503
|
+
# here is some other key that is the function key to be repeated. we must honor this
|
1504
|
+
# and ensure it goes to the right widget
|
1505
|
+
return ch
|
1506
|
+
#return :UNHANDLED
|
1507
|
+
end
|
1508
|
+
end
|
1509
|
+
return 0
|
1510
|
+
end
|
1511
|
+
def digit_argument ch
|
1512
|
+
$multiplier = ch - ?\M-0.getbyte(0)
|
1513
|
+
$log.debug " inside UNIV MULT 0 #{$multiplier} "
|
1514
|
+
# See if user enters numerics. If so discard existing varaible and take only
|
1515
|
+
#+ entered values
|
1516
|
+
_m = $multiplier
|
1517
|
+
while true
|
1518
|
+
ch = @window.getchar()
|
1519
|
+
case ch
|
1520
|
+
when -1
|
1521
|
+
next
|
1522
|
+
when ?0.getbyte(0)..?9.getbyte(0)
|
1523
|
+
_m *= 10 ; _m += (ch-48)
|
1524
|
+
$multiplier = _m
|
1525
|
+
$log.debug " inside UNIV MULT 1 #{$multiplier} "
|
1526
|
+
when ?\M-0.getbyte(0)..?\M-9.getbyte(0)
|
1527
|
+
_m *= 10 ; _m += (ch-?\M-0.getbyte(0))
|
1528
|
+
$multiplier = _m
|
1529
|
+
$log.debug " inside UNIV MULT 2 #{$multiplier} "
|
1530
|
+
else
|
1531
|
+
$log.debug " inside UNIV MULT else got #{ch} "
|
1532
|
+
# here is some other key that is the function key to be repeated. we must honor this
|
1533
|
+
# and ensure it goes to the right widget
|
1534
|
+
return ch
|
1535
|
+
#return :UNHANDLED
|
1536
|
+
end
|
1537
|
+
end
|
1538
|
+
return 0
|
798
1539
|
end
|
799
1540
|
## forms handle keys
|
800
1541
|
# mainly traps tab and backtab to navigate between widgets.
|
801
1542
|
# I know some widgets will want to use tab, e.g edit boxes for entering a tab
|
802
1543
|
# or for completion.
|
803
1544
|
def handle_key(ch)
|
1545
|
+
if ch == ?\C-u.getbyte(0)
|
1546
|
+
ret = universal_argument
|
1547
|
+
$log.debug " FORM set MULT to #{$multiplier}, ret = #{ret} "
|
1548
|
+
return 0 if ret == 0
|
1549
|
+
ch = ret # unhandled char
|
1550
|
+
elsif ch >= ?\M-1.getbyte(0) && ch <= ?\M-9.getbyte(0)
|
1551
|
+
if $catch_alt_digits
|
1552
|
+
ret = digit_argument ch
|
1553
|
+
$log.debug " FORM set MULT DA to #{$multiplier}, ret = #{ret} "
|
1554
|
+
return 0 if ret == 0 # don't see this happening
|
1555
|
+
ch = ret # unhandled char
|
1556
|
+
end
|
1557
|
+
end
|
1558
|
+
|
804
1559
|
case ch
|
805
1560
|
when -1
|
806
1561
|
return
|
807
1562
|
else
|
1563
|
+
keycode = keycode_tos(ch)
|
1564
|
+
$log.debug " form HK #{ch} #{self}, #{@name}, #{keycode} "
|
808
1565
|
field = get_current_field
|
809
1566
|
handled = :UNHANDLED
|
810
1567
|
handled = field.handle_key ch unless field.nil? # no field focussable
|
811
1568
|
# some widgets like textarea and list handle up and down
|
812
1569
|
if handled == :UNHANDLED or handled == -1 or field.nil?
|
813
1570
|
case ch
|
814
|
-
when 9, ?\M-\C-i # tab and M-tab in case widget eats tab (such as Table)
|
1571
|
+
when 9, ?\M-\C-i.getbyte(0) # tab and M-tab in case widget eats tab (such as Table)
|
815
1572
|
ret = select_next_field
|
816
1573
|
return ret if ret == :NO_NEXT_FIELD
|
817
1574
|
# alt-shift-tab or backtab (in case Table eats backtab)
|
@@ -822,14 +1579,31 @@ module RubyCurses
|
|
822
1579
|
select_prev_field
|
823
1580
|
when KEY_DOWN
|
824
1581
|
select_next_field
|
1582
|
+
#when ?\M-L.getbyte(0)
|
1583
|
+
### trying out these for fuun and testing splitpane 2010-01-10 20:32
|
1584
|
+
#$log.debug " field #{field.name} was #{field.width} "
|
1585
|
+
#field.width += 1
|
1586
|
+
#$log.debug " field #{field.name} now #{field.width} "
|
1587
|
+
#field.repaint_all
|
1588
|
+
#when ?\M-H.getbyte(0), ?\M-<.getbyte(0)
|
1589
|
+
#field.width -= 1
|
1590
|
+
#$log.debug " field #{field.name} now #{field.width} "
|
1591
|
+
#field.repaint_all
|
1592
|
+
#when ?\M-J.getbyte(0)
|
1593
|
+
#field.height += 1
|
1594
|
+
#when ?\M-K.getbyte(0)
|
1595
|
+
#field.height -= 1
|
825
1596
|
else
|
826
1597
|
ret = process_key ch, self
|
1598
|
+
$log.debug " process_key #{ch} got ret #{ret} in #{self} "
|
827
1599
|
return :UNHANDLED if ret == :UNHANDLED
|
828
1600
|
end
|
829
1601
|
end
|
830
1602
|
end
|
831
|
-
$log.debug " form before repaint"
|
1603
|
+
$log.debug " form before repaint #{self} , #{@name}, ret #{ret}"
|
832
1604
|
repaint
|
1605
|
+
#return handled # TRYNG 2010-03-01 23:30 since TP returns NO_NEXT_FIELD sometimes
|
1606
|
+
#$multiplier = 0
|
833
1607
|
end
|
834
1608
|
##
|
835
1609
|
# test program to dump data onto log
|
@@ -854,9 +1628,36 @@ module RubyCurses
|
|
854
1628
|
end
|
855
1629
|
$log.debug " END DUMPING DATA "
|
856
1630
|
end
|
1631
|
+
##
|
1632
|
+
# trying out for splitpane and others who have a sub-form
|
1633
|
+
def set_parent_buffer b
|
1634
|
+
@parent_buffer = b
|
1635
|
+
end
|
1636
|
+
# 2010-02-07 14:50 to aid in debugging and comparing log files.
|
1637
|
+
def to_s; @name || self; end
|
857
1638
|
|
858
1639
|
## ADD HERE FORM
|
859
1640
|
end
|
1641
|
+
## Created and sent to all listeners whenever a property is changed
|
1642
|
+
# @see fire_property_change
|
1643
|
+
# @see fire_handler
|
1644
|
+
# @since 1.0.5 added 2010-02-25 23:06
|
1645
|
+
class PropertyChangeEvent
|
1646
|
+
attr_accessor :source, :property_name, :oldvalue, :newvalue
|
1647
|
+
def initialize source, property_name, oldvalue, newvalue
|
1648
|
+
set source, property_name, oldvalue, newvalue
|
1649
|
+
end
|
1650
|
+
def set source, property_name, oldvalue, newvalue
|
1651
|
+
@source, @property_name, @oldvalue, @newvalue =
|
1652
|
+
source, property_name, oldvalue, newvalue
|
1653
|
+
end
|
1654
|
+
def to_s
|
1655
|
+
"PROPERTY_CHANGE name: #{property_name}, oldval: #{@oldvalue}, newvalue: #{@newvalue}, source: #{@source}"
|
1656
|
+
end
|
1657
|
+
def inspect
|
1658
|
+
to_s
|
1659
|
+
end
|
1660
|
+
end
|
860
1661
|
|
861
1662
|
##
|
862
1663
|
# Text edit field
|
@@ -887,6 +1688,7 @@ module RubyCurses
|
|
887
1688
|
#attr_reader :curpos # cursor position in buffer current, in WIDGET
|
888
1689
|
attr_accessor :datatype # crrently set during set_buffer
|
889
1690
|
attr_reader :original_value # value on entering field
|
1691
|
+
attr_accessor :overwrite_mode # true or false INSERT OVERWRITE MODE
|
890
1692
|
|
891
1693
|
def initialize form, config={}, &block
|
892
1694
|
@form = form
|
@@ -931,11 +1733,17 @@ module RubyCurses
|
|
931
1733
|
end
|
932
1734
|
end
|
933
1735
|
def putch char
|
934
|
-
return -1 if !@editable
|
1736
|
+
return -1 if !@editable
|
1737
|
+
return -1 if !@overwrite_mode and @buffer.length >= @maxlen
|
935
1738
|
if @chars_allowed != nil
|
936
1739
|
return if char.match(@chars_allowed).nil?
|
937
1740
|
end
|
938
|
-
|
1741
|
+
# added insert or overwrite mode 2010-03-17 20:11
|
1742
|
+
if @overwrite_mode
|
1743
|
+
@buffer[@curpos] = char
|
1744
|
+
else
|
1745
|
+
@buffer.insert(@curpos, char)
|
1746
|
+
end
|
939
1747
|
@curpos += 1 if @curpos < @maxlen
|
940
1748
|
@modified = true
|
941
1749
|
$log.debug " FIELD FIRING CHANGE: #{char} at new #{@curpos}: bl:#{@buffer.length} buff:[#{@buffer}]"
|
@@ -997,8 +1805,13 @@ module RubyCurses
|
|
997
1805
|
label.col @col-(label.name.length+1) if label.col == -1
|
998
1806
|
label.label_for(self)
|
999
1807
|
end
|
1808
|
+
|
1809
|
+
## Note that some older widgets like Field repaint every time the form.repaint
|
1810
|
+
##+ is called, whether updated or not. I can't remember why this is, but
|
1811
|
+
##+ currently I've not implemented events with these widgets. 2010-01-03 15:00
|
1812
|
+
|
1000
1813
|
def repaint
|
1001
|
-
|
1814
|
+
$log.debug("repaint FIELD: #{id}, #{name}, #{focusable}")
|
1002
1815
|
#return if display_length <= 0 # added 2009-02-17 00:17 sometimes editor comp has 0 and that
|
1003
1816
|
# becomes negative below, no because editing still happens
|
1004
1817
|
@display_length = 1 if display_length == 0
|
@@ -1017,11 +1830,12 @@ module RubyCurses
|
|
1017
1830
|
else
|
1018
1831
|
acolor = $datacolor
|
1019
1832
|
end
|
1020
|
-
@form.window.
|
1833
|
+
@graphic = @form.window if @graphic.nil? ## cell editor listbox hack XXX fix in correct place
|
1834
|
+
$log.debug " Field g:#{@graphic}. r,c,displen:#{@row}, #{@col}, #{@display_length} "
|
1835
|
+
@graphic.printstring row, col, sprintf("%-*s", display_length, printval), acolor, @attr
|
1021
1836
|
end
|
1022
1837
|
def set_focusable(tf)
|
1023
1838
|
@focusable = tf
|
1024
|
-
# @form.regenerate_focusables
|
1025
1839
|
end
|
1026
1840
|
|
1027
1841
|
# field
|
@@ -1047,13 +1861,13 @@ module RubyCurses
|
|
1047
1861
|
end
|
1048
1862
|
when 330
|
1049
1863
|
delete_curr_char if @editable
|
1050
|
-
when ?\C-a
|
1864
|
+
when ?\C-a.getbyte(0)
|
1051
1865
|
cursor_home
|
1052
|
-
when ?\C-e
|
1866
|
+
when ?\C-e.getbyte(0)
|
1053
1867
|
cursor_end
|
1054
|
-
when ?\C-k
|
1868
|
+
when ?\C-k.getbyte(0)
|
1055
1869
|
delete_eol if @editable
|
1056
|
-
when ?\C-u
|
1870
|
+
when ?\C-_.getbyte(0) # changed on 2010-02-26 14:44 so C-u can be used as numeric arg
|
1057
1871
|
@buffer.insert @curpos, @delete_buffer unless @delete_buffer.nil?
|
1058
1872
|
when 32..126
|
1059
1873
|
#$log.debug("FIELD: ch #{ch} ,at #{@curpos}, buffer:[#{@buffer}] bl: #{@buffer.to_s.length}")
|
@@ -1137,6 +1951,7 @@ module RubyCurses
|
|
1137
1951
|
set_modified
|
1138
1952
|
addcol -1
|
1139
1953
|
end
|
1954
|
+
## add a column to cursor position. Field
|
1140
1955
|
def addcol num
|
1141
1956
|
if num < 0
|
1142
1957
|
if @form.col <= @col + @col_offset
|
@@ -1213,7 +2028,7 @@ module RubyCurses
|
|
1213
2028
|
##
|
1214
2029
|
# install trigger to call whenever a value is updated
|
1215
2030
|
def update_command *args, &block
|
1216
|
-
$log.debug "Variable: update command set #{args}"
|
2031
|
+
$log.debug "Variable: update command set " # #{args}"
|
1217
2032
|
@update_command << block
|
1218
2033
|
@args << args
|
1219
2034
|
end
|
@@ -1327,9 +2142,9 @@ module RubyCurses
|
|
1327
2142
|
# for other widgets, attempt to change focus to that field
|
1328
2143
|
def bind_hotkey
|
1329
2144
|
if !@mnemonic.nil?
|
1330
|
-
ch = @mnemonic.downcase()[0] ## FIXME 1.9
|
2145
|
+
ch = @mnemonic.downcase()[0].ord ## FIXME 1.9 DONE
|
1331
2146
|
# meta key
|
1332
|
-
mch = ?\M-a + (ch - ?a)
|
2147
|
+
mch = ?\M-a.getbyte(0) + (ch - ?a.getbyte(0)) ## FIXME 1.9
|
1333
2148
|
if @label_for.is_a? RubyCurses::Button and @label_for.respond_to? :fire
|
1334
2149
|
@form.bind_key(mch, @label_for) { |_form, _butt| _butt.fire }
|
1335
2150
|
else
|
@@ -1365,8 +2180,10 @@ module RubyCurses
|
|
1365
2180
|
str = @justify.to_sym == :right ? "%*s" : "%-*s" # added 2008-12-22 19:05
|
1366
2181
|
# loop added for labels that are wrapped.
|
1367
2182
|
# TODO clear separately since value can change in status like labels
|
2183
|
+
$log.debug " RWID 1595 #{self.class} value: #{value} form: #{form} "
|
2184
|
+
@graphic = @form.window if @graphic.nil? ## HACK messagebox givig this in repaint, 423 not working ??
|
1368
2185
|
0.upto(_height-1) { |i|
|
1369
|
-
@
|
2186
|
+
@graphic.printstring r+i, c, " " * len , acolor,@attr
|
1370
2187
|
}
|
1371
2188
|
lablist.each_with_index do |_value, ix|
|
1372
2189
|
break if ix >= _height
|
@@ -1374,12 +2191,12 @@ module RubyCurses
|
|
1374
2191
|
padding = (@display_length - _value.length)/2
|
1375
2192
|
_value = " "*padding + _value + " "*padding # so its cleared if we change it midway
|
1376
2193
|
end
|
1377
|
-
@
|
2194
|
+
@graphic.printstring r, c, str % [len, _value], acolor,@attr
|
1378
2195
|
r += 1
|
1379
2196
|
end
|
1380
2197
|
if !@mnemonic.nil?
|
1381
2198
|
ulindex = value.index(@mnemonic) || value.index(@mnemonic.swapcase)
|
1382
|
-
@
|
2199
|
+
@graphic.mvchgat(y=firstrow, x=c+ulindex, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, acolor, nil)
|
1383
2200
|
end
|
1384
2201
|
#@form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, color, nil)
|
1385
2202
|
@repaint_required = false
|
@@ -1396,7 +2213,6 @@ module RubyCurses
|
|
1396
2213
|
def initialize form, config={}, &block
|
1397
2214
|
@focusable = true
|
1398
2215
|
@editable = false
|
1399
|
-
#@command_block = nil
|
1400
2216
|
@handler={} # event handler
|
1401
2217
|
@event_args ||= {}
|
1402
2218
|
super
|
@@ -1404,8 +2220,6 @@ module RubyCurses
|
|
1404
2220
|
@color ||= $datacolor
|
1405
2221
|
@surround_chars ||= ['[ ', ' ]']
|
1406
2222
|
@col_offset = @surround_chars[0].length
|
1407
|
-
#@text = @name if @text.nil?
|
1408
|
-
#bind_hotkey # 2008-12-23 22:41 remarked
|
1409
2223
|
end
|
1410
2224
|
##
|
1411
2225
|
# set button based on Action
|
@@ -1433,13 +2247,15 @@ module RubyCurses
|
|
1433
2247
|
end
|
1434
2248
|
##
|
1435
2249
|
# FIXME this will not work in messageboxes since no form available
|
2250
|
+
# if already set mnemonic, then unbind_key, ??
|
2251
|
+
|
1436
2252
|
def mnemonic char
|
1437
2253
|
$log.error " #{self} COULD NOT SET MNEMONIC since form NIL" if @form.nil?
|
1438
2254
|
return if @form.nil?
|
1439
2255
|
@mnemonic = char
|
1440
|
-
ch = char.downcase()[0] ## XXX 1.9
|
2256
|
+
ch = char.downcase()[0].ord ## XXX 1.9
|
1441
2257
|
# meta key
|
1442
|
-
mch = ?\M-a + (ch - ?a)
|
2258
|
+
mch = ?\M-a.getbyte(0) + (ch - ?a.getbyte(0))
|
1443
2259
|
$log.debug " #{self} setting MNEMO to #{char} #{mch}"
|
1444
2260
|
@form.bind_key(mch, self) { |_form, _butt| _butt.fire }
|
1445
2261
|
end
|
@@ -1460,10 +2276,10 @@ module RubyCurses
|
|
1460
2276
|
_value = @text || getvalue # hack for Togglebutton FIXME
|
1461
2277
|
#_value = getvalue
|
1462
2278
|
$log.debug " bind hot #{_value} #{@underline}"
|
1463
|
-
ch = _value[@underline,1].downcase()[0] ## XXX 1.9
|
2279
|
+
ch = _value[@underline,1].downcase()[0].ord ## XXX 1.9 2009-10-05 18:55 TOTEST
|
1464
2280
|
@mnemonic = _value[@underline,1]
|
1465
2281
|
# meta key
|
1466
|
-
mch = ?\M-a + (ch - ?a)
|
2282
|
+
mch = ?\M-a.getbyte(0) + (ch - ?a.getbyte(0))
|
1467
2283
|
@form.bind_key(mch, self) { |_form, _butt| _butt.fire }
|
1468
2284
|
end
|
1469
2285
|
# 2009-01-17 01:48 removed so widgets can be called
|
@@ -1496,12 +2312,22 @@ module RubyCurses
|
|
1496
2312
|
value = getvalue_for_paint
|
1497
2313
|
#$log.debug("button repaint :#{self} r:#{r} c:#{c} col:#{color} bg #{bgcolor} v: #{value} ul #{@underline} mnem #{@mnemonic}")
|
1498
2314
|
len = @display_length || value.length
|
1499
|
-
@form.window.
|
2315
|
+
@graphic = @form.window if @graphic.nil? ## cell editor listbox hack XXX fix in correct place
|
2316
|
+
@graphic.printstring r, c, "%-*s" % [len, value], color, @attr
|
1500
2317
|
# @form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, bgcolor, nil)
|
1501
2318
|
# in toggle buttons the underline can change as the text toggles
|
1502
2319
|
if !@underline.nil? or !@mnemonic.nil?
|
1503
2320
|
uline = @underline && (@underline + @text_offset) || value.index(@mnemonic) || value.index(@mnemonic.swapcase)
|
1504
|
-
|
2321
|
+
$log.debug " mvchgat UNDERLI r= #{r} - #{@graphic.top} c #{c} c+x #{c+uline}- #{@graphic.left} #{@graphic} "
|
2322
|
+
#$log.debug " XXX HACK in next line related to UNDERLINES -graphic.top"
|
2323
|
+
y=r #-@graphic.top
|
2324
|
+
x=c+uline #-@graphic.left
|
2325
|
+
if @graphic.window_type == :PAD
|
2326
|
+
x -= @graphic.left
|
2327
|
+
y -= @graphic.top
|
2328
|
+
end
|
2329
|
+
raise "button underline location error #{x} , #{y} " if x < 0 or c < 0
|
2330
|
+
@graphic.mvchgat(y, x, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, color, nil)
|
1505
2331
|
end
|
1506
2332
|
end
|
1507
2333
|
## command of button (invoked on press, hotkey, space)
|
@@ -1519,11 +2345,9 @@ module RubyCurses
|
|
1519
2345
|
def handle_key ch
|
1520
2346
|
case ch
|
1521
2347
|
when KEY_LEFT, KEY_UP
|
1522
|
-
$log.debug " from 2009-01-16 18:18 buttons return UNHANDLED on UP DOWN LEFT RIGHT"
|
1523
2348
|
return :UNHANDLED
|
1524
2349
|
# @form.select_prev_field
|
1525
2350
|
when KEY_RIGHT, KEY_DOWN
|
1526
|
-
$log.debug " from 2009-01-16 18:18 buttons return UNHANDLED on UP DOWN LEFT RIGHT"
|
1527
2351
|
return :UNHANDLED
|
1528
2352
|
# @form.select_next_field
|
1529
2353
|
when KEY_ENTER, 10, 13, 32 # added space bar also
|