rbcurse 0.1.3 → 1.1.1
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/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
|