ncumbra 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +48 -0
- data/README.md.bak +15 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/examples/ex1.rb +85 -0
- data/examples/ex2.rb +128 -0
- data/examples/ex21.rb +136 -0
- data/examples/ex3.rb +163 -0
- data/examples/ex4.rb +142 -0
- data/examples/ex5.rb +103 -0
- data/examples/exbox.rb +141 -0
- data/examples/exm1.rb +137 -0
- data/examples/keys.rb +67 -0
- data/examples/tt.rb +462 -0
- data/lib/umbra/box.rb +137 -0
- data/lib/umbra/button.rb +130 -0
- data/lib/umbra/buttongroup.rb +96 -0
- data/lib/umbra/checkbox.rb +42 -0
- data/lib/umbra/dialog.rb +214 -0
- data/lib/umbra/eventhandler.rb +134 -0
- data/lib/umbra/field.rb +503 -0
- data/lib/umbra/form.rb +473 -0
- data/lib/umbra/keymappinghandler.rb +96 -0
- data/lib/umbra/label.rb +95 -0
- data/lib/umbra/labeledfield.rb +97 -0
- data/lib/umbra/listbox.rb +384 -0
- data/lib/umbra/menu.rb +93 -0
- data/lib/umbra/messagebox.rb +348 -0
- data/lib/umbra/pad.rb +340 -0
- data/lib/umbra/radiobutton.rb +71 -0
- data/lib/umbra/textbox.rb +417 -0
- data/lib/umbra/togglebutton.rb +140 -0
- data/lib/umbra/version.rb +3 -0
- data/lib/umbra/widget.rb +220 -0
- data/lib/umbra/window.rb +270 -0
- data/lib/umbra.rb +47 -0
- data/umbra.gemspec +27 -0
- metadata +127 -0
data/lib/umbra/field.rb
ADDED
@@ -0,0 +1,503 @@
|
|
1
|
+
# ----------------------------------------------------------------------------- #
|
2
|
+
# File: field.rb
|
3
|
+
# Description: text input field or widget
|
4
|
+
# Author: j kepler http://github.com/mare-imbrium/canis/
|
5
|
+
# Date: 2018-03
|
6
|
+
# License: MIT
|
7
|
+
# Last update: 2018-04-14 08:55
|
8
|
+
# ----------------------------------------------------------------------------- #
|
9
|
+
# field.rb Copyright (C) 2012-2018 j kepler
|
10
|
+
#
|
11
|
+
|
12
|
+
class InputDataEvent # {{{
|
13
|
+
attr_accessor :index0, :index1, :source, :type, :row, :text
|
14
|
+
def initialize index0, index1, source, type, row, text
|
15
|
+
@index0 = index0
|
16
|
+
@index1 = index1
|
17
|
+
@source = source
|
18
|
+
@type = type
|
19
|
+
@row = row
|
20
|
+
@text = text
|
21
|
+
end
|
22
|
+
# until now to_s was returning inspect, but to make it easy for users let us return the value
|
23
|
+
# they most expect which is the text that was changed
|
24
|
+
def to_s
|
25
|
+
inspect
|
26
|
+
end
|
27
|
+
def inspect
|
28
|
+
## now that textarea.to_s prints content we shouldn pass it here.
|
29
|
+
#"#{@type.to_s}, #{@source}, ind0:#{@index0}, ind1:#{@index1}, row:#{@row}, text:#{@text}"
|
30
|
+
"#{@type.to_s}, ind0:#{@index0}, ind1:#{@index1}, row:#{@row}, text:#{@text}"
|
31
|
+
end
|
32
|
+
# this is so that earlier applications were getting source in the block, not an event. they
|
33
|
+
# were doing a fld.getvalue, so we must keep those apps running
|
34
|
+
# @since 1.2.0 added 2010-09-11 12:25
|
35
|
+
def getvalue
|
36
|
+
@source.getvalue
|
37
|
+
end
|
38
|
+
end # }}}
|
39
|
+
# Text edit field
|
40
|
+
# TODO :
|
41
|
+
# ? remove datatype, just use strings.
|
42
|
+
# NOTE: +width+ is the length of the display whereas +maxlen+ is the maximum size that the value
|
43
|
+
# can take. Thus, +maxlen+ can exceed +width+. Currently, +maxlen+ defaults to +width+ which
|
44
|
+
# defaults to 20.
|
45
|
+
# NOTE: Use +text=(val)+ to set value of field, and +text()+ to retrieve value.
|
46
|
+
# == Example
|
47
|
+
# f = Field.new text: "Some value", row: 10, col: 2
|
48
|
+
#
|
49
|
+
# Field introduces an event :CHANGE which is fired for each character deleted or inserted
|
50
|
+
#
|
51
|
+
module Umbra
|
52
|
+
class Field < Widget
|
53
|
+
attr_accessor :maxlen # maximum length allowed into field
|
54
|
+
attr_reader :buffer # actual buffer being used for storage
|
55
|
+
|
56
|
+
|
57
|
+
attr_accessor :values # validate against provided list, (+include?+)
|
58
|
+
attr_accessor :valid_regex # validate against regular expression (+match()+)
|
59
|
+
attr_accessor :valid_range # validate against numeric range, should respond to +include?+
|
60
|
+
# for numeric fields, specify lower or upper limit of entered value
|
61
|
+
attr_accessor :below, :above
|
62
|
+
|
63
|
+
# aliased to type
|
64
|
+
#attr_accessor :chars_allowed # regex, what characters to allow entry, will ignore all else
|
65
|
+
# character to show, earlier called +show+ which clashed with Widget method +show+
|
66
|
+
attr_accessor :mask # what charactr to show for each char entered (password field)
|
67
|
+
attr_accessor :null_allowed # allow nulls, don't validate if null # added , boolean
|
68
|
+
|
69
|
+
# any new widget that has +editable+ should have +modified+ also
|
70
|
+
attr_accessor :editable # allow editing
|
71
|
+
|
72
|
+
# +type+ is just a convenience over +chars_allowed+ and sets some basic filters
|
73
|
+
# @example: :integer, :float, :alpha, :alnum
|
74
|
+
# NOTE: we do not store type, only chars_allowed, so this won't return any value
|
75
|
+
#attr_reader :type # datatype of field, currently only sets chars_allowed
|
76
|
+
|
77
|
+
# this accesses the field created or passed with set_label
|
78
|
+
#attr_reader :label
|
79
|
+
# this is the class of the field set in +text()+, so value is returned in same class
|
80
|
+
# @example : Integer, Integer, Float
|
81
|
+
attr_accessor :datatype # currently set during set_buffer
|
82
|
+
attr_reader :original_value # value on entering field
|
83
|
+
attr_accessor :overwrite_mode # true or false INSERT OVERWRITE MODE
|
84
|
+
|
85
|
+
# column on which field printed, usually the same as +col+ unless +label+ used.
|
86
|
+
# Required by +History+ to popup field history.
|
87
|
+
attr_reader :field_col # column on which field is printed
|
88
|
+
# required due to labels. Is updated after printing
|
89
|
+
# # so can be nil if accessed early 2011-12-8
|
90
|
+
|
91
|
+
def initialize config={}, &block
|
92
|
+
@buffer = String.new
|
93
|
+
@row = 0
|
94
|
+
@col = 0
|
95
|
+
@editable = true
|
96
|
+
@focusable = true
|
97
|
+
|
98
|
+
map_keys
|
99
|
+
init_vars
|
100
|
+
register_events(:CHANGE)
|
101
|
+
super
|
102
|
+
@width ||= 20
|
103
|
+
@maxlen ||= @width
|
104
|
+
end
|
105
|
+
def init_vars
|
106
|
+
@pcol = 0 # needed for horiz scrolling
|
107
|
+
@curpos = 0 # current cursor position in buffer (NOT screen/window/field)
|
108
|
+
# this is the index where characters are put or deleted
|
109
|
+
# # when user edits
|
110
|
+
@modified = false
|
111
|
+
end
|
112
|
+
|
113
|
+
# NOTE: earlier there was some confusion over type, chars_allowed and datatype
|
114
|
+
# Now type and chars_allowed are merged into one.
|
115
|
+
# If you pass a symbol such as :integer, :float or Float Integer then some
|
116
|
+
# standard chars_allowed will be used. Otherwise you may pass a regexp.
|
117
|
+
#
|
118
|
+
# @param [symbol] :integer, :float, :alpha, :alnum, Float, Integer, Numeric, Regexp
|
119
|
+
def type=(val)
|
120
|
+
|
121
|
+
dtype = val
|
122
|
+
#return self if @chars_allowed # disallow changing
|
123
|
+
# send in a regexp, we just save it.
|
124
|
+
if dtype.is_a? Regexp
|
125
|
+
@chars_allowed = dtype
|
126
|
+
return self
|
127
|
+
end
|
128
|
+
dtype = dtype.to_s.downcase.to_sym if dtype.is_a? String
|
129
|
+
case dtype # missing to_sym would have always failed due to to_s 2011-09-30 1.3.1
|
130
|
+
when :integer, Integer
|
131
|
+
@chars_allowed = /\d/
|
132
|
+
when :numeric, :float, Numeric, Float
|
133
|
+
@chars_allowed = /[\d\.]/
|
134
|
+
when :alpha
|
135
|
+
@chars_allowed = /[a-zA-Z]/
|
136
|
+
when :alnum
|
137
|
+
@chars_allowed = /[a-zA-Z0-9]/
|
138
|
+
else
|
139
|
+
raise ArgumentError, "Field type: invalid datatype specified. Use :integer, :numeric, :float, :alpha, :alnum "
|
140
|
+
end
|
141
|
+
self
|
142
|
+
end
|
143
|
+
alias :chars_allowed= :type=
|
144
|
+
|
145
|
+
#
|
146
|
+
# add a char to field, and validate
|
147
|
+
# if disabled or exceeding size
|
148
|
+
# @param [char] a character to add
|
149
|
+
# @return [Integer] 0 if okay, -1 if not editable or exceeding length
|
150
|
+
def putch char
|
151
|
+
return -1 if !@editable
|
152
|
+
return -1 if !@overwrite_mode && (@buffer.length >= @maxlen)
|
153
|
+
blen = @buffer.length
|
154
|
+
if @chars_allowed != nil
|
155
|
+
return if char.match(@chars_allowed).nil?
|
156
|
+
end
|
157
|
+
# added insert or overwrite mode 2010-03-17 20:11
|
158
|
+
oldchar = nil
|
159
|
+
if @overwrite_mode
|
160
|
+
oldchar = @buffer[@curpos]
|
161
|
+
@buffer[@curpos] = char
|
162
|
+
else
|
163
|
+
@buffer.insert(@curpos, char)
|
164
|
+
end
|
165
|
+
oldcurpos = @curpos
|
166
|
+
#$log.warn "XXX: FIELD CURPOS #{@curpos} blen #{@buffer.length} " #if @curpos > blen
|
167
|
+
@curpos += 1 if @curpos < @maxlen
|
168
|
+
@modified = true
|
169
|
+
#$log.debug " FIELD FIRING CHANGE: #{char} at new #{@curpos}: bl:#{@buffer.length} buff:[#{@buffer}]"
|
170
|
+
if @overwrite_mode
|
171
|
+
fire_handler :CHANGE, InputDataEvent.new(oldcurpos,@curpos, self, :DELETE, 0, oldchar) # 2010-09-11 12:43
|
172
|
+
end
|
173
|
+
fire_handler :CHANGE, InputDataEvent.new(oldcurpos,@curpos, self, :INSERT, 0, char) # 2010-09-11 12:43
|
174
|
+
0
|
175
|
+
end
|
176
|
+
|
177
|
+
##
|
178
|
+
# add character to field, adjust scrolling.
|
179
|
+
# NOTE: handlekey only calls this if between 32 and 126.
|
180
|
+
def putc c
|
181
|
+
if c >= 0 and c <= 127
|
182
|
+
ret = putch c.chr
|
183
|
+
if ret == 0
|
184
|
+
# character is valid
|
185
|
+
if addcol(1) == -1 # if can't go forward, try scrolling
|
186
|
+
# scroll if exceeding display len but less than max len
|
187
|
+
if @curpos > @width && @curpos <= @maxlen
|
188
|
+
@pcol += 1 if @pcol < @width
|
189
|
+
end
|
190
|
+
end
|
191
|
+
@modified = true
|
192
|
+
return 0
|
193
|
+
end
|
194
|
+
end
|
195
|
+
return -1
|
196
|
+
end
|
197
|
+
# delete a character from the buffer at given position
|
198
|
+
# Called by +delete_curr_char+ and +delete_prev_char+.
|
199
|
+
def delete_at index=@curpos
|
200
|
+
return -1 if !@editable
|
201
|
+
char = @buffer.slice!(index,1)
|
202
|
+
#$log.debug " delete at #{index}: #{@buffer.length}: #{@buffer}"
|
203
|
+
@modified = true
|
204
|
+
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos, self, :DELETE, 0, char) # 2010-09-11 13:01
|
205
|
+
end
|
206
|
+
#
|
207
|
+
# silently restores earlier value without firing handlers, use if exception and you want old value
|
208
|
+
# Called when pressing <ESC> or <c-g>.
|
209
|
+
def restore_original_value
|
210
|
+
@buffer = @original_value.dup
|
211
|
+
# earlier commented but trying again, since i am getting IndexError in insert 2188
|
212
|
+
# Added next 3 lines to fix issue, now it comes back to beginning.
|
213
|
+
cursor_home
|
214
|
+
|
215
|
+
@repaint_required = true
|
216
|
+
end
|
217
|
+
##
|
218
|
+
# set value of Field
|
219
|
+
# fires CHANGE handler
|
220
|
+
# Please don't use this directly, use +text+
|
221
|
+
# This name is from ncurses field, added underscore to emphasize not to use
|
222
|
+
private def _set_buffer value #:nodoc:
|
223
|
+
@repaint_required = true
|
224
|
+
@datatype = value.class
|
225
|
+
@delete_buffer = @buffer.dup
|
226
|
+
@buffer = value.to_s.dup
|
227
|
+
# don't allow setting of value greater than maxlen
|
228
|
+
@buffer = @buffer[0,@maxlen] if @maxlen && @buffer.length > @maxlen
|
229
|
+
@curpos = 0
|
230
|
+
# hope @delete_buffer is not overwritten
|
231
|
+
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos, self, :DELETE, 0, @delete_buffer) # 2010-09-11 13:01
|
232
|
+
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos, self, :INSERT, 0, @buffer) # 2010-09-11 13:01
|
233
|
+
self # 2011-10-2
|
234
|
+
end
|
235
|
+
## add a column to cursor position. Field
|
236
|
+
private def addcol num
|
237
|
+
x = @col_offset + num
|
238
|
+
return -1 if x < 0
|
239
|
+
return -1 if x > @width
|
240
|
+
@col_offset += num
|
241
|
+
end
|
242
|
+
|
243
|
+
# converts back into original type
|
244
|
+
# changed to convert on 2009-01-06 23:39
|
245
|
+
# 2018-04-13 - Changed from private to public since I got an error on on_leave
|
246
|
+
# when this was called from LabeledField.
|
247
|
+
def getvalue
|
248
|
+
dt = @datatype || String
|
249
|
+
case dt.to_s
|
250
|
+
when "String"
|
251
|
+
return @buffer
|
252
|
+
when "Integer"
|
253
|
+
return @buffer.to_i
|
254
|
+
when "Float"
|
255
|
+
return @buffer.to_f
|
256
|
+
else
|
257
|
+
return @buffer.to_s
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
|
262
|
+
public
|
263
|
+
## Note that some older widgets like Field repaint every time the form.repaint
|
264
|
+
##+ is called, whether updated or not. I can't remember why this is, but
|
265
|
+
##+ currently I've not implemented events with these widgets. 2010-01-03 15:00
|
266
|
+
|
267
|
+
def repaint
|
268
|
+
return unless @repaint_required # 2010-11-20 13:13 its writing over a window i think TESTING
|
269
|
+
$log.debug("repaint FIELD: #{name}, r:#{row} c:#{col},wid:#{width},pcol:#{@pcol}, #{focusable} st: #{@state} ")
|
270
|
+
@width = 1 if width == 0
|
271
|
+
printval = getvalue_for_paint().to_s # added 2009-01-06 23:27
|
272
|
+
printval = mask()*printval.length unless @mask.nil?
|
273
|
+
if !printval.nil?
|
274
|
+
if printval.length > width # only show maxlen
|
275
|
+
printval = printval[@pcol..@pcol+width-1]
|
276
|
+
else
|
277
|
+
printval = printval[@pcol..-1]
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
acolor = @color_pair || CP_WHITE
|
282
|
+
if @state == :HIGHLIGHTED
|
283
|
+
acolor = @highlight_color_pair || CP_RED
|
284
|
+
end
|
285
|
+
#$log.debug " Field g:#{@graphic}. r,c,displen:#{@row}, #{@col}, #{@width} c:#{@color} bg:#{@bgcolor} a:#{@attr} :#{@name} "
|
286
|
+
r = row
|
287
|
+
c = col
|
288
|
+
@graphic.printstring r, c, sprintf("%-*s", width, printval), acolor, attr()
|
289
|
+
@field_col = c
|
290
|
+
@repaint_required = false
|
291
|
+
end
|
292
|
+
|
293
|
+
def map_keys
|
294
|
+
return if @keys_mapped
|
295
|
+
bind_key(FFI::NCurses::KEY_LEFT, :cursor_backward )
|
296
|
+
bind_key(FFI::NCurses::KEY_RIGHT, :cursor_forward )
|
297
|
+
bind_key(FFI::NCurses::KEY_BACKSPACE, :delete_prev_char )
|
298
|
+
bind_key(127, :delete_prev_char )
|
299
|
+
bind_key(330, :delete_curr_char )
|
300
|
+
bind_key(?\C-a, :cursor_home )
|
301
|
+
bind_key(?\C-e, :cursor_end )
|
302
|
+
bind_key(?\C-k, :delete_eol )
|
303
|
+
bind_key(?\C-_, :undo_delete_eol )
|
304
|
+
#bind_key(27){ text @original_value }
|
305
|
+
bind_key(?\C-g, 'revert'){ restore_original_value }
|
306
|
+
@keys_mapped = true
|
307
|
+
end
|
308
|
+
|
309
|
+
# field - handle a key sent for form
|
310
|
+
#
|
311
|
+
def handle_key ch
|
312
|
+
$log.debug "inside handle key of field with #{ch}"
|
313
|
+
@repaint_required = true
|
314
|
+
case ch
|
315
|
+
when 32..126
|
316
|
+
putc ch
|
317
|
+
when 27 # cannot bind it, so hardcoding it here
|
318
|
+
restore_original_value
|
319
|
+
else
|
320
|
+
ret = super
|
321
|
+
return ret
|
322
|
+
end
|
323
|
+
0 # 2008-12-16 23:05 without this -1 was going back so no repaint
|
324
|
+
end
|
325
|
+
# does an undo on delete_eol, not a real undo
|
326
|
+
def undo_delete_eol
|
327
|
+
return if @delete_buffer.nil?
|
328
|
+
#oldvalue = @buffer
|
329
|
+
@buffer.insert @curpos, @delete_buffer
|
330
|
+
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :INSERT, 0, @delete_buffer) # 2010-09-11 13:01
|
331
|
+
end
|
332
|
+
##
|
333
|
+
# position cursor at start of field
|
334
|
+
def cursor_home
|
335
|
+
@curpos = 0
|
336
|
+
@pcol = 0
|
337
|
+
set_col_offset 0
|
338
|
+
end
|
339
|
+
##
|
340
|
+
# goto end of field, "end" is a keyword so could not use it.
|
341
|
+
def cursor_end
|
342
|
+
blen = @buffer.rstrip.length
|
343
|
+
if blen < @width
|
344
|
+
set_col_offset blen
|
345
|
+
else
|
346
|
+
@pcol = blen-@width
|
347
|
+
#set_form_col @width-1
|
348
|
+
set_col_offset blen
|
349
|
+
end
|
350
|
+
@curpos = blen # this is position in array where editing or motion is to happen regardless of what you see
|
351
|
+
# regardless of pcol (panning)
|
352
|
+
end
|
353
|
+
# sets the visual cursor on the window at correct place
|
354
|
+
# NOTE be careful of curpos - pcol being less than 0
|
355
|
+
private def set_col_offset x=@curpos
|
356
|
+
@curpos = x || 0 # NOTE we set the index of cursor here
|
357
|
+
#return -1 if x < 0
|
358
|
+
#return -1 if x > @width
|
359
|
+
if x > @width
|
360
|
+
x = @width
|
361
|
+
end
|
362
|
+
@col_offset = x
|
363
|
+
return
|
364
|
+
=begin
|
365
|
+
c = @col + @col_offset + @curpos - @pcol
|
366
|
+
min = @col + @col_offset
|
367
|
+
max = min + @width
|
368
|
+
c = min if c < min
|
369
|
+
c = max if c > max
|
370
|
+
#$log.debug " #{@name} FIELD set_form_col #{c}, curpos #{@curpos} , #{@col} + #{@col_offset} pcol:#{@pcol} "
|
371
|
+
#setrowcol nil, c # this does not exist since it called form
|
372
|
+
=end
|
373
|
+
end
|
374
|
+
def delete_eol
|
375
|
+
return -1 unless @editable
|
376
|
+
pos = @curpos-1
|
377
|
+
@delete_buffer = @buffer[@curpos..-1]
|
378
|
+
# if pos is 0, pos-1 becomes -1, end of line!
|
379
|
+
@buffer = pos == -1 ? "" : @buffer[0..pos]
|
380
|
+
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :DELETE, 0, @delete_buffer)
|
381
|
+
return @delete_buffer
|
382
|
+
end
|
383
|
+
# move cursor forward one character, called with KEY_RIGHT action.
|
384
|
+
def cursor_forward
|
385
|
+
if @curpos < @buffer.length
|
386
|
+
if addcol(1)==-1 # go forward if you can, else scroll
|
387
|
+
@pcol += 1 if @pcol < @width
|
388
|
+
end
|
389
|
+
@curpos += 1
|
390
|
+
end
|
391
|
+
# $log.debug " crusor FORWARD cp:#{@curpos} pcol:#{@pcol} b.l:#{@buffer.length} d_l:#{@display_length} fc:#{@form.col}"
|
392
|
+
end
|
393
|
+
# move cursor back one character, called with KEY_LEFT action.
|
394
|
+
def cursor_backward
|
395
|
+
if @curpos > 0
|
396
|
+
@curpos -= 1
|
397
|
+
#if @pcol > 0 #and @form.col == @col + @col_offset
|
398
|
+
#@pcol -= 1
|
399
|
+
#end
|
400
|
+
addcol -1
|
401
|
+
elsif @pcol > 0
|
402
|
+
# pan left only when cursor pos is 0
|
403
|
+
@pcol -= 1
|
404
|
+
end
|
405
|
+
# $log.debug " crusor back cp:#{@curpos} pcol:#{@pcol} b.l:#{@buffer.length} d_l:#{@display_length} fc:#{@form.col}"
|
406
|
+
=begin
|
407
|
+
# this is perfect if not scrolling, but now needs changes
|
408
|
+
if @curpos > 0
|
409
|
+
@curpos -= 1
|
410
|
+
addcol -1
|
411
|
+
end
|
412
|
+
=end
|
413
|
+
end
|
414
|
+
def delete_curr_char
|
415
|
+
return -1 unless @editable
|
416
|
+
delete_at
|
417
|
+
@modified = true
|
418
|
+
end
|
419
|
+
# called when user presses backspace.
|
420
|
+
# Delete character on left of cursor
|
421
|
+
def delete_prev_char
|
422
|
+
return -1 if !@editable
|
423
|
+
return if @curpos <= 0
|
424
|
+
# if we've panned, then unpan, and don't move cursor back
|
425
|
+
# Otherwise, adjust cursor (move cursor back as we delete)
|
426
|
+
adjust = true
|
427
|
+
if @pcol > 0
|
428
|
+
@pcol -= 1
|
429
|
+
adjust = false
|
430
|
+
end
|
431
|
+
@curpos -= 1 if @curpos > 0
|
432
|
+
delete_at
|
433
|
+
addcol -1 if adjust # move visual cursor back
|
434
|
+
@modified = true
|
435
|
+
end
|
436
|
+
# upon leaving a field
|
437
|
+
# returns false if value not valid as per values or valid_regex
|
438
|
+
# 2008-12-22 12:40 if null_allowed, don't validate, but do fire_handlers
|
439
|
+
def on_leave
|
440
|
+
val = getvalue
|
441
|
+
#$log.debug " FIELD ON LEAVE:#{val}. #{@values.inspect}"
|
442
|
+
valid = true
|
443
|
+
if val.to_s.empty? && @null_allowed
|
444
|
+
#$log.debug " empty and null allowed"
|
445
|
+
else
|
446
|
+
if !@values.nil?
|
447
|
+
valid = @values.include? val
|
448
|
+
raise FieldValidationException, "Field value (#{val}) not in values: #{@values.join(',')}" unless valid
|
449
|
+
end
|
450
|
+
if !@valid_regex.nil?
|
451
|
+
valid = @valid_regex.match(val.to_s)
|
452
|
+
raise FieldValidationException, "Field not matching regex #{@valid_regex}" unless valid
|
453
|
+
end
|
454
|
+
# added valid_range for numerics 2011-09-29
|
455
|
+
if !in_range?(val)
|
456
|
+
raise FieldValidationException, "Field not matching range #{@valid_range}, above #{@above} or below #{@below} "
|
457
|
+
end
|
458
|
+
end
|
459
|
+
# here is where we should set the forms modified to true - 2009-01
|
460
|
+
if modified?
|
461
|
+
@modified = true
|
462
|
+
end
|
463
|
+
# if super fails we would have still set modified to true
|
464
|
+
super
|
465
|
+
#return valid
|
466
|
+
end
|
467
|
+
|
468
|
+
# checks field against +valid_range+, +above+ and +below+ , returning +true+ if it passes
|
469
|
+
# set attributes, +false+ if it fails any one.
|
470
|
+
def in_range?( val )
|
471
|
+
val = val.to_i
|
472
|
+
(@above.nil? or val > @above) and
|
473
|
+
(@below.nil? or val < @below) and
|
474
|
+
(@valid_range.nil? or @valid_range.include?(val))
|
475
|
+
end
|
476
|
+
## save original value on enter, so we can check for modified.
|
477
|
+
# 2009-01-18 12:25
|
478
|
+
# 2011-10-9 I have changed to take @buffer since getvalue returns a datatype
|
479
|
+
# and this causes a crash in set_original on cursor forward.
|
480
|
+
def on_enter
|
481
|
+
#@original_value = getvalue.dup rescue getvalue
|
482
|
+
@original_value = @buffer.dup # getvalue.dup rescue getvalue
|
483
|
+
super
|
484
|
+
end
|
485
|
+
##
|
486
|
+
# overriding widget, check for value change
|
487
|
+
def modified?
|
488
|
+
getvalue() != @original_value
|
489
|
+
end
|
490
|
+
# 2018-03-22 - replaced the old style text(val) with attr style
|
491
|
+
def text
|
492
|
+
getvalue
|
493
|
+
end
|
494
|
+
def text=(val)
|
495
|
+
return unless val # added 2010-11-17 20:11, dup will fail on nil
|
496
|
+
# will bomb on integer or float etc !!
|
497
|
+
#_set_buffer(val.dup)
|
498
|
+
_set_buffer(val)
|
499
|
+
end
|
500
|
+
alias :default= :text=
|
501
|
+
# ADD HERE FIELD
|
502
|
+
end # }}}
|
503
|
+
end # module
|