rbcurse 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +33 -0
- data/README.markdown +7 -1
- data/TODO2.txt +21 -15
- data/VERSION +1 -1
- data/examples/abasiclist.rb +2 -2
- data/examples/alpmenu.rb +1 -1
- data/examples/app.rb +0 -1
- data/examples/appdirtree.rb +4 -2
- data/examples/appemail.rb +7 -3
- data/examples/appemaillb.rb +1 -1
- data/examples/appgcompose.rb +2 -2
- data/examples/appgmail.rb +1 -1
- data/examples/appmethods.rb +20 -2
- data/examples/atree.rb +9 -1
- data/examples/dbdemo.rb +460 -0
- data/examples/dirtree.rb +1 -1
- data/examples/menu1.rb +37 -5
- data/examples/multispl.rb +1 -1
- data/examples/rfe.rb +9 -2
- data/examples/splitp.rb +1 -1
- data/examples/sqlc.rb +6 -10
- data/examples/sqlm.rb +2 -20
- data/examples/sqlt.rb +408 -0
- data/examples/term2.rb +1 -1
- data/examples/test2.rb +169 -97
- data/examples/testapp.rb +1 -1
- data/examples/testapp2.rb +1 -1
- data/examples/testkeypress.rb +4 -2
- data/examples/testtable.rb +6 -0
- data/examples/testtpane.rb +35 -23
- data/examples/testvimsplit.rb +3 -2
- data/lib/rbcurse.rb +1 -1
- data/lib/rbcurse/action.rb +8 -0
- data/lib/rbcurse/app.rb +39 -23
- data/lib/rbcurse/extras/bottomline.rb +101 -13
- data/lib/rbcurse/extras/directorylist.rb +14 -5
- data/lib/rbcurse/extras/divider.rb +1 -1
- data/lib/rbcurse/extras/listselectable.rb +42 -8
- data/lib/rbcurse/extras/masterdetail.rb +2 -2
- data/lib/rbcurse/extras/scrollbar.rb +11 -2
- data/lib/rbcurse/extras/statusline.rb +56 -0
- data/lib/rbcurse/extras/stdscrwindow.rb +11 -0
- data/lib/rbcurse/extras/tabular.rb +2 -1
- data/lib/rbcurse/extras/tabularwidget.rb +60 -17
- data/lib/rbcurse/extras/viewer.rb +16 -4
- data/lib/rbcurse/keylabelprinter.rb +34 -4
- data/lib/rbcurse/listeditable.rb +5 -1
- data/lib/rbcurse/listkeys.rb +1 -1
- data/lib/rbcurse/listscrollable.rb +15 -8
- data/lib/rbcurse/rbasiclistbox.rb +44 -23
- data/lib/rbcurse/rcommandwindow.rb +8 -14
- data/lib/rbcurse/rdialogs.rb +187 -2
- data/lib/rbcurse/rlistbox.rb +38 -19
- data/lib/rbcurse/rmenu.rb +313 -93
- data/lib/rbcurse/rmessagebox.rb +3 -2
- data/lib/rbcurse/rmulticontainer.rb +5 -3
- data/lib/rbcurse/rmultisplit.rb +2 -11
- data/lib/rbcurse/rmultitextview.rb +4 -5
- data/lib/rbcurse/rtabbedpane.rb +223 -69
- data/lib/rbcurse/rtable.rb +6 -10
- data/lib/rbcurse/rtextarea.rb +57 -36
- data/lib/rbcurse/rtextview.rb +12 -15
- data/lib/rbcurse/rtree.rb +79 -22
- data/lib/rbcurse/rvimsplit.rb +16 -25
- data/lib/rbcurse/rwidget.rb +376 -523
- data/lib/rbcurse/tree/treecellrenderer.rb +24 -11
- data/lib/rbcurse/tree/treemodel.rb +1 -1
- data/lib/ver/window.rb +130 -66
- metadata +5 -3
- data/examples/term.rb +0 -48
data/lib/rbcurse/rvimsplit.rb
CHANGED
@@ -64,6 +64,10 @@ module RubyCurses
|
|
64
64
|
@suppress_borders = false
|
65
65
|
@_use_preferred_sizes = true
|
66
66
|
@row_offset = @col_offset = 1
|
67
|
+
# type can be :INCREASE, :DECREASE, :EXPAND, :UNEXPAND :EQUAL
|
68
|
+
@_events ||= []
|
69
|
+
@_events.push :COMPONENT_RESIZE_EVENT
|
70
|
+
@_events.push :DRAG_EVENT
|
67
71
|
super
|
68
72
|
@focusable = true
|
69
73
|
@editable = false
|
@@ -77,9 +81,6 @@ module RubyCurses
|
|
77
81
|
# hash, keyed on component, contains Split (which side, flow or stack, weight)
|
78
82
|
@ch = {}
|
79
83
|
@weight ||= 0.50
|
80
|
-
# type can be :INCREASE, :DECREASE, :EXPAND, :UNEXPAND :EQUAL
|
81
|
-
@_events.push :COMPONENT_RESIZE_EVENT
|
82
|
-
@_events.push :DRAG_EVENT
|
83
84
|
|
84
85
|
init_vars
|
85
86
|
bind_key([?\C-w,?o], :expand)
|
@@ -100,9 +101,6 @@ module RubyCurses
|
|
100
101
|
def init_vars
|
101
102
|
@repaint_required = true
|
102
103
|
@recalculate_splits = true # convert weight to size
|
103
|
-
# seems it works with false also, so do we really need it to be true ?
|
104
|
-
# whe true was giving a seg fault on increasing child window by 0.05
|
105
|
-
@_child_buffering = false # private, internal. not to be changed by callers.
|
106
104
|
@row_offset = @col_offset = 0 if @suppress_borders # FIXME supposed to use this !!
|
107
105
|
|
108
106
|
@internal_width = 2
|
@@ -212,25 +210,25 @@ module RubyCurses
|
|
212
210
|
when KEY_UP
|
213
211
|
# CHECK BOUNDS TODO
|
214
212
|
# TODO what about KEY_LEFT and RIGHT ?
|
215
|
-
if source.
|
213
|
+
if source.next_component && source.next_component.row > 1 && source.parent.height > 1
|
216
214
|
source.parent.height -= 1
|
217
|
-
source.
|
218
|
-
source.
|
215
|
+
source.next_component.height +=1
|
216
|
+
source.next_component.row -= 1
|
219
217
|
source.parent.repaint_required
|
220
|
-
source.
|
218
|
+
source.next_component.repaint_required
|
221
219
|
source.parent.repaint
|
222
|
-
source.
|
220
|
+
source.next_component.repaint
|
223
221
|
end
|
224
222
|
when KEY_DOWN
|
225
223
|
# CHECK BOUNDS TODO check with appemail.rb
|
226
|
-
if source.
|
224
|
+
if source.next_component && source.next_component.height > 1
|
227
225
|
source.parent.height += 1
|
228
|
-
source.
|
229
|
-
source.
|
226
|
+
source.next_component.height -=1
|
227
|
+
source.next_component.row += 1
|
230
228
|
source.parent.repaint_required
|
231
|
-
source.
|
229
|
+
source.next_component.repaint_required
|
232
230
|
source.parent.repaint
|
233
|
-
source.
|
231
|
+
source.next_component.repaint
|
234
232
|
end
|
235
233
|
end
|
236
234
|
end
|
@@ -238,9 +236,6 @@ module RubyCurses
|
|
238
236
|
end
|
239
237
|
end
|
240
238
|
c.parent_component = self
|
241
|
-
c.should_create_buffer = @_child_buffering
|
242
|
-
c.ext_row_offset += @ext_row_offset + @row #- @subform1.window.top #0# screen_row
|
243
|
-
c.ext_col_offset += @ext_col_offset + @col #-@subform1.window.left # 0# screen_col
|
244
239
|
|
245
240
|
@components << c
|
246
241
|
if which == :FIRST
|
@@ -276,7 +271,6 @@ module RubyCurses
|
|
276
271
|
# repaint object
|
277
272
|
# called by Form, and sometimes parent component (if not form).
|
278
273
|
def repaint
|
279
|
-
safe_create_buffer # 2010-01-04 12:36 BUFFERED moved here 2010-01-05 18:07
|
280
274
|
my_win = @form ? @form.window : @target_window
|
281
275
|
@graphic = my_win unless @graphic
|
282
276
|
raise " #{@name} neither form, nor target window given TV paint " unless my_win
|
@@ -368,8 +362,6 @@ module RubyCurses
|
|
368
362
|
# NOTE: at present one cannot change from flow to stack inside a pane
|
369
363
|
|
370
364
|
@repaint_required = false
|
371
|
-
@buffer_modified = true # required by form to call buffer_to_screen BUFFERED
|
372
|
-
buffer_to_window #
|
373
365
|
end
|
374
366
|
def v?
|
375
367
|
@orientation == :VERTICAL_SPLIT
|
@@ -451,8 +443,7 @@ module RubyCurses
|
|
451
443
|
rca.col += e.width
|
452
444
|
totalwd += wt if wt
|
453
445
|
end
|
454
|
-
e.set_buffering(:target_window => @target_window || @form.window, :bottom => e.height-1, :right => e.width-1, :form => @form )
|
455
|
-
e.set_buffering(:screen_top => e.row, :screen_left => e.col)
|
446
|
+
e.set_buffering(:target_window => @target_window || @form.window, :bottom => e.height-1, :right => e.width-1, :form => @form ) # removed on 2011-09-29
|
456
447
|
$log.debug " XXXXX VIMS R #{e.row} C #{e.col} H #{e.height} W #{e.width} "
|
457
448
|
e.repaint
|
458
449
|
e._object_created = true # added 2010-09-16 13:02 now prop handlers can be fired
|
@@ -726,7 +717,7 @@ module RubyCurses
|
|
726
717
|
RubyCurses::FocusManager.add @vb
|
727
718
|
@vb.parent_component = self
|
728
719
|
@components << @vb
|
729
|
-
@vb.set_buffering(:target_window => @target_window || @form.window, :form => @form )
|
720
|
+
@vb.set_buffering(:target_window => @target_window || @form.window, :form => @form ) # removed on 2011-09-29
|
730
721
|
@vb.bind :DRAG_EVENT do |ev|
|
731
722
|
if v?
|
732
723
|
case ev.type
|
data/lib/rbcurse/rwidget.rb
CHANGED
@@ -10,9 +10,12 @@
|
|
10
10
|
* Author: rkumar (arunachalesha)
|
11
11
|
* Date: 2008-11-19 12:49
|
12
12
|
* License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
13
|
-
|
14
|
-
|
15
|
-
-
|
13
|
+
|
14
|
+
== CHANGES
|
15
|
+
* 2011-10-2 Added PropertyVetoException to rollback changes to property
|
16
|
+
* 2011-10-2 Returning self from dsl_accessor and dsl_property for chaining
|
17
|
+
* 2011-10-2 removing clutter of buffering, a lot of junk code removed too.
|
18
|
+
== TODO
|
16
19
|
- make some methods private/protected
|
17
20
|
- Add bottom bar also, perhaps allow it to be displayed on a key so it does not take
|
18
21
|
- Can key bindings be abstracted so they can be inherited /reused.
|
@@ -20,8 +23,6 @@ TODO
|
|
20
23
|
|
21
24
|
|
22
25
|
=end
|
23
|
-
require 'rubygems'
|
24
|
-
##require 'ncurses'
|
25
26
|
require 'logger'
|
26
27
|
#require 'rbcurse/mapper'
|
27
28
|
require 'rbcurse/colormap'
|
@@ -60,24 +61,39 @@ end
|
|
60
61
|
class Module
|
61
62
|
## others may not want this, sets config, so there's a duplicate hash
|
62
63
|
# also creates a attr_writer so you can use =.
|
64
|
+
# 2011-10-2 V1.3.1 Now returning self, so i can chain calls
|
63
65
|
def dsl_accessor(*symbols)
|
64
66
|
symbols.each { |sym|
|
67
|
+
#open('myfile.out', 'a') { |f|
|
68
|
+
#f.puts "dsl_access #{sym} "
|
69
|
+
#}
|
65
70
|
class_eval %{
|
66
71
|
def #{sym}(*val)
|
67
72
|
if val.empty?
|
68
73
|
@#{sym}
|
69
74
|
else
|
75
|
+
#if @frozen # 2011-10-1 prevent object from being changed # changed 2011 dts
|
76
|
+
#return if @frozen && (@frozen_list.nil? || @frozen_list.include?(:#{sym}) )
|
77
|
+
#end
|
70
78
|
@#{sym} = val.size == 1 ? val[0] : val
|
71
79
|
# i am itching to deprecate next line XXX
|
72
80
|
@config["#{sym}"]=@#{sym}
|
81
|
+
self # 2011-10-2
|
73
82
|
end
|
74
83
|
end
|
75
|
-
|
84
|
+
# can the next bypass validations
|
85
|
+
# I don't think anyone will expect self to be returned if using = to assign
|
86
|
+
attr_writer sym #2011-10-2
|
87
|
+
#def #{sym}=(val)
|
88
|
+
##{sym}(val)
|
89
|
+
# self
|
90
|
+
#end
|
76
91
|
}
|
77
92
|
}
|
78
93
|
end
|
79
94
|
# Besides creating getters and setters, this also fires property change handler
|
80
95
|
# if the value changes, and after the object has been painted once.
|
96
|
+
# 2011-10-2 V1.3.1 Now returning self, so i can chain calls
|
81
97
|
def dsl_property(*symbols)
|
82
98
|
symbols.each { |sym|
|
83
99
|
class_eval %{
|
@@ -85,21 +101,34 @@ class Module
|
|
85
101
|
if val.empty?
|
86
102
|
@#{sym}
|
87
103
|
else
|
104
|
+
#return(self) if @frozen && (@frozen_list.nil? || @frozen_list.include?(:#{sym}) )
|
88
105
|
oldvalue = @#{sym}
|
89
|
-
@#{sym} = val.size == 1 ? val[0] : val
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
106
|
+
# @#{sym} = val.size == 1 ? val[0] : val
|
107
|
+
tmp = val.size == 1 ? val[0] : val
|
108
|
+
newvalue = tmp
|
109
|
+
# i am itching to deprecate config setting
|
110
|
+
if oldvalue.nil? || @_object_created.nil?
|
111
|
+
@#{sym} = tmp
|
112
|
+
@config["#{sym}"]=@#{sym}
|
113
|
+
end
|
114
|
+
return(self) if oldvalue.nil? || @_object_created.nil?
|
115
|
+
|
94
116
|
if oldvalue != newvalue
|
95
117
|
# trying to reduce calls to fire, when object is being created
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
118
|
+
begin
|
119
|
+
fire_property_change("#{sym}", oldvalue, newvalue) if !oldvalue.nil?
|
120
|
+
@#{sym} = tmp
|
121
|
+
@config["#{sym}"]=@#{sym}
|
122
|
+
rescue PropertyVetoException
|
123
|
+
$log.warn "PropertyVetoException for #{sym}:" + oldvalue + "-> "+newvalue
|
124
|
+
end
|
125
|
+
end # if old
|
126
|
+
self
|
127
|
+
end # if val
|
128
|
+
end # def
|
100
129
|
#attr_writer sym
|
101
130
|
def #{sym}=val
|
102
|
-
|
131
|
+
# TODO if Variable, take .value NEXT VERSION
|
103
132
|
#{sym}(val)
|
104
133
|
end
|
105
134
|
}
|
@@ -120,12 +149,25 @@ class Fixnum
|
|
120
149
|
end
|
121
150
|
end unless "a"[0] == "a"
|
122
151
|
|
123
|
-
#include Ncurses XXX 2011-09-8 testing FFI
|
124
152
|
module RubyCurses
|
125
153
|
extend self
|
126
154
|
include ColorMap
|
127
155
|
class FieldValidationException < RuntimeError
|
128
156
|
end
|
157
|
+
|
158
|
+
# The property change is not acceptable, undo it. e.g. test2.rb
|
159
|
+
# @param [String] text message
|
160
|
+
# @param [Event] PropertyChangeEvent object
|
161
|
+
# @since 1.4.0
|
162
|
+
class PropertyVetoException < RuntimeError
|
163
|
+
def initialize(string, event)
|
164
|
+
@string = string
|
165
|
+
@event = event
|
166
|
+
super(string)
|
167
|
+
end
|
168
|
+
attr_reader :string, :event
|
169
|
+
end
|
170
|
+
|
129
171
|
module Utils
|
130
172
|
## this is the numeric argument used to repeat and action by repeatm()
|
131
173
|
$multiplier = 0
|
@@ -247,7 +289,7 @@ module RubyCurses
|
|
247
289
|
# 2010-02-24 12:43 trying to take in multiple key bindings, TODO unbind
|
248
290
|
# TODO add symbol so easy to map from config file or mapping file
|
249
291
|
def bind_key keycode, *args, &blk
|
250
|
-
|
292
|
+
$log.debug " #{@name} bind_key received #{keycode} "
|
251
293
|
@key_handler ||= {}
|
252
294
|
if !block_given?
|
253
295
|
blk = args.pop
|
@@ -258,7 +300,7 @@ module RubyCurses
|
|
258
300
|
when String
|
259
301
|
keycode = keycode.getbyte(0) #if keycode.class==String ## 1.9 2009-10-05 19:40
|
260
302
|
#$log.debug " #{name} Widg String called bind_key BIND #{keycode}, #{keycode_tos(keycode)} "
|
261
|
-
$log.debug "
|
303
|
+
$log.debug " assigning #{keycode} " if $log.debug?
|
262
304
|
@key_handler[keycode] = blk
|
263
305
|
when Array
|
264
306
|
# for starters lets try with 2 keys only
|
@@ -268,11 +310,11 @@ module RubyCurses
|
|
268
310
|
a1 = keycode[1]
|
269
311
|
a1 = keycode[1].getbyte(0) if keycode[1].class == String
|
270
312
|
@key_handler[a0] ||= OrderedHash.new
|
271
|
-
$log.debug "
|
313
|
+
$log.debug " assigning #{keycode} , A0 #{a0} , A1 #{a1} " if $log.debug?
|
272
314
|
@key_handler[a0][a1] = blk
|
273
|
-
#$log.debug "
|
315
|
+
#$log.debug " XX assigning #{keycode} to key_handler " if $log.debug?
|
274
316
|
else
|
275
|
-
#$log.debug "
|
317
|
+
#$log.debug " assigning #{keycode} to key_handler " if $log.debug?
|
276
318
|
@key_handler[keycode] = blk
|
277
319
|
end
|
278
320
|
@key_args ||= {}
|
@@ -312,7 +354,7 @@ module RubyCurses
|
|
312
354
|
if respond_to? blk
|
313
355
|
return send(blk, *@key_args[keycode])
|
314
356
|
else
|
315
|
-
alert "This does not respond to #{blk.to_s} "
|
357
|
+
alert "This ( #{self.class} ) does not respond to #{blk.to_s} "
|
316
358
|
end
|
317
359
|
else
|
318
360
|
$log.debug "rwidget BLOCK called _process_key " if $log.debug?
|
@@ -325,7 +367,7 @@ module RubyCurses
|
|
325
367
|
require 'rbcurse/extras/viewer'
|
326
368
|
RubyCurses::Viewer.view what, config
|
327
369
|
end
|
328
|
-
end
|
370
|
+
end # module
|
329
371
|
|
330
372
|
module EventHandler
|
331
373
|
##
|
@@ -333,9 +375,12 @@ module RubyCurses
|
|
333
375
|
def bind event, *xargs, &blk
|
334
376
|
#$log.debug "#{self} called EventHandler BIND #{event}, args:#{xargs} "
|
335
377
|
if @_events
|
336
|
-
|
378
|
+
$log.warn "#{self.class} does not support this event: #{event}. #{@_events} " if !@_events.include? event
|
379
|
+
#raise ArgumentError, "#{self.class} does not support this event: #{event}. #{@_events} " if !@_events.include? event
|
337
380
|
else
|
338
|
-
|
381
|
+
# it can come here if bind in initial block, since widgets add to @_event after calling super
|
382
|
+
# maybe we can change that.
|
383
|
+
$log.warn "BIND #{self.class} (#{event}) XXXXX no events defined in @_events. Please do so to avoid bugs and debugging. This will become a fatal error soon."
|
339
384
|
end
|
340
385
|
@handler ||= {}
|
341
386
|
@event_args ||= {}
|
@@ -378,6 +423,10 @@ module RubyCurses
|
|
378
423
|
# added 2011-09-26 1.3.0 so a user raised exception on LEAVE
|
379
424
|
# keeps cursor in same field.
|
380
425
|
raise fve
|
426
|
+
rescue PropertyVetoException => pve
|
427
|
+
# added 2011-09-26 1.3.0 so a user raised exception on LEAVE
|
428
|
+
# keeps cursor in same field.
|
429
|
+
raise pve
|
381
430
|
rescue => ex
|
382
431
|
## some don't have name
|
383
432
|
#$log.error "======= Error ERROR in block event #{self}: #{name}, #{event}"
|
@@ -395,8 +444,8 @@ module RubyCurses
|
|
395
444
|
## added on 2009-01-08 00:33
|
396
445
|
# goes with dsl_property
|
397
446
|
# Need to inform listeners - done 2010-02-25 23:09
|
447
|
+
# Can throw a FieldValidationException or PropertyVetoException
|
398
448
|
def fire_property_change text, oldvalue, newvalue
|
399
|
-
# should i return if oldvalue is nil ??? TODO XXX
|
400
449
|
#$log.debug " FPC #{self}: #{text} #{oldvalue}, #{newvalue}"
|
401
450
|
return if oldvalue.nil? || @_object_created.nil? # added 2010-09-16 so if called by methods it is still effective
|
402
451
|
if @pce.nil?
|
@@ -406,6 +455,7 @@ module RubyCurses
|
|
406
455
|
end
|
407
456
|
fire_handler :PROPERTY_CHANGE, @pce
|
408
457
|
@repaint_required = true # this was a hack and shoudl go, someone wanted to set this so it would repaint (viewport line 99 fire_prop
|
458
|
+
repaint_all(true) # for repainting borders, headers etc 2011-09-28 V1.3.1
|
409
459
|
end
|
410
460
|
|
411
461
|
end # module eventh
|
@@ -443,6 +493,14 @@ module RubyCurses
|
|
443
493
|
end
|
444
494
|
end
|
445
495
|
end # module config
|
496
|
+
|
497
|
+
#
|
498
|
+
# prints a status line at bottom where mode's statuses et can be reflected
|
499
|
+
def status_line config={}, &block
|
500
|
+
require 'rbcurse/extras/statusline'
|
501
|
+
sl = RubyCurses::StatusLine.new @form, config, &block
|
502
|
+
end
|
503
|
+
|
446
504
|
##
|
447
505
|
# Basic widget class.
|
448
506
|
# NOTE: I may soon remove the config hash. I don't use it and its just making things heavy.
|
@@ -481,34 +539,40 @@ module RubyCurses
|
|
481
539
|
dsl_property :min_width # added 2009-10-28 13:40 for splitpanes and better resizing
|
482
540
|
dsl_property :min_height # added 2009-10-28 13:40 for splitpanes and better resizing
|
483
541
|
|
484
|
-
## 2010-01-05 13:27 create buffer conditionally, if enclosing component asks. Needs to be passed down
|
485
|
-
##+ to further children or editor components. Default false.
|
486
|
-
attr_accessor :should_create_buffer # added 2010-01-05 13:16 BUFFERED, trying to create buffersonly where required.
|
487
542
|
attr_accessor :_object_created # 2010-09-16 12:12 to prevent needless property change firing when object being set
|
488
543
|
|
544
|
+
#attr_accessor :frozen # true false
|
545
|
+
#attr_accessor :frozen_list # list of attribs that cannot be changed
|
489
546
|
## I think parent_form was not a good idea since i can't add parent widget offsets
|
490
547
|
##+ thus we should use parent_comp and push up.
|
491
548
|
attr_accessor :parent_component # added 2010-01-12 23:28 BUFFERED - to bubble up
|
492
549
|
# tired of getting the cursor wrong and guessing, i am now going to try to get absolute
|
493
550
|
# coordinates - 2010-02-07 20:17 this should be updated by parent.
|
494
|
-
attr_accessor :ext_col_offset, :ext_row_offset # 2010-02-07 20:16 to get abs position for cursor
|
551
|
+
#attr_accessor :ext_col_offset, :ext_row_offset # 2010-02-07 20:16 to get abs position for cursor rem 2011-09-29
|
495
552
|
attr_accessor :rows_panned # moved from form, how many rows scrolled.panned 2010-02-11 15:26
|
496
553
|
attr_accessor :cols_panned # moved from form, how many cols scrolled.panned 2010-02-11 15:26
|
497
554
|
|
498
555
|
# sometimes inside a container there's no way of knowing if an individual comp is in focus
|
499
556
|
# other than the explicitly set it and inquire . 2010-09-02 14:47 @since 1.1.5
|
557
|
+
# NOTE state takes care of this and is set by form
|
500
558
|
attr_accessor :focussed # is this widget in focus, so they may paint differently
|
501
559
|
|
502
560
|
def initialize form, aconfig={}, &block
|
503
561
|
@form = form
|
504
562
|
@row_offset ||= 0
|
505
563
|
@col_offset ||= 0
|
506
|
-
|
564
|
+
#@ext_row_offset = @ext_col_offset = 0 # 2010-02-07 20:18 # removed on 2011-09-29
|
507
565
|
@state = :NORMAL
|
508
566
|
@attr = nil
|
509
567
|
|
510
568
|
@handler = nil # we can avoid firing if nil
|
511
569
|
@event_args = {}
|
570
|
+
# These are standard events for most widgets which will be fired by
|
571
|
+
# Form. In the case of CHANGED, form fires if it's editable property is set, so
|
572
|
+
# it does not apply to all widgets.
|
573
|
+
@_events ||= []
|
574
|
+
@_events.push( *[:ENTER, :LEAVE, :CHANGED, :PROPERTY_CHANGE])
|
575
|
+
|
512
576
|
config_setup aconfig # @config.each_pair { |k,v| variable_set(k,v) }
|
513
577
|
#instance_eval &block if block_given?
|
514
578
|
if block_given?
|
@@ -522,10 +586,6 @@ module RubyCurses
|
|
522
586
|
# own default
|
523
587
|
@bgcolor ||= "black" # 0
|
524
588
|
@color ||= "white" # $datacolor
|
525
|
-
# These are standard events for most widgets which will be fired by
|
526
|
-
# Form. In the case of CHANGED, form fires if it's editable property is set, so
|
527
|
-
# it does not apply to all widgets.
|
528
|
-
@_events = [:ENTER, :LEAVE, :CHANGED, :PROPERTY_CHANGE]
|
529
589
|
# @id = form.add_widget(self) if !form.nil? and form.respond_to? :add_widget
|
530
590
|
set_form(form) unless form.nil?
|
531
591
|
end
|
@@ -533,7 +593,7 @@ module RubyCurses
|
|
533
593
|
# just in case anyone does a super. Not putting anything here
|
534
594
|
# since i don't want anyone accidentally overriding
|
535
595
|
@buffer_modified = false
|
536
|
-
#@manages_cursor = false # form should manage it, I will pass row and col to it.
|
596
|
+
#@manages_cursor = false # form should manage it, I will pass row and col to it.
|
537
597
|
end
|
538
598
|
|
539
599
|
# modified
|
@@ -594,22 +654,17 @@ module RubyCurses
|
|
594
654
|
end
|
595
655
|
##
|
596
656
|
# default repaint method. Called by form for all widgets.
|
597
|
-
#
|
657
|
+
# widget does not have display_length.
|
598
658
|
def repaint
|
599
659
|
r,c = rowcol
|
600
660
|
$log.debug("widget repaint : r:#{r} c:#{c} col:#{@color}" )
|
601
661
|
value = getvalue_for_paint
|
602
662
|
len = @display_length || value.length
|
603
663
|
acolor = @color_pair || get_color($datacolor, @color, @bgcolor)
|
604
|
-
#if @bgcolor.is_a? String and @color.is_a? String
|
605
|
-
#acolor = ColorMap.get_color(@color, @bgcolor)
|
606
|
-
#else
|
607
|
-
#acolor = $datacolor
|
608
|
-
#end
|
609
664
|
@graphic.printstring r, c, "%-*s" % [len, value], acolor, @attr
|
610
665
|
# next line should be in same color but only have @att so we can change att is nec
|
611
666
|
#@form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, @bgcolor, nil)
|
612
|
-
|
667
|
+
#@buffer_modified = true # required for form to call buffer_to_screen CLEANUP
|
613
668
|
end
|
614
669
|
|
615
670
|
def destroy
|
@@ -661,9 +716,11 @@ module RubyCurses
|
|
661
716
|
end
|
662
717
|
# puts cursor on correct row.
|
663
718
|
def set_form_row
|
664
|
-
raise "empty todo widget"
|
665
719
|
# @form.row = @row + 1 + @winrow
|
666
|
-
|
720
|
+
#@form.row = @row + 1
|
721
|
+
r, c = rowcol
|
722
|
+
$log.warn " empty set_form_row in widget #{self} r = #{r} , c = #{c} "
|
723
|
+
setrowcol row, nil
|
667
724
|
end
|
668
725
|
# set cursor on correct column, widget
|
669
726
|
# Ideally, this should be overriden, as it is not likely to be correct.
|
@@ -671,7 +728,7 @@ module RubyCurses
|
|
671
728
|
@curpos = col1 || 0 # 2010-01-14 21:02
|
672
729
|
#@form.col = @col + @col_offset + @curpos
|
673
730
|
c = @col + @col_offset + @curpos
|
674
|
-
$log.
|
731
|
+
$log.warn " #{@name} empty set_form_col #{c}, #{@form} "
|
675
732
|
setrowcol nil, c
|
676
733
|
end
|
677
734
|
def hide
|
@@ -690,7 +747,7 @@ module RubyCurses
|
|
690
747
|
end
|
691
748
|
##
|
692
749
|
# moves focus to this field
|
693
|
-
#
|
750
|
+
# we must look into running on_leave of previous field
|
694
751
|
def focus
|
695
752
|
return if !@focusable
|
696
753
|
if @form.validate_field != -1
|
@@ -698,39 +755,6 @@ module RubyCurses
|
|
698
755
|
end
|
699
756
|
end
|
700
757
|
##
|
701
|
-
# bind an action to a key, required if you create a button which has a hotkey
|
702
|
-
# or a field to be focussed on a key, or any other user defined action based on key
|
703
|
-
# e.g. bind_key ?\C-x, object, block
|
704
|
-
# added 2009-01-06 19:13 since widgets need to handle keys properly
|
705
|
-
# 2010-02-24 12:43 trying to take in multiple key bindings, TODO unbind
|
706
|
-
# TODO add symbol so easy to map from config file or mapping file
|
707
|
-
def OLDbind_key keycode, *args, &blk
|
708
|
-
@key_handler ||= {}
|
709
|
-
if !block_given?
|
710
|
-
blk = args.pop
|
711
|
-
raise "If block not passed, last arg should be a method symbol" if !blk.is_a? Symbol
|
712
|
-
$log.debug " #{@name} bind_key received a symbol #{blk} "
|
713
|
-
end
|
714
|
-
case keycode
|
715
|
-
when String
|
716
|
-
$log.debug "Widg String called bind_key BIND #{keycode} #{keycode_tos(keycode)} "
|
717
|
-
keycode = keycode.getbyte(0) #if keycode.class==String ## 1.9 2009-10-05 19:40
|
718
|
-
@key_handler[keycode] = blk
|
719
|
-
when Array
|
720
|
-
# for starters lets try with 2 keys only
|
721
|
-
a0 = keycode[0]
|
722
|
-
a0 = keycode[0].getbyte(0) if keycode[0].class == String
|
723
|
-
a1 = keycode[1]
|
724
|
-
a1 = keycode[1].getbyte(0) if keycode[1].class == String
|
725
|
-
@key_handler[a0] ||= OrderedHash.new
|
726
|
-
@key_handler[a0][a1] = blk
|
727
|
-
else
|
728
|
-
@key_handler[keycode] = blk
|
729
|
-
end
|
730
|
-
@key_args ||= {}
|
731
|
-
@key_args[keycode] = args
|
732
|
-
end
|
733
|
-
##
|
734
758
|
# remove a binding that you don't want
|
735
759
|
def unbind_key keycode
|
736
760
|
@key_args.delete keycode unless @key_args.nil?
|
@@ -741,12 +765,6 @@ module RubyCurses
|
|
741
765
|
# returns UNHANDLED if no block for it
|
742
766
|
# after form handles basic keys, it gives unhandled key to current field, if current field returns
|
743
767
|
# unhandled, then it checks this map.
|
744
|
-
# added 2009-01-06 19:13 since widgets need to handle keys properly
|
745
|
-
# added 2009-01-18 12:58 returns ret val of blk.call
|
746
|
-
# so that if block does not handle, the key can still be handled
|
747
|
-
# e.g. table last row, last col does not handle, so it will auto go to next field
|
748
|
-
# 2010-02-24 13:45 handles 2 key combinations, copied from Form, must be identical in logic
|
749
|
-
# except maybe for window pointer. TODO not tested
|
750
768
|
def process_key keycode, object
|
751
769
|
return _process_key keycode, object, @graphic
|
752
770
|
end
|
@@ -761,62 +779,8 @@ module RubyCurses
|
|
761
779
|
def get_preferred_size
|
762
780
|
return @preferred_height, @preferred_width
|
763
781
|
end
|
764
|
-
##
|
765
|
-
# creates a buffer for the widget to write to.
|
766
|
-
# This is typically called in the constructor. Sometimes, the constructor
|
767
|
-
# does not have a height or width, since the object will be resized based on parents
|
768
|
-
# size, as in splitpane
|
769
|
-
# Please use this only if embedding this object in another object/s that would wish
|
770
|
-
# to crop this. Otherwise, you could have many pads in your app.
|
771
|
-
# Sets @graphic which can be used in place of @form.window
|
772
|
-
#
|
773
|
-
# @return [buffer] returns pad created
|
774
|
-
# @since 0.1.3
|
775
|
-
# NOTE: 2010-01-12 11:14 there are some parent widgets that may want this w to have a larger top and left.
|
776
|
-
# Setting it later, means that the first repaint can be off.
|
777
|
-
|
778
|
-
def create_buffer()
|
779
|
-
$log.debug " #{self.class} CB called with #{@should_create_buffer} H: #{@height} W #{@width} "
|
780
|
-
if @should_create_buffer
|
781
|
-
@height or $log.warn " CB height is nil, setting to 1. This may not be what you want"
|
782
|
-
mheight = @height || 1 # some widgets don't have height XXX
|
783
|
-
mwidth = @width || 30 # some widgets don't have width as yet
|
784
|
-
mrow = @row || 0
|
785
|
-
mcol = @col || 0
|
786
|
-
layout = { :height => mheight, :width => mwidth, :top => mrow, :left => mcol }
|
787
|
-
$log.debug " cb .. #{@name} create_buffer #{mrow} #{mcol} #{mheight} #{mwidth}"
|
788
|
-
@screen_buffer = VER::Pad.create_with_layout(layout)
|
789
|
-
@is_double_buffered = true # will be checked prior to blitting
|
790
|
-
@buffer_modified = true # set this in repaint
|
791
|
-
@repaint_all = true # added 2010-01-08 19:02
|
792
|
-
else
|
793
|
-
## NOTE: if form has not been set, you could run into problems
|
794
|
-
## Typically a form MUST be set by now, unless you are buffering, in which
|
795
|
-
##+ case it should go in above block.
|
796
|
-
@screen_buffer = @form.window if @form
|
797
|
-
end
|
798
782
|
|
799
|
-
@graphic = @screen_buffer # use buffer for writing, not screen window
|
800
|
-
return @screen_buffer
|
801
|
-
end # create_buffer
|
802
783
|
|
803
|
-
##
|
804
|
-
# checks if buffer not created already, and figures
|
805
|
-
# out dimensions.
|
806
|
-
# Preferable to use this instead of directly using create_buffer.
|
807
|
-
#
|
808
|
-
def safe_create_buffer
|
809
|
-
if @screen_buffer == nil
|
810
|
-
if @height == nil
|
811
|
-
@height = @preferred_height || @min_height
|
812
|
-
end
|
813
|
-
if @width == nil
|
814
|
-
@width = @preferred_width || @min_width
|
815
|
-
end
|
816
|
-
create_buffer
|
817
|
-
end
|
818
|
-
return @screen_buffer
|
819
|
-
end
|
820
784
|
##
|
821
785
|
# Inform the system that the buffer has been modified
|
822
786
|
# and should be blitted over the screen or copied to parent.
|
@@ -825,72 +789,6 @@ module RubyCurses
|
|
825
789
|
end
|
826
790
|
|
827
791
|
|
828
|
-
##
|
829
|
-
# copy the buffer to the screen, or given window/pad.
|
830
|
-
# Relevant only in double_buffered case since pad has to be written
|
831
|
-
# to screen. Should be called only by outer form, not by widgets as a widget
|
832
|
-
# could be inside another widget.
|
833
|
-
# Somewhere we need to clear screen if scrolling.???
|
834
|
-
# aka b2s
|
835
|
-
# @param [Window, #get_window, nil] screen to write to, if nil then write to phys screen
|
836
|
-
# @return 0 - copy success, -1 copy failure, 1 - did nothing, usually since buffer_modified false
|
837
|
-
|
838
|
-
def buffer_to_screen(screen=nil, pminrow=0, pmincol=0)
|
839
|
-
raise "deprecated b2s "
|
840
|
-
return 1 unless @is_double_buffered and @buffer_modified
|
841
|
-
# screen is nil when form calls this to write to physical screen
|
842
|
-
$log.debug " screen inside buffer_to_screen b2s :#{screen} "
|
843
|
-
$log.error "ERROR !I have moved away fomr this method. Your program is broken and will not be working"
|
844
|
-
## 2010-01-03 19:38 i think its wrong to put the pad onto the screen
|
845
|
-
##+ since wrefreshing the window will cause this to be overwriting
|
846
|
-
##+ so i put current window here.
|
847
|
-
if screen == nil
|
848
|
-
#$log.debug " XXX calling graphic.wrefresh 2010-01-03 12:27 (parent_buffer was nil) "
|
849
|
-
#$log.debug " XXX 2010-01-03 20:47 now copying pad #{@graphic} onto form.window"
|
850
|
-
ret = @graphic.wrefresh
|
851
|
-
## 2010-01-03 20:45 rather than writing to phys screen, i write to forms window
|
852
|
-
##+ so later updates to that window do not overwrite this widget.
|
853
|
-
## We need to check this out with scrollpane and splitpane.
|
854
|
-
#ret = @graphic.copywin(@form.window.get_window, 0, 0, @row, @col, @row+@height-1, @col+@width-1,0)
|
855
|
-
else
|
856
|
-
# screen is passed when a parent object calls this to copy child buffer to itself
|
857
|
-
@graphic.set_backing_window(screen)
|
858
|
-
$log.debug " #{@name} #{@graphic} calling copy pad to win COPY"
|
859
|
-
ret = @graphic.copy_pad_to_win
|
860
|
-
end
|
861
|
-
@buffer_modified = false
|
862
|
-
return ret
|
863
|
-
end # buffer_to_screen
|
864
|
-
##
|
865
|
-
# returns screen_buffer or nil
|
866
|
-
#
|
867
|
-
# @return [screen_buffer, nil] screen_buffer earlier created
|
868
|
-
# @since 0.1.3
|
869
|
-
|
870
|
-
def get_buffer()
|
871
|
-
@screen_buffer
|
872
|
-
end # get_buffer
|
873
|
-
|
874
|
-
##
|
875
|
-
# destroys screen_buffer if present
|
876
|
-
#
|
877
|
-
# @return
|
878
|
-
# @since 0.1.3
|
879
|
-
|
880
|
-
def destroy_buffer()
|
881
|
-
if @screen_buffer != nil
|
882
|
-
@screen_buffer.destroy # ???
|
883
|
-
end
|
884
|
-
end # destroy_buffer
|
885
|
-
|
886
|
-
##
|
887
|
-
# Does the widget buffer its output in a pad
|
888
|
-
#
|
889
|
-
# @return [true, false] comment
|
890
|
-
|
891
|
-
def is_double_buffered?()
|
892
|
-
@is_double_buffered
|
893
|
-
end # is_double_buffered
|
894
792
|
|
895
793
|
##
|
896
794
|
# getter and setter for width - 2009-10-29 22:45
|
@@ -901,11 +799,11 @@ module RubyCurses
|
|
901
799
|
# @since 0.1.3
|
902
800
|
#
|
903
801
|
def width(*val)
|
904
|
-
#$log.debug " inside
|
802
|
+
#$log.debug " inside width() #{val}"
|
905
803
|
if val.empty?
|
906
804
|
return @width
|
907
805
|
else
|
908
|
-
#$log.debug " inside
|
806
|
+
#$log.debug " inside width()"
|
909
807
|
oldvalue = @width || 0 # is this default okay, else later nil cries
|
910
808
|
#@width = val.size == 1 ? val[0] : val
|
911
809
|
@width = val[0]
|
@@ -915,10 +813,10 @@ module RubyCurses
|
|
915
813
|
fire_property_change(:width, oldvalue, newvalue)
|
916
814
|
repaint_all(true) # added 2010-01-08 18:51 so widgets can redraw everything.
|
917
815
|
end
|
918
|
-
if is_double_buffered? and newvalue != oldvalue
|
919
|
-
|
920
|
-
|
921
|
-
end
|
816
|
+
#if is_double_buffered? and newvalue != oldvalue # removed on 2011-09-29
|
817
|
+
#$log.debug " #{@name} w calling resize of screen buffer with #{newvalue}. WARNING: does not change buffering_params"
|
818
|
+
#@screen_buffer.resize(0, newvalue)
|
819
|
+
#end
|
922
820
|
end
|
923
821
|
end
|
924
822
|
def width=val
|
@@ -933,7 +831,7 @@ module RubyCurses
|
|
933
831
|
# @since 0.1.3
|
934
832
|
#
|
935
833
|
def height(*val)
|
936
|
-
#$log.debug " inside
|
834
|
+
#$log.debug " inside height() #{val[0]}"
|
937
835
|
if val.empty?
|
938
836
|
return @height
|
939
837
|
else
|
@@ -947,12 +845,6 @@ module RubyCurses
|
|
947
845
|
$log.debug " widget #{@name} setting repaint_all to true"
|
948
846
|
@repaint_all=true
|
949
847
|
end
|
950
|
-
# XXX this troubles me a lot. gets fired more than we would like
|
951
|
-
# XXX When both h and w change then happens 2 times.
|
952
|
-
if is_double_buffered? and newvalue != oldvalue
|
953
|
-
$log.debug " #{@name} h calling resize of screen buffer with #{newvalue}"
|
954
|
-
@screen_buffer.resize(newvalue, 0)
|
955
|
-
end
|
956
848
|
end
|
957
849
|
end
|
958
850
|
def height=val
|
@@ -1018,85 +910,21 @@ module RubyCurses
|
|
1018
910
|
#setformrowcol r,c
|
1019
911
|
end
|
1020
912
|
|
913
|
+
# I was removing this altogether but vimsplit needs this, or masterdetail gives form and window
|
914
|
+
# to vimsplit. So i 've removed everything but the form and window setting. 2011-09-29 SETBUFF
|
1021
915
|
# move from TextView
|
1022
916
|
# parameters relating to buffering - new 2010-02-12 12:09 RFED16
|
1023
917
|
# I am merging so i can call multiple times
|
1024
918
|
# WARNING NOTE : this does not set Pad's top and left since Pad may not be created yet, or at all
|
1025
919
|
def set_buffering params
|
1026
|
-
|
1027
|
-
#@should_create_buffer = params[:should_create_buffer] || true
|
920
|
+
|
1028
921
|
@target_window ||= params[:target_window]
|
1029
|
-
# trying out, 2010-02-12 19:40 sometimes no form even with parent.
|
1030
922
|
@form = params[:form] unless @form
|
1031
|
-
|
1032
|
-
# what if container does not ask child to buffer, as in splitpane
|
1033
|
-
# then graphic could be nil
|
1034
|
-
if @graphic.nil? # and should_create_buffer not set or false XXX
|
923
|
+
if @graphic.nil?
|
1035
924
|
@graphic = @target_window
|
1036
925
|
end
|
1037
|
-
$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]} "
|
1038
|
-
# @top = params[:top]
|
1039
|
-
# @left = params[:left]
|
1040
|
-
# @bottom = params[:bottom]
|
1041
|
-
# @right = params[:right]
|
1042
|
-
# offsets ?
|
1043
|
-
# warning, this does not touch @top and left of Pad, often pad will bot yet be created
|
1044
|
-
@buffer_params.merge!(params)
|
1045
|
-
if !@screen_buffer.nil?
|
1046
|
-
# update Pad since some folks take from there such as print_border
|
1047
|
-
@screen_buffer.top = params[:screen_top] if !params[:screen_top].nil?
|
1048
|
-
@screen_buffer.left = params[:screen_left] if !params[:screen_left].nil?
|
1049
|
-
end
|
1050
926
|
end
|
1051
927
|
|
1052
|
-
# copy buffer onto window
|
1053
|
-
# RFED16 added 2010-02-12 14:42 0 simpler buffer management
|
1054
|
-
def buffer_to_window
|
1055
|
-
if @is_double_buffered and @buffer_modified
|
1056
|
-
raise " #{@name} @buffer_params not passed. Use set_buffering()" unless @buffer_params
|
1057
|
-
# we are notchecking for TV's width exceedingg, could get -1 if TV exceeds parent/
|
1058
|
-
$log.debug "RFED16 paint #{@name} calling b2s #{@graphic} "
|
1059
|
-
# TODO need to call set_screen_row_col (top, left), set_pad_top_left (pminrow, pmaxrow), set_screen_max_row_col
|
1060
|
-
if false
|
1061
|
-
# boh these print the pad behind 0,0, later scroll etc cover it and show bars.
|
1062
|
-
# adding window was giving error
|
1063
|
-
ret = buffer_to_screen #@target_window.get_window
|
1064
|
-
#ret = @graphic.wrefresh
|
1065
|
-
else
|
1066
|
-
# ext gives me parents offset. often the row would be zero, so we still need one extra
|
1067
|
-
r1 = @ext_row_offset # XXX NO, i should use top and left
|
1068
|
-
c1 = @ext_col_offset
|
1069
|
-
r = @graphic.top # 2010-02-12 21:12 TRYING THIS.
|
1070
|
-
c = @graphic.left
|
1071
|
-
maxr = @buffer_params[:bottom]
|
1072
|
-
maxc = @buffer_params[:right]
|
1073
|
-
r = @buffer_params[:screen_top] || 0
|
1074
|
-
c = @buffer_params[:screen_left] || 0
|
1075
|
-
$log.debug " b2w #{r1} #{c1} , #{r} #{c} "
|
1076
|
-
## sadly this is bypassing the method that does this stuff in Pad. We need to assimilate it back, so not so much work here
|
1077
|
-
pminr = @graphic.pminrow
|
1078
|
-
pminc = @graphic.pmincol
|
1079
|
-
border_width = 0 # 2 #XXX 2010-02-15 23:40 2 to 0
|
1080
|
-
$log.debug " #{@name} ret = @graphic.copywin(@target_window.get_window, #{pminr}, #{pminc}, #{r}, #{c}, #{r}+#{maxr} - #{border_width}, #{c} + #{maxc} - #{border_width} ,0)"
|
1081
|
-
# this print the view at 0,0, byt covers the scrllare, bars not shown.
|
1082
|
-
# this can crash if textview is smaller than container dimension
|
1083
|
-
# can crash/give -1 when panning, giong beyond pad size XXX
|
1084
|
-
ret = @graphic.copywin(@target_window.get_window, pminr, pminc, r, c, r+maxr-border_width, c+maxc-border_width,0)
|
1085
|
-
if ret == -1
|
1086
|
-
$log.debug " copywin #{@name} h #{@height} w #{@width} "
|
1087
|
-
if @height <= maxr-border_width
|
1088
|
-
$log.warn " h #{@height} is <= :bottom #{maxr} "
|
1089
|
-
end
|
1090
|
-
if @width <= maxc-border_width
|
1091
|
-
$log.warn " h #{@width} is <= :right #{maxc} "
|
1092
|
-
end
|
1093
|
-
$log.warn "ERROR !!! copywin returns -1 check Target: #{@target_window}, #{@target_window.get_window} " if ret == -1
|
1094
|
-
end
|
1095
|
-
end
|
1096
|
-
$log.debug " copywin ret --> #{ret} "
|
1097
|
-
#
|
1098
|
-
end
|
1099
|
-
end
|
1100
928
|
def event_list
|
1101
929
|
return @@events if defined? @@events
|
1102
930
|
nil
|
@@ -1113,64 +941,84 @@ module RubyCurses
|
|
1113
941
|
class Form
|
1114
942
|
include EventHandler
|
1115
943
|
include RubyCurses::Utils
|
1116
|
-
attr_reader :value
|
944
|
+
attr_reader :value # ???
|
945
|
+
|
946
|
+
# array of widgets
|
1117
947
|
attr_reader :widgets
|
948
|
+
|
949
|
+
# related window used for printing
|
1118
950
|
attr_accessor :window
|
951
|
+
|
952
|
+
# cursor row and col
|
1119
953
|
attr_accessor :row, :col
|
1120
954
|
# attr_accessor :color
|
1121
955
|
# attr_accessor :bgcolor
|
1122
|
-
|
1123
|
-
|
956
|
+
|
957
|
+
# has the form been modified
|
1124
958
|
attr_accessor :modified
|
959
|
+
|
960
|
+
# index of active widget
|
1125
961
|
attr_accessor :active_index
|
1126
|
-
|
962
|
+
|
963
|
+
# hash containing widgets by name for retrieval
|
964
|
+
# Useful if one widget refers to second before second created.
|
965
|
+
attr_reader :by_name
|
966
|
+
|
967
|
+
# associated menubar
|
1127
968
|
attr_reader :menu_bar
|
969
|
+
|
1128
970
|
attr_accessor :navigation_policy # :CYCLICAL will cycle around. Needed to move to other tabs
|
1129
971
|
## i need some way to move the cursor by telling the main form what the coords are
|
1130
972
|
##+ perhaps this will work
|
1131
|
-
attr_accessor :parent_form # added 2009-12-28 23:01 BUFFERED - to bubble up row col changes
|
973
|
+
attr_accessor :parent_form # added 2009-12-28 23:01 BUFFERED - to bubble up row col changes
|
974
|
+
|
1132
975
|
# how many rows the component is panning embedded widget by
|
1133
|
-
attr_accessor :rows_panned # HACK added 2009-12-30 16:01 BUFFERED
|
976
|
+
attr_accessor :rows_panned # HACK added 2009-12-30 16:01 BUFFERED USED ??? CLEANUP XXX
|
1134
977
|
# how many cols the component is panning embedded widget by
|
1135
|
-
attr_accessor :cols_panned # HACK added 2009-12-30 16:01 BUFFERED
|
978
|
+
attr_accessor :cols_panned # HACK added 2009-12-30 16:01 BUFFERED USED ??? CLEANUP XXX
|
979
|
+
|
1136
980
|
## next 2 added since tabbedpanes offset needs to be accounted by form inside it.
|
1137
981
|
attr_accessor :add_cols # 2010-01-26 20:23 additional columns due to being placed in some container
|
1138
982
|
attr_accessor :add_rows # 2010-01-26 20:23 additional columns due to being placed in some container
|
983
|
+
|
984
|
+
# name given to form for debugging
|
1139
985
|
attr_accessor :name # for debugging 2010-02-02 20:12
|
1140
|
-
|
1141
|
-
# attr_accessor :allow_alt_digits # catch Alt-1-9 as digit_argument
|
986
|
+
|
1142
987
|
def initialize win, &block
|
1143
988
|
@window = win
|
1144
989
|
@widgets = []
|
1145
990
|
@by_name = {}
|
1146
991
|
@active_index = -1
|
1147
|
-
@padx = @pady = 0
|
1148
992
|
@row = @col = -1
|
1149
|
-
@
|
1150
|
-
@add_cols = @add_rows = 0 # 2010-01-26 20:28
|
993
|
+
@add_cols = @add_rows = 0 # 2010-01-26 20:28 CLEANUP
|
1151
994
|
@handler = {}
|
1152
995
|
@modified = false
|
1153
996
|
@focusable = true
|
1154
997
|
@navigation_policy ||= :CYCLICAL
|
998
|
+
@_events = [:ENTER, :LEAVE]
|
1155
999
|
instance_eval &block if block_given?
|
1156
|
-
@_firsttime = true # internal, don't touch
|
1157
1000
|
## I need some counter so a widget knows it has been panned and can send a correct
|
1158
1001
|
##+ cursor coordinate to system.
|
1159
1002
|
@rows_panned = @cols_panned = 0 # how many rows were panned, typically at a higher level
|
1160
1003
|
@_firsttime = true; # added on 2010-01-02 19:21 to prevent scrolling crash !
|
1161
1004
|
@name ||= ""
|
1005
|
+
|
1006
|
+
# related to emacs kill ring concept for copy-paste
|
1007
|
+
|
1162
1008
|
$kill_ring ||= [] # 2010-03-09 22:42 so textarea and others can copy and paste emacs EMACS
|
1163
1009
|
$kill_ring_pointer = 0 # needs to be incremented with each append, moved with yank-pop
|
1164
1010
|
$append_next_kill = false
|
1165
1011
|
$kill_last_pop_size = 0 # size of last pop which has to be cleared
|
1166
1012
|
|
1167
|
-
#@allow_alt_digits = true ; # capture Alt-1-9 as digit_args. Set to false if you wish to map
|
1168
|
-
# Alt-1-9 to buttons of tabs
|
1169
1013
|
$last_key = 0 # last key pressed @since 1.1.5 (not used yet)
|
1170
1014
|
$current_key = 0 # curr key pressed @since 1.1.5 (so some containers can behave based on whether
|
1171
1015
|
# user tabbed in, or backtabbed in (rmultisplit)
|
1016
|
+
|
1017
|
+
# for storing error message
|
1172
1018
|
$error_message ||= Variable.new ""
|
1173
|
-
|
1019
|
+
|
1020
|
+
# what kind of key-bindings do you want, :vim or :emacs
|
1021
|
+
$key_map ||= :vim ## :emacs or :vim, keys to be defined accordingly. TODO
|
1174
1022
|
end
|
1175
1023
|
##
|
1176
1024
|
# set this menubar as the form's menu bar.
|
@@ -1179,7 +1027,7 @@ module RubyCurses
|
|
1179
1027
|
def set_menu_bar mb
|
1180
1028
|
@menu_bar = mb
|
1181
1029
|
add_widget mb
|
1182
|
-
mb.toggle_key ||=
|
1030
|
+
mb.toggle_key ||= Ncurses.KEY_F2
|
1183
1031
|
if !mb.toggle_key.nil?
|
1184
1032
|
ch = mb.toggle_key
|
1185
1033
|
bind_key(ch) do |_form|
|
@@ -1198,20 +1046,13 @@ module RubyCurses
|
|
1198
1046
|
def add_widget widget
|
1199
1047
|
# this help to access widget by a name
|
1200
1048
|
if widget.respond_to? :name and !widget.name.nil?
|
1049
|
+
$log.debug "NAME #{self} adding a widget #{@widgets.length} .. #{widget.name} "
|
1201
1050
|
@by_name[widget.name] = widget
|
1202
1051
|
end
|
1203
1052
|
|
1204
1053
|
|
1205
1054
|
$log.debug " #{self} adding a widget #{@widgets.length} .. #{widget} "
|
1206
1055
|
@widgets << widget
|
1207
|
-
# add form offsets to widget's external offsets - 2010-02-07 20:22
|
1208
|
-
if widget.is_a? RubyCurses::Widget
|
1209
|
-
if @window # ext seems redundant
|
1210
|
-
widget.ext_col_offset += @window.left # just hope window aint undef!! XXX
|
1211
|
-
$log.debug " #{@name} add widget ( #{widget.name} ) ext_row #{widget.ext_row_offset} += #{@window.top} "
|
1212
|
-
widget.ext_row_offset += @window.top
|
1213
|
-
end
|
1214
|
-
end
|
1215
1056
|
return @widgets.length-1
|
1216
1057
|
end
|
1217
1058
|
alias :add :add_widget
|
@@ -1220,7 +1061,6 @@ module RubyCurses
|
|
1220
1061
|
# added 2008-12-09 12:18
|
1221
1062
|
def remove_widget widget
|
1222
1063
|
if widget.respond_to? :name and !widget.name.nil?
|
1223
|
-
$log.debug "removing from byname: #{widget.name} "
|
1224
1064
|
@by_name.delete(widget.name)
|
1225
1065
|
end
|
1226
1066
|
@widgets.delete widget
|
@@ -1228,7 +1068,7 @@ module RubyCurses
|
|
1228
1068
|
# form repaint
|
1229
1069
|
# to be called at some interval, such as after each keypress.
|
1230
1070
|
def repaint
|
1231
|
-
$log.debug " form repaint:#{self}, #{@name} , r #{@row} c #{@col} "
|
1071
|
+
$log.debug " form repaint:#{self}, #{@name} , r #{@row} c #{@col} " if $log.debug?
|
1232
1072
|
@widgets.each do |f|
|
1233
1073
|
next if f.visible == false # added 2008-12-09 12:17
|
1234
1074
|
f.repaint
|
@@ -1245,23 +1085,19 @@ module RubyCurses
|
|
1245
1085
|
setpos
|
1246
1086
|
# XXX this creates a problem if window is a pad
|
1247
1087
|
# although this does show cursor movement etc.
|
1248
|
-
###
|
1088
|
+
### @window.wrefresh
|
1249
1089
|
if @window.window_type == :WINDOW
|
1250
|
-
|
1090
|
+
#$log.debug " formrepaint #{@name} calling window.wrefresh #{@window} "
|
1251
1091
|
@window.wrefresh
|
1252
1092
|
Ncurses::Panel.update_panels ## added 2010-11-05 00:30 to see if clears the stdscr problems
|
1253
1093
|
else
|
1254
1094
|
$log.warn " XXX formrepaint #{@name} no refresh called 2011-09-19 #{@window} "
|
1255
|
-
#@window.wrefresh # trying FFI 2011-09-19
|
1256
1095
|
end
|
1257
1096
|
end
|
1258
1097
|
##
|
1259
1098
|
# move cursor to where the fields row and col are
|
1260
1099
|
# private
|
1261
1100
|
def setpos r=@row, c=@col
|
1262
|
-
# next 2 lines added, only do cursor if current field doesn't manage it.
|
1263
|
-
#curr = get_current_field
|
1264
|
-
#return if curr.manages_cursor
|
1265
1101
|
$log.debug "setpos : (#{self}) #{r} #{c}"
|
1266
1102
|
## adding just in case things are going out of bounds of a parent and no cursor to be shown
|
1267
1103
|
return if r.nil? or c.nil? # added 2009-12-29 23:28 BUFFERED
|
@@ -1289,7 +1125,7 @@ module RubyCurses
|
|
1289
1125
|
elsif @active_index != ix
|
1290
1126
|
f = @widgets[@active_index]
|
1291
1127
|
begin
|
1292
|
-
#$log.debug "
|
1128
|
+
#$log.debug " select first field, calling on_leave of #{f} #{@active_index} "
|
1293
1129
|
on_leave f
|
1294
1130
|
rescue => err
|
1295
1131
|
$log.error " Caught EXCEPTION req_first_field on_leave #{err}"
|
@@ -1318,16 +1154,18 @@ module RubyCurses
|
|
1318
1154
|
@active_index = nil
|
1319
1155
|
select_prev_field
|
1320
1156
|
end
|
1157
|
+
|
1321
1158
|
# please do not use req_ i will deprecate it soon.
|
1322
1159
|
alias :req_last_field :select_last_field
|
1160
|
+
|
1323
1161
|
## do not override
|
1324
1162
|
# form's trigger, fired when any widget loses focus
|
1325
|
-
# This wont get called in editor components in tables, since they are formless
|
1163
|
+
# This wont get called in editor components in tables, since they are formless
|
1326
1164
|
def on_leave f
|
1327
1165
|
return if f.nil? || !f.focusable # added focusable, else label was firing
|
1328
1166
|
f.state = :NORMAL
|
1329
1167
|
# on leaving update text_variable if defined. Should happen on modified only
|
1330
|
-
# should this not be f.text_var ... f.buffer ?
|
1168
|
+
# should this not be f.text_var ... f.buffer ? 2008-11-25 18:58
|
1331
1169
|
#f.text_variable.value = f.buffer if !f.text_variable.nil? # 2008-12-20 23:36
|
1332
1170
|
f.on_leave if f.respond_to? :on_leave
|
1333
1171
|
fire_handler :LEAVE, f
|
@@ -1337,6 +1175,9 @@ module RubyCurses
|
|
1337
1175
|
f.fire_handler(:CHANGED, f)
|
1338
1176
|
end
|
1339
1177
|
end
|
1178
|
+
# form calls on_enter of each object.
|
1179
|
+
# However, if a multicomponent calls on_enter of a widget, this code will
|
1180
|
+
# not be triggered. The highlighted part
|
1340
1181
|
def on_enter f
|
1341
1182
|
return if f.nil? || !f.focusable # added focusable, else label was firing 2010-09
|
1342
1183
|
f.state = :HIGHLIGHTED
|
@@ -1354,27 +1195,33 @@ module RubyCurses
|
|
1354
1195
|
# puts focus on the given field/widget index
|
1355
1196
|
# XXX if called externally will not run a on_leave of previous field
|
1356
1197
|
def select_field ix0
|
1357
|
-
#return if @widgets.nil? or @widgets.empty? or !@widgets[ix0].focusable
|
1358
1198
|
return if @widgets.nil? or @widgets.empty? or !focusable?(@widgets[ix0])
|
1359
|
-
#$log.debug "
|
1199
|
+
#$log.debug "inside select_field : #{ix0} ai #{@active_index}"
|
1360
1200
|
f = @widgets[ix0]
|
1361
1201
|
if focusable?(f)
|
1362
1202
|
@active_index = ix0
|
1363
1203
|
@row, @col = f.rowcol
|
1364
|
-
|
1365
|
-
@window.wmove @row, @col # added RK FFI 2011-09-7
|
1204
|
+
#$log.debug " WMOVE insdie sele nxt field : ROW #{@row} COL #{@col} "
|
1366
1205
|
on_enter f
|
1206
|
+
@window.wmove @row, @col # added RK FFI 2011-09-7 = setpos
|
1207
|
+
|
1208
|
+
f.set_form_row # added 2011-10-5 so when embedded in another form it can get the cursor
|
1209
|
+
f.set_form_col
|
1210
|
+
|
1367
1211
|
f.curpos = 0
|
1368
1212
|
repaint
|
1369
1213
|
@window.refresh
|
1370
1214
|
else
|
1371
|
-
$log.debug "
|
1215
|
+
$log.debug "inside select field ENABLED FALSE : act #{@active_index} ix0 #{ix0}"
|
1372
1216
|
end
|
1373
1217
|
end
|
1374
1218
|
##
|
1375
1219
|
# run validate_field on a field, usually whatevers current
|
1376
1220
|
# before transferring control
|
1377
1221
|
# We should try to automate this so developer does not have to remember to call it.
|
1222
|
+
# # @param field object
|
1223
|
+
# @return [0, -1] for success or failure
|
1224
|
+
# NOTE : catches exception and sets $error_message, check if -1
|
1378
1225
|
def validate_field f=@widgets[@active_index]
|
1379
1226
|
begin
|
1380
1227
|
on_leave f
|
@@ -1393,21 +1240,25 @@ module RubyCurses
|
|
1393
1240
|
# in which case returns :NO_NEXT_FIELD.
|
1394
1241
|
# FIXME: in the beginning it comes in as -1 and does an on_leave of last field
|
1395
1242
|
def select_next_field
|
1396
|
-
return if @widgets.nil? or @widgets.empty?
|
1397
|
-
|
1243
|
+
return :UNHANDLED if @widgets.nil? or @widgets.empty?
|
1244
|
+
#$log.debug "insdie sele nxt field : #{@active_index} WL:#{@widgets.length}"
|
1398
1245
|
if @active_index.nil? || @active_index == -1 # needs to be tested out A LOT
|
1399
1246
|
@active_index = -1
|
1400
1247
|
else
|
1401
1248
|
f = @widgets[@active_index]
|
1402
1249
|
begin
|
1403
1250
|
on_leave f
|
1251
|
+
rescue FieldValidationException => err # added 2011-10-2 v1.3.1 so we can rollback
|
1252
|
+
$log.error "select_next_field: caught EXCEPTION #{err}"
|
1253
|
+
$error_message.value = "#{err}"
|
1254
|
+
raise err
|
1404
1255
|
rescue => err
|
1405
1256
|
$log.error "select_next_field: caught EXCEPTION #{err}"
|
1406
1257
|
$log.error(err.backtrace.join("\n"))
|
1407
1258
|
# $error_message = "#{err}" # changed 2010
|
1408
1259
|
$error_message.value = "#{err}"
|
1409
1260
|
Ncurses.beep
|
1410
|
-
return
|
1261
|
+
return 0
|
1411
1262
|
end
|
1412
1263
|
end
|
1413
1264
|
index = @active_index + 1
|
@@ -1416,7 +1267,7 @@ module RubyCurses
|
|
1416
1267
|
#$log.debug "insdie sele nxt field : i #{i} #{index} WL:#{@widgets.length}, field #{f}"
|
1417
1268
|
if focusable?(f)
|
1418
1269
|
select_field i
|
1419
|
-
return
|
1270
|
+
return 0
|
1420
1271
|
end
|
1421
1272
|
end
|
1422
1273
|
#req_first_field
|
@@ -1430,11 +1281,11 @@ module RubyCurses
|
|
1430
1281
|
f = @widgets[i]
|
1431
1282
|
if focusable?(f)
|
1432
1283
|
select_field i
|
1433
|
-
return
|
1284
|
+
return 0
|
1434
1285
|
end
|
1435
1286
|
end
|
1436
1287
|
end
|
1437
|
-
$log.debug "
|
1288
|
+
$log.debug "inside sele nxt field : NO NEXT #{@active_index} WL:#{@widgets.length}"
|
1438
1289
|
return :NO_NEXT_FIELD
|
1439
1290
|
end
|
1440
1291
|
##
|
@@ -1444,7 +1295,7 @@ module RubyCurses
|
|
1444
1295
|
# @return [nil, :NO_PREV_FIELD] nil if cyclical and it finds a field
|
1445
1296
|
# if not cyclical, and no more fields then :NO_PREV_FIELD
|
1446
1297
|
def select_prev_field
|
1447
|
-
return if @widgets.nil? or @widgets.empty?
|
1298
|
+
return :UNHANDLED if @widgets.nil? or @widgets.empty?
|
1448
1299
|
#$log.debug "insdie sele prev field : #{@active_index} WL:#{@widgets.length}"
|
1449
1300
|
if @active_index.nil?
|
1450
1301
|
@active_index = @widgets.length
|
@@ -1469,7 +1320,7 @@ module RubyCurses
|
|
1469
1320
|
return
|
1470
1321
|
end
|
1471
1322
|
end
|
1472
|
-
|
1323
|
+
|
1473
1324
|
## added on 2008-12-14 18:27 so we can skip to another form/tab
|
1474
1325
|
# 2009-01-08 12:24 no recursion, can be stack overflows if no focusable field
|
1475
1326
|
if @navigation_policy == :CYCLICAL
|
@@ -1496,12 +1347,7 @@ module RubyCurses
|
|
1496
1347
|
@window.wmove @row, @col
|
1497
1348
|
## 2010-01-30 23:45 exchange calling parent with calling this forms setrow
|
1498
1349
|
# since in tabbedpane with table i am not gietting this forms offset.
|
1499
|
-
|
1500
|
-
# added on 2010-01-05 22:26 so component widgets like scrollpane can get the cursor
|
1501
|
-
#if !@parent_form.nil? and @parent_form != self #@form
|
1502
|
-
#$log.debug " #{@name} addcol calling parents setrowcol #{row}, #{col}: #{@parent_form} "
|
1503
|
-
#@parent_form.setrowcol nil, col
|
1504
|
-
#end
|
1350
|
+
setrowcol nil, col
|
1505
1351
|
end
|
1506
1352
|
##
|
1507
1353
|
# move cursor by given rows and columns, can be negative.
|
@@ -1527,9 +1373,9 @@ module RubyCurses
|
|
1527
1373
|
@col = c unless c.nil?
|
1528
1374
|
r += @add_rows unless r.nil? # 2010-01-26 20:31
|
1529
1375
|
c += @add_cols unless c.nil? # 2010-01-26 20:31
|
1530
|
-
$log.debug " addcols #{@add_cols} addrow #{@add_rows} : #{self} "
|
1376
|
+
$log.debug " addcols #{@add_cols} addrow #{@add_rows} : #{self} r = #{r} , c = #{c} "
|
1531
1377
|
if !@parent_form.nil? and @parent_form != self
|
1532
|
-
$log.debug " (#{@name}) calling parents setrowcol #{r}, #{c} : pare: #{@parent_form}; self: #{self}, #{self.class} "
|
1378
|
+
$log.debug " (#{@name}) addrow calling parents setrowcol #{r}, #{c} : pare: #{@parent_form}; self: #{self}, #{self.class} "
|
1533
1379
|
#r += @parent_form.window.top unless r.nil?
|
1534
1380
|
#c += @parent_form.window.left unless c.nil?
|
1535
1381
|
@parent_form.setrowcol r, c
|
@@ -1542,14 +1388,17 @@ module RubyCurses
|
|
1542
1388
|
# after form handles basic keys, it gives unhandled key to current field, if current field returns
|
1543
1389
|
# unhandled, then it checks this map.
|
1544
1390
|
# Please update widget with any changes here. TODO: match regexes as in mapper
|
1391
|
+
|
1545
1392
|
def process_key keycode, object
|
1546
1393
|
return _process_key keycode, object, @window
|
1547
1394
|
end
|
1395
|
+
|
1548
1396
|
# Defines how user can give numeric args to a command even in edit mode
|
1549
1397
|
# User either presses universal_argument (C-u) which generates a series of 4 16 64.
|
1550
1398
|
# Or he presses C-u and then types some numbers. Followed by the action.
|
1551
1399
|
# @returns [0, :UNHANDLED] :UNHANDLED implies that last keystroke is still to evaluated
|
1552
1400
|
# by system. ) implies only numeric args were obtained. This method updates $multiplier
|
1401
|
+
|
1553
1402
|
def universal_argument
|
1554
1403
|
$multiplier = ( ($multiplier.nil? || $multiplier == 0) ? 4 : $multiplier *= 4)
|
1555
1404
|
$log.debug " inside UNIV MULT0: #{$multiplier} "
|
@@ -1583,6 +1432,7 @@ module RubyCurses
|
|
1583
1432
|
end
|
1584
1433
|
return 0
|
1585
1434
|
end
|
1435
|
+
|
1586
1436
|
def digit_argument ch
|
1587
1437
|
$multiplier = ch - ?\M-0.getbyte(0)
|
1588
1438
|
$log.debug " inside UNIV MULT 0 #{$multiplier} "
|
@@ -1612,11 +1462,16 @@ module RubyCurses
|
|
1612
1462
|
end
|
1613
1463
|
return 0
|
1614
1464
|
end
|
1465
|
+
|
1615
1466
|
## forms handle keys
|
1616
1467
|
# mainly traps tab and backtab to navigate between widgets.
|
1617
1468
|
# I know some widgets will want to use tab, e.g edit boxes for entering a tab
|
1618
1469
|
# or for completion.
|
1470
|
+
# @throws FieldValidationException
|
1471
|
+
# NOTE : please rescue exceptions when you use this in your main loop and alert() user
|
1472
|
+
#
|
1619
1473
|
def handle_key(ch)
|
1474
|
+
handled = :UNHANDLED # 2011-10-4
|
1620
1475
|
if ch == ?\C-u.getbyte(0)
|
1621
1476
|
ret = universal_argument
|
1622
1477
|
$log.debug "C-u FORM set MULT to #{$multiplier}, ret = #{ret} "
|
@@ -1646,11 +1501,14 @@ module RubyCurses
|
|
1646
1501
|
Ncurses.endwin
|
1647
1502
|
@window.wrefresh
|
1648
1503
|
else
|
1649
|
-
keycode = keycode_tos(ch)
|
1650
|
-
$log.debug " form HK #{ch} #{self}, #{@name}, #{keycode} "
|
1651
1504
|
field = get_current_field
|
1505
|
+
if $log.debug?
|
1506
|
+
keycode = keycode_tos(ch)
|
1507
|
+
$log.debug " form HK #{ch} #{self}, #{@name}, #{keycode}, field: giving to: #{field}, #{field.name} "
|
1508
|
+
end
|
1652
1509
|
handled = :UNHANDLED
|
1653
1510
|
handled = field.handle_key ch unless field.nil? # no field focussable
|
1511
|
+
$log.debug "handled inside Form #{ch} from #{field} got #{handled} "
|
1654
1512
|
# some widgets like textarea and list handle up and down
|
1655
1513
|
if handled == :UNHANDLED or handled == -1 or field.nil?
|
1656
1514
|
case ch
|
@@ -1662,36 +1520,24 @@ module RubyCurses
|
|
1662
1520
|
ret = select_prev_field
|
1663
1521
|
return ret if ret == :NO_PREV_FIELD
|
1664
1522
|
when FFI::NCurses::KEY_UP
|
1665
|
-
select_prev_field
|
1523
|
+
ret = select_prev_field
|
1524
|
+
return ret if ret == :NO_PREV_FIELD
|
1666
1525
|
when FFI::NCurses::KEY_DOWN
|
1667
|
-
select_next_field
|
1668
|
-
|
1669
|
-
### trying out these for fuun and testing splitpane 2010-01-10 20:32
|
1670
|
-
#$log.debug " field #{field.name} was #{field.width} "
|
1671
|
-
#field.width += 1
|
1672
|
-
#$log.debug " field #{field.name} now #{field.width} "
|
1673
|
-
#field.repaint_all
|
1674
|
-
#when ?\M-H.getbyte(0), ?\M-<.getbyte(0)
|
1675
|
-
#field.width -= 1
|
1676
|
-
#$log.debug " field #{field.name} now #{field.width} "
|
1677
|
-
#field.repaint_all
|
1678
|
-
#when ?\M-J.getbyte(0)
|
1679
|
-
#field.height += 1
|
1680
|
-
#when ?\M-K.getbyte(0)
|
1681
|
-
#field.height -= 1
|
1526
|
+
ret = select_next_field
|
1527
|
+
return ret if ret == :NO_NEXT_FIELD
|
1682
1528
|
else
|
1683
|
-
#$log.debug "
|
1529
|
+
#$log.debug " before calling process_key in form #{ch} " if $log.debug?
|
1684
1530
|
ret = process_key ch, self
|
1685
1531
|
$log.debug "FORM process_key #{ch} got ret #{ret} in #{self} "
|
1686
1532
|
return :UNHANDLED if ret == :UNHANDLED
|
1687
1533
|
end
|
1534
|
+
elsif handled == :NO_NEXT_FIELD || handled == :NO_PREV_FIELD # 2011-10-4
|
1535
|
+
return handled
|
1688
1536
|
end
|
1689
1537
|
end
|
1690
1538
|
$log.debug " form before repaint #{self} , #{@name}, ret #{ret}"
|
1691
1539
|
repaint
|
1692
1540
|
$last_key = ch
|
1693
|
-
#return handled # TRYNG 2010-03-01 23:30 since TP returns NO_NEXT_FIELD sometimes
|
1694
|
-
#$multiplier = 0
|
1695
1541
|
end
|
1696
1542
|
##
|
1697
1543
|
# test program to dump data onto log
|
@@ -1701,8 +1547,8 @@ module RubyCurses
|
|
1701
1547
|
# or editable as filters. I just dump everything?
|
1702
1548
|
# What's more, currently getvalue has been used by paint to return what needs to be displayed -
|
1703
1549
|
# at least by label and button.
|
1704
|
-
def
|
1705
|
-
$log.debug " DUMPING DATA "
|
1550
|
+
def DEPRECATED_dump_data # CLEAN
|
1551
|
+
$log.debug "DEPRECATED DUMPING DATA "
|
1706
1552
|
@widgets.each do |w|
|
1707
1553
|
# we need checkbox and radio button values
|
1708
1554
|
#next if w.is_a? RubyCurses::Button or w.is_a? RubyCurses::Label
|
@@ -1717,7 +1563,7 @@ module RubyCurses
|
|
1717
1563
|
$log.debug " END DUMPING DATA "
|
1718
1564
|
end
|
1719
1565
|
##
|
1720
|
-
# trying out for splitpane and others who have a sub-form
|
1566
|
+
# trying out for splitpane and others who have a sub-form. TabbedPane uses
|
1721
1567
|
def set_parent_buffer b
|
1722
1568
|
@parent_buffer = b
|
1723
1569
|
end
|
@@ -1757,15 +1603,6 @@ module RubyCurses
|
|
1757
1603
|
col = w.col
|
1758
1604
|
return row, col
|
1759
1605
|
end
|
1760
|
-
## so if we come back from ncurses cooked mode we can repaint.
|
1761
|
-
# not required, we have to stop and restart ncurses.
|
1762
|
-
#def reset_all
|
1763
|
-
#$log.debug " form reset:#{self}, #{@name} , r #{@row} c #{@col} "
|
1764
|
-
#@widgets.each do |f|
|
1765
|
-
#next if f.visible == false # added 2008-12-09 12:17
|
1766
|
-
#f.repaint_all()
|
1767
|
-
#end
|
1768
|
-
#end
|
1769
1606
|
|
1770
1607
|
## ADD HERE FORM
|
1771
1608
|
end
|
@@ -1807,72 +1644,68 @@ module RubyCurses
|
|
1807
1644
|
dsl_accessor :default # TODO use set_buffer for now
|
1808
1645
|
dsl_accessor :values # validate against provided list
|
1809
1646
|
dsl_accessor :valid_regex # validate against regular expression
|
1647
|
+
dsl_accessor :valid_range # validate against numeric range # 2011-09-29 V1.3.1
|
1810
1648
|
|
1811
|
-
dsl_accessor :chars_allowed
|
1812
|
-
dsl_accessor :display_length
|
1813
|
-
|
1814
|
-
|
1815
|
-
dsl_accessor :show
|
1816
|
-
dsl_accessor :null_allowed
|
1649
|
+
dsl_accessor :chars_allowed # regex, what characters to allow, will ignore all else
|
1650
|
+
dsl_accessor :display_length # how much to display
|
1651
|
+
#dsl_property :bgcolor # background color 'red' 'black' 'cyan' etc # 2011-09-29 IN WIDGET
|
1652
|
+
#dsl_property :color # foreground colors from Ncurses COLOR_xxxx
|
1653
|
+
dsl_accessor :show # what charactr to show for each char entered (password field)
|
1654
|
+
dsl_accessor :null_allowed # allow nulls, don't validate if null # added 2008-12-22 12:38
|
1817
1655
|
|
1818
1656
|
# any new widget that has editable should have modified also
|
1819
1657
|
dsl_accessor :editable # allow editing
|
1820
1658
|
|
1821
1659
|
attr_reader :form
|
1822
|
-
attr_reader :handler
|
1823
|
-
attr_reader :type
|
1824
|
-
#attr_reader :curpos
|
1825
|
-
attr_accessor :datatype
|
1826
|
-
attr_reader :original_value
|
1660
|
+
attr_reader :handler # event handler
|
1661
|
+
attr_reader :type # datatype of field, currently only sets chars_allowed
|
1662
|
+
#attr_reader :curpos # cursor position in buffer current, in WIDGET
|
1663
|
+
attr_accessor :datatype # crrently set during set_buffer
|
1664
|
+
attr_reader :original_value # value on entering field
|
1827
1665
|
attr_accessor :overwrite_mode # true or false INSERT OVERWRITE MODE
|
1828
1666
|
|
1829
1667
|
def initialize form, config={}, &block
|
1830
1668
|
@form = form
|
1831
1669
|
@buffer = String.new
|
1832
1670
|
#@type=config.fetch("type", :varchar)
|
1833
|
-
# 2010-10-19 12:26 slight change, hopefully won't bomb
|
1834
1671
|
@display_length = 20
|
1835
1672
|
@maxlen = @display_length
|
1836
1673
|
@row = 0
|
1837
1674
|
@col = 0
|
1838
1675
|
@bgcolor = $def_bg_color
|
1839
1676
|
@color = $def_fg_color
|
1840
|
-
#@name = config.fetch("name", nil)
|
1841
1677
|
@editable = true
|
1842
1678
|
@focusable = true
|
1843
|
-
# are these redundant ?
|
1844
|
-
#@display_length = config.fetch("display_length", 20)
|
1845
|
-
#@maxlen=config.fetch("maxlen", @display_length)
|
1846
|
-
#@row = config.fetch("row", 0)
|
1847
|
-
#@col = config.fetch("col", 0)
|
1848
|
-
#@bgcolor = config.fetch("bgcolor", $def_bg_color)
|
1849
|
-
#@color = config.fetch("color", $def_fg_color)
|
1850
|
-
#@name = config.fetch("name", nil)
|
1851
|
-
#@editable = config.fetch("editable", true)
|
1852
|
-
#@focusable = config.fetch("focusable", true)
|
1853
1679
|
@event_args = {} # arguments passed at time of binding, to use when firing event
|
1854
1680
|
map_keys
|
1855
1681
|
init_vars
|
1856
|
-
|
1682
|
+
@_events ||= []
|
1857
1683
|
@_events.push(:CHANGE)
|
1684
|
+
super
|
1858
1685
|
end
|
1859
1686
|
def init_vars
|
1860
|
-
@pcol = 0
|
1687
|
+
@pcol = 0 # needed for horiz scrolling
|
1861
1688
|
@curpos = 0 # current cursor position in buffer
|
1862
1689
|
@modified = false
|
1863
1690
|
@repaint_required = true
|
1864
1691
|
end
|
1692
|
+
|
1693
|
+
#
|
1694
|
+
# Set Variable as value.
|
1695
|
+
# This allows using Field as a proxy
|
1696
|
+
# @param [Variable] variable containing text value
|
1697
|
+
#
|
1865
1698
|
def text_variable tv
|
1866
1699
|
@text_variable = tv
|
1867
1700
|
set_buffer tv.value
|
1868
1701
|
end
|
1869
1702
|
##
|
1870
1703
|
# define a datatype, currently only influences chars allowed
|
1871
|
-
# integer and float. what about allowing a minus sign?
|
1704
|
+
# integer and float. what about allowing a minus sign?
|
1872
1705
|
# 2010-09-10 20:59 changed string to symbol
|
1873
1706
|
def type dtype
|
1874
1707
|
return if !@chars_allowed.nil?
|
1875
|
-
case dtype.to_s.downcase
|
1708
|
+
case dtype.to_s.downcase.to_sym # missing to_sym would have always failed due to to_s 2011-09-30 1.3.1
|
1876
1709
|
when :integer
|
1877
1710
|
@chars_allowed = /\d/
|
1878
1711
|
when :numeric, :float
|
@@ -1881,8 +1714,12 @@ module RubyCurses
|
|
1881
1714
|
@chars_allowed = /[a-zA-Z]/
|
1882
1715
|
when :alnum
|
1883
1716
|
@chars_allowed = /[a-zA-Z0-9]/
|
1717
|
+
else
|
1718
|
+
raise "type: invalid datatype specified. Use :integer, :numeric, :float, :alpha, :alnum "
|
1884
1719
|
end
|
1885
1720
|
end
|
1721
|
+
|
1722
|
+
#
|
1886
1723
|
# add a char to field, and validate
|
1887
1724
|
# NOTE: this should return self for chaining operations and throw an exception
|
1888
1725
|
# if disabled or exceeding size
|
@@ -1941,8 +1778,18 @@ module RubyCurses
|
|
1941
1778
|
#fire_handler :CHANGE, self # 2008-12-09 14:51
|
1942
1779
|
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos, self, :DELETE, 0, char) # 2010-09-11 13:01
|
1943
1780
|
end
|
1781
|
+
#
|
1782
|
+
# silently restores value without firing handlers, use if exception and you want old value
|
1783
|
+
# @since 1.4.0 2011-10-2
|
1784
|
+
def restore_original_value
|
1785
|
+
@buffer = @original_value.dup
|
1786
|
+
#@curpos = 0 # this would require restting setformcol
|
1787
|
+
@repaint_required = true
|
1788
|
+
end
|
1944
1789
|
##
|
1945
1790
|
# should this do a dup ?? YES
|
1791
|
+
# set value of Field
|
1792
|
+
# fires CHANGE handler
|
1946
1793
|
def set_buffer value
|
1947
1794
|
@repaint_required = true
|
1948
1795
|
@datatype = value.class
|
@@ -1950,9 +1797,10 @@ module RubyCurses
|
|
1950
1797
|
@delete_buffer = @buffer.dup
|
1951
1798
|
@buffer = value.to_s.dup
|
1952
1799
|
@curpos = 0
|
1953
|
-
#
|
1800
|
+
# hope @delete_buffer is not overwritten
|
1954
1801
|
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos, self, :DELETE, 0, @delete_buffer) # 2010-09-11 13:01
|
1955
1802
|
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos, self, :INSERT, 0, @buffer) # 2010-09-11 13:01
|
1803
|
+
self # 2011-10-2
|
1956
1804
|
end
|
1957
1805
|
# converts back into original type
|
1958
1806
|
# changed to convert on 2009-01-06 23:39
|
@@ -1974,19 +1822,19 @@ module RubyCurses
|
|
1974
1822
|
# Typically one passes a Label, but now we can pass just a String, a label
|
1975
1823
|
# is created
|
1976
1824
|
# @param [Label, String] label object to be associated with this field
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
1825
|
+
def set_label label
|
1826
|
+
# added case for user just using a string
|
1827
|
+
case label
|
1828
|
+
when String
|
1829
|
+
# what if no form at this point
|
1830
|
+
label = Label.new @form, {:text => label}
|
1831
|
+
end
|
1832
|
+
@label = label
|
1833
|
+
label.row @row if label.row == -1
|
1834
|
+
label.col @col-(label.name.length+1) if label.col == -1
|
1835
|
+
label.label_for(self)
|
1836
|
+
label
|
1837
|
+
end
|
1990
1838
|
|
1991
1839
|
## Note that some older widgets like Field repaint every time the form.repaint
|
1992
1840
|
##+ is called, whether updated or not. I can't remember why this is, but
|
@@ -2009,15 +1857,10 @@ module RubyCurses
|
|
2009
1857
|
end
|
2010
1858
|
#printval = printval[0..display_length-1] if printval.length > display_length
|
2011
1859
|
acolor = @color_pair || get_color($datacolor, @color, @bgcolor)
|
2012
|
-
|
2013
|
-
#acolor = ColorMap.get_color(@color, @bgcolor)
|
2014
|
-
#else
|
2015
|
-
#acolor = $datacolor
|
2016
|
-
#end
|
2017
|
-
@graphic = @form.window if @graphic.nil? ## cell editor listbox hack XXX fix in correct place
|
1860
|
+
@graphic = @form.window if @graphic.nil? ## cell editor listbox hack
|
2018
1861
|
#$log.debug " Field g:#{@graphic}. r,c,displen:#{@row}, #{@col}, #{@display_length} "
|
2019
1862
|
@graphic.printstring row, col, sprintf("%-*s", display_length, printval), acolor, @attr
|
2020
|
-
@repaint_required = false
|
1863
|
+
@repaint_required = false
|
2021
1864
|
end
|
2022
1865
|
def set_focusable(tf)
|
2023
1866
|
@focusable = tf
|
@@ -2033,50 +1876,22 @@ module RubyCurses
|
|
2033
1876
|
bind_key(?\C-e){ cursor_end }
|
2034
1877
|
bind_key(?\C-k){ delete_eol }
|
2035
1878
|
bind_key(?\C-_){ undo_delete_eol }
|
2036
|
-
bind_key(27){ set_buffer @original_value }
|
1879
|
+
#bind_key(27){ set_buffer @original_value }
|
1880
|
+
bind_key(?\C-g){ set_buffer @original_value } # 2011-09-29 V1.3.1 ESC did not work
|
2037
1881
|
@keys_mapped = true
|
2038
1882
|
end
|
2039
1883
|
|
2040
1884
|
# field
|
2041
|
-
#
|
1885
|
+
#
|
2042
1886
|
def handle_key ch
|
2043
|
-
@repaint_required = true
|
1887
|
+
@repaint_required = true
|
2044
1888
|
#map_keys unless @keys_mapped # moved to init
|
2045
1889
|
case ch
|
2046
|
-
#when KEY_LEFT
|
2047
|
-
#cursor_backward
|
2048
|
-
#when KEY_RIGHT
|
2049
|
-
#cursor_forward
|
2050
|
-
#when KEY_BACKSPACE, 127
|
2051
|
-
#delete_prev_char if @editable
|
2052
|
-
#when KEY_UP
|
2053
|
-
# $log.debug " FIELD GOT KEY_UP, NOW IGNORING 2009-01-16 17:52 "
|
2054
|
-
#@form.select_prev_field # in a table this should not happen 2009-01-16 17:47
|
2055
|
-
# return :UNHANDLED
|
2056
|
-
#when KEY_DOWN
|
2057
|
-
# $log.debug " FIELD GOT KEY_DOWN, NOW IGNORING 2009-01-16 17:52 "
|
2058
|
-
#@form.select_next_field # in a table this should not happen 2009-01-16 17:47
|
2059
|
-
# return :UNHANDLED
|
2060
|
-
# user cannot bind here or on form if i eat up
|
2061
|
-
#when KEY_ENTER, 10, 13
|
2062
|
-
#if respond_to? :fire
|
2063
|
-
#fire
|
2064
|
-
#end
|
2065
|
-
#when 330
|
2066
|
-
#delete_curr_char if @editable
|
2067
|
-
#when ?\C-a.getbyte(0)
|
2068
|
-
#cursor_home
|
2069
|
-
#when ?\C-e.getbyte(0)
|
2070
|
-
#cursor_end
|
2071
|
-
#when ?\C-k.getbyte(0)
|
2072
|
-
#delete_eol if @editable
|
2073
|
-
#when ?\C-_.getbyte(0) # changed on 2010-02-26 14:44 so C-u can be used as numeric arg
|
2074
|
-
#undo_delete_eol
|
2075
1890
|
when 32..126
|
2076
1891
|
#$log.debug("FIELD: ch #{ch} ,at #{@curpos}, buffer:[#{@buffer}] bl: #{@buffer.to_s.length}")
|
2077
1892
|
putc ch
|
2078
|
-
|
2079
|
-
|
1893
|
+
when 27 # cannot bind it
|
1894
|
+
set_buffer @original_value
|
2080
1895
|
else
|
2081
1896
|
ret = super
|
2082
1897
|
return ret
|
@@ -2099,15 +1914,15 @@ module RubyCurses
|
|
2099
1914
|
##
|
2100
1915
|
# goto end of field, "end" is a keyword so could not use it.
|
2101
1916
|
def cursor_end
|
2102
|
-
|
2103
|
-
|
2104
|
-
|
2105
|
-
|
2106
|
-
|
2107
|
-
|
2108
|
-
|
2109
|
-
|
2110
|
-
|
1917
|
+
blen = @buffer.rstrip.length
|
1918
|
+
if blen < @display_length
|
1919
|
+
set_form_col blen
|
1920
|
+
else
|
1921
|
+
@pcol = blen-@display_length
|
1922
|
+
set_form_col @display_length-1
|
1923
|
+
end
|
1924
|
+
@curpos = blen # HACK
|
1925
|
+
# $log.debug " crusor END cp:#{@curpos} pcol:#{@pcol} b.l:#{@buffer.length} d_l:#{@display_length} fc:#{@form.col}"
|
2111
1926
|
#set_form_col @buffer.length
|
2112
1927
|
end
|
2113
1928
|
def delete_eol
|
@@ -2194,8 +2009,13 @@ module RubyCurses
|
|
2194
2009
|
valid = @valid_regex.match(val.to_s)
|
2195
2010
|
raise FieldValidationException, "Field not matching regex #{@valid_regex}" unless valid
|
2196
2011
|
end
|
2012
|
+
# added valid_range for numerics 2011-09-29
|
2013
|
+
if !@valid_range.nil?
|
2014
|
+
valid = @valid_range.include?(val.to_i)
|
2015
|
+
raise FieldValidationException, "Field not matching range #{@valid_range}" unless valid
|
2016
|
+
end
|
2197
2017
|
end
|
2198
|
-
# here is where we should set the forms modified to true - 2009-01
|
2018
|
+
# here is where we should set the forms modified to true - 2009-01
|
2199
2019
|
if modified?
|
2200
2020
|
set_modified true
|
2201
2021
|
end
|
@@ -2205,8 +2025,11 @@ module RubyCurses
|
|
2205
2025
|
end
|
2206
2026
|
## save original value on enter, so we can check for modified.
|
2207
2027
|
# 2009-01-18 12:25
|
2028
|
+
# 2011-10-9 I have changed to take @buffer since getvalue returns a datatype
|
2029
|
+
# and this causes a crash in set_original on cursor forward.
|
2208
2030
|
def on_enter
|
2209
|
-
|
2031
|
+
#@original_value = getvalue.dup rescue getvalue
|
2032
|
+
@original_value = @buffer.dup # getvalue.dup rescue getvalue
|
2210
2033
|
super
|
2211
2034
|
end
|
2212
2035
|
##
|
@@ -2238,6 +2061,7 @@ module RubyCurses
|
|
2238
2061
|
# will update the Variable. A variable can be used to link a field with a label or
|
2239
2062
|
# some other widget.
|
2240
2063
|
# This is the new version of Variable. Deleting old version on 2009-01-17 12:04
|
2064
|
+
|
2241
2065
|
class Variable
|
2242
2066
|
|
2243
2067
|
def initialize value=""
|
@@ -2246,6 +2070,7 @@ module RubyCurses
|
|
2246
2070
|
@value = value
|
2247
2071
|
@klass = value.class.to_s
|
2248
2072
|
end
|
2073
|
+
|
2249
2074
|
##
|
2250
2075
|
# This is to ensure that change handlers for all dependent objects are called
|
2251
2076
|
# so they are updated. This is called from text_variable property of some widgets. If you
|
@@ -2361,6 +2186,8 @@ module RubyCurses
|
|
2361
2186
|
@name ||= @text
|
2362
2187
|
@repaint_required = true
|
2363
2188
|
end
|
2189
|
+
#
|
2190
|
+
# get the value for the label
|
2364
2191
|
def getvalue
|
2365
2192
|
@text_variable && @text_variable.value || @text
|
2366
2193
|
end
|
@@ -2391,49 +2218,49 @@ module RubyCurses
|
|
2391
2218
|
# XXX need to move wrapping etc up and done once.
|
2392
2219
|
def repaint
|
2393
2220
|
return unless @repaint_required
|
2394
|
-
|
2395
|
-
|
2396
|
-
|
2397
|
-
|
2398
|
-
|
2399
|
-
|
2400
|
-
|
2401
|
-
|
2402
|
-
|
2403
|
-
|
2404
|
-
|
2405
|
-
end
|
2406
|
-
end
|
2407
|
-
lablist << value
|
2408
|
-
end
|
2409
|
-
len = @display_length || value.length
|
2410
|
-
acolor = get_color $datacolor
|
2411
|
-
#$log.debug "label :#{@text}, #{value}, #{r}, #{c} col= #{@color}, #{@bgcolor} acolor #{acolor} j:#{@justify} dlL: #{@display_length} "
|
2412
|
-
firstrow = r
|
2413
|
-
_height = @height || 1
|
2414
|
-
str = @justify.to_sym == :right ? "%*s" : "%-*s" # added 2008-12-22 19:05
|
2415
|
-
# loop added for labels that are wrapped.
|
2416
|
-
# TODO clear separately since value can change in status like labels
|
2417
|
-
#$log.debug " RWID 1595 #{self.class} value: #{value} form: #{form} "
|
2418
|
-
@graphic = @form.window if @graphic.nil? ## HACK messagebox givig this in repaint, 423 not working ??
|
2419
|
-
0.upto(_height-1) { |i|
|
2420
|
-
@graphic.printstring r+i, c, " " * len , acolor,@attr
|
2421
|
-
}
|
2422
|
-
lablist.each_with_index do |_value, ix|
|
2423
|
-
break if ix >= _height
|
2424
|
-
if @justify.to_sym == :center
|
2425
|
-
padding = (@display_length - _value.length)/2
|
2426
|
-
_value = " "*padding + _value + " "*padding # so its cleared if we change it midway
|
2221
|
+
r,c = rowcol
|
2222
|
+
# value often nil so putting blank, but usually some application error
|
2223
|
+
value = getvalue_for_paint || ""
|
2224
|
+
lablist = []
|
2225
|
+
if @height && @height > 1
|
2226
|
+
lablist = wrap_text(value, @display_length).split("\n")
|
2227
|
+
else
|
2228
|
+
# ensure we do not exceed
|
2229
|
+
if !@display_length.nil?
|
2230
|
+
if value.length > @display_length
|
2231
|
+
value = value[0..@display_length-1]
|
2427
2232
|
end
|
2428
|
-
@graphic.printstring r, c, str % [len, _value], acolor,@attr
|
2429
|
-
r += 1
|
2430
2233
|
end
|
2431
|
-
|
2432
|
-
|
2433
|
-
|
2234
|
+
lablist << value
|
2235
|
+
end
|
2236
|
+
len = @display_length || value.length
|
2237
|
+
acolor = get_color $datacolor
|
2238
|
+
#$log.debug "label :#{@text}, #{value}, #{r}, #{c} col= #{@color}, #{@bgcolor} acolor #{acolor} j:#{@justify} dlL: #{@display_length} "
|
2239
|
+
firstrow = r
|
2240
|
+
_height = @height || 1
|
2241
|
+
str = @justify.to_sym == :right ? "%*s" : "%-*s" # added 2008-12-22 19:05
|
2242
|
+
# loop added for labels that are wrapped.
|
2243
|
+
# TODO clear separately since value can change in status like labels
|
2244
|
+
|
2245
|
+
@graphic = @form.window if @graphic.nil? ## HACK messagebox givig this in repaint, 423 not working ??
|
2246
|
+
0.upto(_height-1) { |i|
|
2247
|
+
@graphic.printstring r+i, c, " " * len , acolor,@attr
|
2248
|
+
}
|
2249
|
+
lablist.each_with_index do |_value, ix|
|
2250
|
+
break if ix >= _height
|
2251
|
+
if @justify.to_sym == :center
|
2252
|
+
padding = (@display_length - _value.length)/2
|
2253
|
+
_value = " "*padding + _value + " "*padding # so its cleared if we change it midway
|
2434
2254
|
end
|
2435
|
-
|
2436
|
-
|
2255
|
+
@graphic.printstring r, c, str % [len, _value], acolor,@attr
|
2256
|
+
r += 1
|
2257
|
+
end
|
2258
|
+
if !@mnemonic.nil?
|
2259
|
+
ulindex = value.index(@mnemonic) || value.index(@mnemonic.swapcase)
|
2260
|
+
@graphic.mvchgat(y=firstrow, x=c+ulindex, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, acolor, nil)
|
2261
|
+
end
|
2262
|
+
#@form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, color, nil)
|
2263
|
+
@repaint_required = false
|
2437
2264
|
end
|
2438
2265
|
# ADD HERE LABEL
|
2439
2266
|
end
|
@@ -2452,12 +2279,13 @@ module RubyCurses
|
|
2452
2279
|
@editable = false
|
2453
2280
|
@handler={} # event handler
|
2454
2281
|
@event_args ||= {}
|
2282
|
+
@_events ||= []
|
2283
|
+
@_events.push :PRESS
|
2455
2284
|
super
|
2456
2285
|
@bgcolor ||= $datacolor
|
2457
2286
|
@color ||= $datacolor
|
2458
2287
|
@surround_chars ||= ['[ ', ' ]']
|
2459
2288
|
@col_offset = @surround_chars[0].length
|
2460
|
-
@_events.push :PRESS
|
2461
2289
|
end
|
2462
2290
|
##
|
2463
2291
|
# set button based on Action
|
@@ -2483,6 +2311,7 @@ module RubyCurses
|
|
2483
2311
|
@text = s
|
2484
2312
|
end
|
2485
2313
|
end
|
2314
|
+
|
2486
2315
|
##
|
2487
2316
|
# FIXME this will not work in messageboxes since no form available
|
2488
2317
|
# if already set mnemonic, then unbind_key, ??
|
@@ -2491,12 +2320,13 @@ module RubyCurses
|
|
2491
2320
|
$log.error " #{self} COULD NOT SET MNEMONIC since form NIL" if @form.nil?
|
2492
2321
|
return if @form.nil?
|
2493
2322
|
@mnemonic = char
|
2494
|
-
ch = char.downcase()[0].ord ##
|
2323
|
+
ch = char.downcase()[0].ord ## 1.9
|
2495
2324
|
# meta key
|
2496
2325
|
mch = ?\M-a.getbyte(0) + (ch - ?a.getbyte(0))
|
2497
2326
|
$log.debug " #{self} setting MNEMO to #{char} #{mch}"
|
2498
2327
|
@form.bind_key(mch, self) { |_form, _butt| _butt.fire }
|
2499
2328
|
end
|
2329
|
+
|
2500
2330
|
##
|
2501
2331
|
# bind hotkey to form keys. added 2008-12-15 20:19
|
2502
2332
|
# use ampersand in name or underline
|
@@ -2511,13 +2341,7 @@ module RubyCurses
|
|
2511
2341
|
mch = ?\M-a.getbyte(0) + (ch - ?a.getbyte(0))
|
2512
2342
|
@form.bind_key(mch, self) { |_form, _butt| _butt.fire }
|
2513
2343
|
end
|
2514
|
-
|
2515
|
-
# def on_enter
|
2516
|
-
# $log.debug "ONENTER : #{@bgcolor} "
|
2517
|
-
# end
|
2518
|
-
# def on_leave
|
2519
|
-
# $log.debug "ONLEAVE : #{@bgcolor} "
|
2520
|
-
# end
|
2344
|
+
|
2521
2345
|
def getvalue
|
2522
2346
|
@text_variable.nil? ? @text : @text_variable.get_value(@name)
|
2523
2347
|
end
|
@@ -2542,14 +2366,14 @@ module RubyCurses
|
|
2542
2366
|
value = getvalue_for_paint
|
2543
2367
|
#$log.debug("button repaint :#{self} r:#{r} c:#{c} col:#{color} bg #{bgcolor} v: #{value} ul #{@underline} mnem #{@mnemonic}")
|
2544
2368
|
len = @display_length || value.length
|
2545
|
-
@graphic = @form.window if @graphic.nil? ## cell editor listbox hack
|
2369
|
+
@graphic = @form.window if @graphic.nil? ## cell editor listbox hack
|
2546
2370
|
@graphic.printstring r, c, "%-*s" % [len, value], color, @attr
|
2547
2371
|
# @form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, bgcolor, nil)
|
2548
2372
|
# in toggle buttons the underline can change as the text toggles
|
2549
2373
|
if @underline || @mnemonic
|
2550
2374
|
uline = @underline && (@underline + @text_offset) || value.index(@mnemonic) || value.index(@mnemonic.swapcase)
|
2551
2375
|
#$log.debug " mvchgat UNDERLI r= #{r} - #{@graphic.top} c #{c} c+x #{c+uline}- #{@graphic.left} #{@graphic} "
|
2552
|
-
#$log.debug "
|
2376
|
+
#$log.debug " HACK in next line related to UNDERLINES -graphic.top"
|
2553
2377
|
# if the char is not found don't print it
|
2554
2378
|
if uline
|
2555
2379
|
y=r #-@graphic.top
|
@@ -2563,6 +2387,7 @@ module RubyCurses
|
|
2563
2387
|
end
|
2564
2388
|
end
|
2565
2389
|
end
|
2390
|
+
|
2566
2391
|
## command of button (invoked on press, hotkey, space)
|
2567
2392
|
# added args 2008-12-20 19:22
|
2568
2393
|
def command *args, &block
|
@@ -2573,9 +2398,10 @@ module RubyCurses
|
|
2573
2398
|
def fire
|
2574
2399
|
$log.debug "firing PRESS #{text}"
|
2575
2400
|
# why the .... am i passing form ? Pass a ActionEvent with source, text() and getvalue()
|
2576
|
-
#fire_handler :PRESS, @form
|
2401
|
+
#fire_handler :PRESS, @form changed on 2010-09-12 19:22
|
2577
2402
|
fire_handler :PRESS, ActionEvent.new(self, :PRESS, text)
|
2578
2403
|
end
|
2404
|
+
|
2579
2405
|
# Button
|
2580
2406
|
def handle_key ch
|
2581
2407
|
case ch
|
@@ -2590,9 +2416,21 @@ module RubyCurses
|
|
2590
2416
|
fire
|
2591
2417
|
end
|
2592
2418
|
else
|
2419
|
+
if $key_map == :vim
|
2420
|
+
case ch
|
2421
|
+
when ?j.getbyte(0)
|
2422
|
+
@form.window.ungetch(KEY_DOWN)
|
2423
|
+
return 0
|
2424
|
+
when ?k.getbyte(0)
|
2425
|
+
@form.window.ungetch(KEY_UP)
|
2426
|
+
return 0
|
2427
|
+
end
|
2428
|
+
|
2429
|
+
end
|
2593
2430
|
return :UNHANDLED
|
2594
2431
|
end
|
2595
2432
|
end
|
2433
|
+
|
2596
2434
|
# temporary method, shoud be a proper class
|
2597
2435
|
def self.button_layout buttons, row, startcol=0, cols=Ncurses.COLS-1, gap=5
|
2598
2436
|
col = startcol
|
@@ -2676,6 +2514,10 @@ module RubyCurses
|
|
2676
2514
|
@text_offset = @surround_chars[0].length
|
2677
2515
|
@surround_chars[0] + buttontext + @surround_chars[1]
|
2678
2516
|
end
|
2517
|
+
|
2518
|
+
# toggle button handle key
|
2519
|
+
# @param [int] key received
|
2520
|
+
#
|
2679
2521
|
def handle_key ch
|
2680
2522
|
if ch == 32
|
2681
2523
|
toggle
|
@@ -2683,11 +2525,13 @@ module RubyCurses
|
|
2683
2525
|
super
|
2684
2526
|
end
|
2685
2527
|
end
|
2528
|
+
|
2686
2529
|
##
|
2687
2530
|
# toggle the button value
|
2688
2531
|
def toggle
|
2689
2532
|
fire
|
2690
2533
|
end
|
2534
|
+
|
2691
2535
|
# called on :PRESS event
|
2692
2536
|
# caller should check state of itemevent passed to block
|
2693
2537
|
def fire
|
@@ -2714,9 +2558,11 @@ module RubyCurses
|
|
2714
2558
|
# call fire of button class 2008-12-09 17:49
|
2715
2559
|
end
|
2716
2560
|
end # class
|
2561
|
+
|
2717
2562
|
##
|
2718
2563
|
# A checkbox, may be selected or unselected
|
2719
2564
|
# TODO hotkey should work here too.
|
2565
|
+
#
|
2720
2566
|
class CheckBox < ToggleButton
|
2721
2567
|
dsl_accessor :align_right # the button will be on the right 2008-12-09 23:41
|
2722
2568
|
# if a variable has been defined, off and on value will be set in it (default 0,1)
|
@@ -2745,10 +2591,12 @@ module RubyCurses
|
|
2745
2591
|
end
|
2746
2592
|
end
|
2747
2593
|
end # class
|
2594
|
+
|
2748
2595
|
##
|
2749
2596
|
# A selectable button that has a text value. It is based on a Variable that
|
2750
2597
|
# is shared by other radio buttons. Only one is selected at a time, unlike checkbox
|
2751
2598
|
# 2008-11-27 18:45 just made this inherited from Checkbox
|
2599
|
+
|
2752
2600
|
class RadioButton < ToggleButton
|
2753
2601
|
dsl_accessor :align_right # the button will be on the right 2008-12-09 23:41
|
2754
2602
|
# if a variable has been defined, off and on value will be set in it (default 0,1)
|
@@ -2756,11 +2604,13 @@ module RubyCurses
|
|
2756
2604
|
@surround_chars = ['(', ')'] if @surround_chars.nil?
|
2757
2605
|
super
|
2758
2606
|
end
|
2607
|
+
|
2759
2608
|
# all radio buttons will return the value of the selected value, not the offered value
|
2760
2609
|
def getvalue
|
2761
2610
|
#@text_variable.value
|
2762
2611
|
@variable.get_value @name
|
2763
2612
|
end
|
2613
|
+
|
2764
2614
|
def getvalue_for_paint
|
2765
2615
|
buttontext = getvalue() == @value ? "o" : " "
|
2766
2616
|
dtext = @display_length.nil? ? text : "%-*s" % [@display_length, text]
|
@@ -2775,16 +2625,19 @@ module RubyCurses
|
|
2775
2625
|
return pretext + " #{dtext}"
|
2776
2626
|
end
|
2777
2627
|
end
|
2628
|
+
|
2778
2629
|
def toggle
|
2779
2630
|
@variable.set_value @value, @name
|
2780
2631
|
# call fire of button class 2008-12-09 17:49
|
2781
2632
|
fire
|
2782
2633
|
end
|
2634
|
+
|
2783
2635
|
# added for bindkeys since that calls fire, not toggle - XXX i don't like this
|
2784
2636
|
def fire
|
2785
2637
|
@variable.set_value @value,@name
|
2786
2638
|
super
|
2787
2639
|
end
|
2640
|
+
|
2788
2641
|
##
|
2789
2642
|
# ideally this should not be used. But implemented for completeness.
|
2790
2643
|
# it is recommended to toggle some other radio button than to uncheck this.
|