ncumbra 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env ruby
2
+ # ----------------------------------------------------------------------------- #
3
+ # File: ,,F
4
+ # Description: This file does the following:
5
+ # Author: r kumar
6
+ # Date: ,,D
7
+ # Last update: 2018-05-15 12:53
8
+ # License: MIT License
9
+ # ----------------------------------------------------------------------------- #
10
+ require 'umbra'
11
+ require 'umbra/label'
12
+ require 'umbra/tabular'
13
+ require 'umbra/listbox'
14
+ require 'umbra/textbox'
15
+ require 'umbra/box'
16
+
17
+ def startup
18
+ require 'logger'
19
+ require 'date'
20
+
21
+ path = File.join(ENV["LOGDIR"] || "./" ,"v.log")
22
+ file = File.open(path, File::WRONLY|File::TRUNC|File::CREAT)
23
+ $log = Logger.new(path)
24
+ $log.level = Logger::DEBUG
25
+ today = Date.today
26
+ $log.info "Started demo tabular on #{today}"
27
+ FFI::NCurses.init_pair(10, FFI::NCurses::BLACK, FFI::NCurses::GREEN) # statusline
28
+ end
29
+ def statusline win, str, col = 0
30
+ win.printstring( FFI::NCurses.LINES-1, col, str, 10)
31
+ end
32
+ begin
33
+ include Umbra
34
+ init_curses
35
+ startup
36
+ win = Window.new
37
+ statusline(win, " "*(win.width-0), 0)
38
+ statusline(win, "Press Ctrl-q to quit #{win.height}:#{win.width}", 20)
39
+ title = Label.new( :text => "Demo of Tabular", :row => 0, :col => 0 , :width => FFI::NCurses.COLS-1,
40
+ :justify => :center, :color_pair => 0)
41
+
42
+ form = Form.new win
43
+ form.add_widget title
44
+
45
+ box = Box.new row: 2, col: 0, width: 10, height: 7
46
+ t = Tabular.new(['a', 'b'], [1, 2], [3, 4], [5,6])
47
+ lb = Listbox.new list: t.render
48
+ box.fill lb
49
+ box1 = Box.new row: box.row + box.height + 0, col: box.col, width: 10, height: 7
50
+ t = Tabular.new ['a', 'b']
51
+ t << [1, 2]
52
+ t << [3, 4]
53
+ t << [4, 6]
54
+ t << [8, 6]
55
+ t << [2, 6]
56
+ t.y = '| '
57
+ t.x = '+-'
58
+ lb1 = Listbox.new list: t.render
59
+ box1.fill lb1
60
+
61
+ #file = File.expand_path("examples/tasks.csv", __FILE__)
62
+ file = File.expand_path("examples/tasks.csv")
63
+ lines = File.open(file,'r').readlines
64
+ heads = %w[ id sta type prio title ]
65
+ t = Tabular.new do |t|
66
+ t.headings = heads
67
+ t.y = ' '
68
+ lines.each { |e| t.add_row e.chomp.split '|' }
69
+ end
70
+
71
+ t = t.render
72
+ wid = t[0].length + 2
73
+ wid = 30
74
+ box2 = Box.new title: "tasks.csv", row: box.row , col: box.col + box.width+1, width: FFI::NCurses.COLS-box.width-1, height: FFI::NCurses.LINES-1-box.row
75
+ lb2 = Listbox.new list: t
76
+
77
+ r = `ls -l`
78
+ res = r.split("\n")
79
+
80
+ t = Tabular.new do
81
+ self.headings = 'User', 'Size', 'Mon', 'Date', 'Time', 'File'
82
+ res.each { |e|
83
+ cols = e.split
84
+ next if cols.count < 6
85
+ cols = cols[3..-1]
86
+ cols = cols[0..5] if cols.count > 6
87
+ add_row cols
88
+ }
89
+ column_width 1, 6
90
+ column_align 1, :right
91
+ end
92
+ #t.y = '| '
93
+ #t.x = '+-'
94
+ tb = Textbox.new list: t.render
95
+ box2.add lb2, tb
96
+
97
+ form.add_widget box, lb
98
+ form.add_widget box1, lb1
99
+ form.add_widget box2, lb2, tb
100
+
101
+
102
+ form.pack
103
+ form.repaint
104
+ win.wrefresh
105
+
106
+ y = x = 1
107
+ while (ch = win.getkey) != FFI::NCurses::KEY_CTRL_Q
108
+ next if ch == -1
109
+ form.handle_key ch
110
+ #statusline(win, "Pressed #{ch} on ", 70)
111
+ win.wrefresh
112
+ end
113
+
114
+ rescue Object => e
115
+ @window.destroy if @window
116
+ FFI::NCurses.endwin
117
+ puts e
118
+ puts e.backtrace.join("\n")
119
+ ensure
120
+ @window.destroy if @window
121
+ FFI::NCurses.endwin
122
+ puts
123
+ end
@@ -0,0 +1,88 @@
1
+ 1|clo|bug|X3|messagebox label print overlaps left border
2
+ 2|clo|enh|P4|Field: methods not chainable
3
+ 3|clo|bug|P3|button crash if mnemo not in text
4
+ 4|clo|enh|P3|link mnemo should not have Alt
5
+ 8|ope|bug|P5|container keep repainting all
6
+ 9|clo|enh|P3|menu bar keys
7
+ 10|ope|enh|P4|combo keys
8
+ 11|clo|bug|X3|hand written DSL defs dont fire prop handler
9
+ 12|clo|bug|X4|textview on_enter
10
+ 13|clo|enh|P3|traversal of listboxes
11
+ 14|clo|enh|P3|check keys Alt-Sh-O, Alt-[. Add some missing
12
+ 15|clo|bug|P3|2 keys simulaneously with Alt-O or Alt-[
13
+ 16|clo|enh|P3|put key combins in arrays and match
14
+ 17|ope|bug|P4|selected_item of list broken
15
+ 18|clo|enh|P3|valid_range for Field
16
+ 19|clo|bug|X2|tree can print beyond right margin
17
+ 20|ope|bug|P4|cannot bind_key using Alt key and another.
18
+ 21|sta|enh|P2|make code from App common so reusable in other examples
19
+ 22|ope|bug|P3|widget hide (visible false) does not hide
20
+ 23|clo|bug|P3|listbox color changes not reflecting in cell_renderer
21
+ 24|clo|bug|P3|Table: delete row should reflect focussed_index.
22
+ 25|clo|enh|X3|#cleanup add_cols rows_panned #urgent
23
+ 26|ope|fea|P5|App to have a layout abject
24
+ 27|ope|bug|P4|#fix testvimsplit not sizing STACK correctly
25
+ 28|clo|enh|P1|FieldValidationException should rollback change,
26
+ 29|clo|enh|X1|return self from dsl_prop and dsl_accessor,
27
+ 30|can|bug|P3|on_leave has validations that should be separated,
28
+ 31|clo|enh|X1|#listbox data more accessible from LB class,
29
+ 32|ope|enh|P4| #tree many empty methods in #treemodel
30
+ 33|clo|enh|X3|display_menu shd furhter glob on tab
31
+ 34|clo|enh|X3|display_menu large list need scrolling
32
+ 35|clo|bug|X3|alert message getting truncated after 2 lines
33
+ 36|clo|fea|X3|use j k h l for navigation if unused by a button of widget
34
+ 37|ope|enh|P4|simplify #vimsplit calculation
35
+ 38|clo|bug|X3|#tabbedpane when fire, state of old tab discrep
36
+ 39|ope|bug|P5|tabularwidget truncate needed left_margin
37
+ 40|clo|bug|X3|%textarea C-e goes to last char, not one after that
38
+ 41|clo|bug|X3|M-2 did not work in textarea
39
+ 42|ope|bug|P5|append_to_kill, yank not working in %listbox
40
+ 43|clo|bug|X1|rt arrow and backspace issue ask(), dbdemo save #urgent
41
+ 44|clo|bug|P1|need to hide window after ask(), dbdemo save
42
+ 45|clo|bug|X3|directory list, after pressing Enter on ../ focus on header
43
+ 46|clo|enh|X3|textview repaints all even when no scrolling
44
+ 47|ope|enh|P4|vieditable and io.rb need to create statuswindow and take input
45
+ 48|clo|bug|X3|say not working after ask hides window
46
+ 49|ope|enh|P5|resultsetview needs way to specify key fields
47
+ 50|ope|bug|P5|sort on tabularwidget with resultset error sometimes
48
+ 51|clo|bug|X2|TabbedPane's TabbedButtons rely on window being 0,0
49
+ 52|ope|bug|P4|%label set_label may have to calculate at repaint esp in app
50
+ 53|clo|bug|X3|%App. if shortcut used outside stack or flow, dont attach form or set
51
+ 54|clo|bug|X3|inside newtabbedpane button mnemonic and underline not happening #fix
52
+ 55|ope|enh|P4|Have a module Expandable for those that are multiline
53
+ 56|ope|enh|P4|DRY up titles and borders
54
+ 57|clo|enh|X2|dont put default for color and bg in init of Wid or field
55
+ 58|clo|enh|X2|Fields display_length should be width or made alias
56
+ 60|ope|enh|P4|fields width, display_len is for input area, not label plus input
57
+ 61|ope|bug|P4|test2.rb color change not affecting text objects
58
+ 62|clo|bug|X2|when using chunks, movement crashes C-e etc
59
+ 63|clo|bug|X2|chunks in textview, when scrolling earlier lines shown
60
+ 64|clo|enh|X2|abstract chunk and parse into Format class
61
+ 65|ope|enh|P3|clean up window.rb prv_printstring etc
62
+ 66|clo|bug|X2|colorparser needs to carryover, and :reset
63
+ 67|clo|enh|X3|several places doing attrib conversion in window, use get_attrib
64
+ 68|clo|bug|X4|move chunk parsing from window.rb to chunk as in textview
65
+ 69|ope|bug|P2|C-u not available for textpad and view. how to
66
+ 70|ope|enh|P4|confusion between renderer and color_parser
67
+ 71|clo|enh|X1|redo combo with basiclist or new popup
68
+ 72|clo|enh|X2|redo label simplify, one line only
69
+ 73|clo|bug|X2|rbasiclist needs to reduce selected symbol
70
+ 74|ope|enh|P3|list and others should just calculate longest in list
71
+ 75|ope|enh|P4|textpad to allow append << at some stage
72
+ 76|clo|enh|X3|appmethods.rb may need to go into lib/common or somewhere else
73
+ 77|clo|enh|X2|switch messagebox old and new and change rdialog
74
+ 78|clo|enh|X1|switch tabbedpane classes and update examples
75
+ 79|ope|enh|P3|cleanup button getpaint etc
76
+ 80|ope|enh|P3|use @focusable in form to simplify
77
+ 81|clo|bug|X2|field label mnemonic not being set
78
+ 82|ope|bug|P2|new messagebox need default_button option
79
+ 83|clo|enh|X2|check statusline usage, should use formatted only
80
+ 84|clo|bug|X2|dbdemo M-z not doing anything
81
+ 85|ope|bug|P2|combo symbol when label, see newmessagebox
82
+ 86|ope|bug|P2|combo let caller suggest width and use if longer than longest item
83
+ 87|ope|enh|P3|praps global setting lists etc use SPC for scroll or selection
84
+ 88|ope|enh|P2|keep working on wsshortcuts as in testws..2.rb
85
+ 89|ope|bug|P2|messagebox, see about background for zterm-256 as in header
86
+ 90|clo|bug|X2|messagebox: message sets width, even if user has specified
87
+ 91|clo|enh|X2|messagebox: default row col cannot be 0,0
88
+ 92|ope|enh|P3|messagebox: if text longer than display then can we split
data/lib/umbra/box.rb CHANGED
@@ -4,36 +4,40 @@
4
4
  # Author: j kepler http://github.com/mare-imbrium/canis/
5
5
  # Date: 2018-04-07
6
6
  # License: MIT
7
- # Last update: 2018-04-08 09:12
7
+ # Last update: 2018-05-22 14:44
8
8
  # ----------------------------------------------------------------------------- #
9
9
  # box.rb Copyright (C) 2018 j kepler
10
10
  module Umbra
11
11
  ##
12
12
  # A box is a container around one, maybe more, widgets.
13
+ ## FIXME box needs to resize components if it's dimensions are changed.
14
+ ## Or should components have a link to parent, so they can resize themselves ?
13
15
  #
14
16
  class Box < Widget
15
- attr_accessor :title
16
- attr_accessor :width
17
- attr_accessor :height
17
+ attr_property :title
18
+ #attr_property :width
19
+ #attr_property :height
18
20
  attr_accessor :row_offset # not used yet
19
21
  attr_accessor :col_offset # not used yet
20
- attr_accessor :visible
22
+ attr_property :visible
21
23
  attr_reader :widgets
22
24
  attr_reader :widget
23
- attr_accessor :justify # right, left or center TODO
25
+ attr_property :justify # right, left or center TODO
24
26
 
25
27
  def initialize config={}, &block
26
28
  @focusable = false
27
29
  @visible = true
28
30
  super
29
- @int_height = @height - 2
30
- @int_width = @width - 2
31
+ #@int_height = @height - 2
32
+ @int_height = self.height - 2
33
+ #@int_width = @width - 2
34
+ @int_width = self.width - 2
31
35
  @hlines = []
32
36
  @vlines = []
33
37
  end
34
38
  def repaint
35
39
  return unless @visible
36
- print_border @row, @col, @height, @width, @color_pair || CP_BLACK, @attr || NORMAL
40
+ print_border self.row, self.col, self.height, self.width, @color_pair || CP_BLACK, @attr || NORMAL
37
41
  print_title @title
38
42
  if !@hlines.empty?
39
43
  @hlines.each {|e| hline(e.first, e[1]) }
@@ -68,10 +72,10 @@ module Umbra
68
72
  def flow *w
69
73
  @widgets = w
70
74
  num = w.size
71
- wid = (@int_width / num).floor
75
+ wid = (@int_width / num).floor ## FIXME how to recalc this if RESIZE
72
76
  ht = @int_height
73
- srow = @row + 1
74
- scol = @col + 1
77
+ srow = self.row + 1
78
+ scol = self.col + 1
75
79
  w.each_with_index do |e, ix|
76
80
  # unfortunately this is messing with button width calculation
77
81
  # maybe field and button should have resizable or expandable ?
@@ -89,16 +93,28 @@ module Umbra
89
93
  # use if only one widget will expand into this box
90
94
  def fill w
91
95
  # should have been nice if I could add widget to form, but then order might get wrong
92
- w.row = @row + 1
93
- w.col = @col + 1
94
- w.width = @width - 2 if w.respond_to? :width
95
- w.height = @height - 2 if w.respond_to? :height
96
+ w.row = self.row + 1
97
+ w.col = self.col + 1
98
+ if w.respond_to? :width
99
+ if @width < 0
100
+ w.width = @width - 1 ## relative to bottom
101
+ else
102
+ w.width = @width - 2 ## absolute
103
+ end
104
+ end
105
+ if w.respond_to? :height
106
+ if @height < 0
107
+ w.height = @height - 1 ## relative to bottom
108
+ else
109
+ w.height = @height - 2 ## absolute
110
+ end
111
+ end
96
112
  @widget = w
97
113
  end
98
114
  def hline row, col
99
- return if row >= @row + @height
115
+ return if row >= self.row + self.height
100
116
  $log.debug " hline: #{row} ... #{@row} #{@height} "
101
- FFI::NCurses.mvwhline( @graphic.pointer, row, col, FFI::NCurses::ACS_HLINE, @width-2)
117
+ FFI::NCurses.mvwhline( @graphic.pointer, row, col, FFI::NCurses::ACS_HLINE, self.width()-2)
102
118
  end
103
119
 
104
120
  # print a title over the box on zeroth row
@@ -111,15 +127,16 @@ module Umbra
111
127
  when :left
112
128
  4
113
129
  when :right
114
- @width -stitle.size - 3
130
+ self.width -stitle.size - 3
115
131
  else
116
- (@width-stitle.size)/2
132
+ (self.width-stitle.size)/2
117
133
  end
118
134
  #FFI::NCurses.mvwaddstr(@pointer, 0, col, stitle)
119
- @graphic.printstring(@row, col, stitle)
135
+ @graphic.printstring(self.row, col, stitle)
120
136
  end
121
137
 
122
138
  private def print_border row, col, height, width, color, att=FFI::NCurses::A_NORMAL
139
+ $log.debug " PRINTING border with #{row} #{col} #{height} #{width} INSIDE BOX"
123
140
  pointer = @graphic.pointer
124
141
  FFI::NCurses.wattron(pointer, FFI::NCurses.COLOR_PAIR(color) | att)
125
142
  FFI::NCurses.mvwaddch pointer, row, col, FFI::NCurses::ACS_ULCORNER
@@ -4,7 +4,7 @@
4
4
  # Author: j kepler http://github.com/mare-imbrium/canis/
5
5
  # Date: 2018-04-01 - 16:08
6
6
  # License: MIT
7
- # Last update: 2018-04-01 16:21
7
+ # Last update: 2018-05-14 14:34
8
8
  # ----------------------------------------------------------------------------- #
9
9
  # checkbox.rb Copyright (C) 2012-2018 j kepler
10
10
  module Umbra
@@ -12,7 +12,7 @@ module Umbra
12
12
  # A checkbox, may be selected or unselected
13
13
  #
14
14
  class Checkbox < ToggleButton
15
- attr_accessor :align_right # the button will be on the right 2008-12-09 23:41
15
+ attr_property :align_right # the button will be on the right 2008-12-09 23:41
16
16
  # if a variable has been defined, off and on value will be set in it (default 0,1)
17
17
  def initialize config={}, &block
18
18
  @surround_chars = ['[', ']'] # 2008-12-23 23:16 added space in Button so overriding
data/lib/umbra/dialog.rb CHANGED
@@ -9,7 +9,7 @@
9
9
  # Author: j kepler http://github.com/mare-imbrium/canis/
10
10
  # Date: 2018-03-27 - 12:09
11
11
  # License: MIT
12
- # Last update: 2018-04-20 11:05
12
+ # Last update: 2018-04-22 23:11
13
13
  # ----------------------------------------------------------------------------- #
14
14
  # dialog.rb Copyright (C) 2012-2018 j kepler
15
15
  #
@@ -166,7 +166,6 @@ end # module
166
166
 
167
167
  # create a centered window. # {{{
168
168
  # NOTE: this should probably go into window class, or some util class.
169
- # TODO: it hardcodes background color. fix this.
170
169
  def create_centered_window height, width, color_pair=0, attrib=REVERSE
171
170
  row = ((FFI::NCurses.LINES-height)/2).floor
172
171
  col = ((FFI::NCurses.COLS-width)/2).floor
@@ -59,18 +59,18 @@ module Umbra
59
59
  aeve = @event_args[event]
60
60
  ablk.each_with_index do |blk, ix|
61
61
  #$log.debug "#{self} called EventHandler firehander #{@name}, #{event}, obj: #{object},args: #{aeve[ix]}"
62
- $log.debug "#{self} called EventHandler firehander #{@name}, #{event}"
62
+ # self prints the entire content of list or table!
63
+ $log.debug "EVENTHANDLER: #{self} called EventHandler firehander #{@name}, #{event}"
63
64
  begin
64
65
  blk.call object, *aeve[ix]
65
66
  rescue FieldValidationException => fve
66
67
  # added 2011-09-26 1.3.0 so a user raised exception on LEAVE
67
68
  # keeps cursor in same field.
68
69
  raise fve
69
- #rescue PropertyVetoException => pve
70
- # 2018-03-18 - commented off
70
+ rescue PropertyVetoException => pve
71
71
  # added 2011-09-26 1.3.0 so a user raised exception on LEAVE
72
72
  # keeps cursor in same field.
73
- #raise pve
73
+ raise pve
74
74
  rescue => ex
75
75
  ## some don't have name
76
76
  # FIXME this should be displayed somewhere. It just goes into log file quietly.
@@ -102,11 +102,59 @@ module Umbra
102
102
  end # if
103
103
  end # }}}
104
104
 
105
+ def fire_property_change text, oldvalue, newvalue
106
+ # canis returns if oldvalue is nil, but if object created with nil and later
107
+ # prop is set then we need a handler fired.
108
+ return if @_object_created.nil?
109
+ $log.debug " FPC #{self}: #{text} "
110
+ if @pce.nil?
111
+ @pce = PropertyChangeEvent.new(self, text, oldvalue, newvalue)
112
+ else
113
+ @pce.set( self, text, oldvalue, newvalue)
114
+ end
115
+ fire_handler :PROPERTY_CHANGE, @pce
116
+ @repaint_required = true
117
+ end
118
+
119
+ ## Created and sent to all listeners whenever a property is changed
120
+ # @see fire_property_change
121
+ # @see fire_handler
122
+ # @since 1.0.5 added 2010-02-25 23:06
123
+ class PropertyChangeEvent # {{{
124
+ attr_accessor :source, :property_name, :oldvalue, :newvalue
125
+ def initialize source, property_name, oldvalue, newvalue
126
+ set source, property_name, oldvalue, newvalue
127
+ end
128
+ def set source, property_name, oldvalue, newvalue
129
+ @source, @property_name, @oldvalue, @newvalue =
130
+ source, property_name, oldvalue, newvalue
131
+ end
132
+ def to_s
133
+ "PROPERTY_CHANGE name: #{property_name}, oldval: #{@oldvalue}, newvalue: #{@newvalue}, source: #{@source}"
134
+ end
135
+ def inspect
136
+ to_s
137
+ end
138
+ end # }}}
139
+
105
140
  # event? : returns boolean depending on whether this widget has registered the given event {{{
106
141
  def event? eve
107
142
  @_events.include? eve
108
143
  end # }}}
109
144
 
145
+ # The property change is not acceptable, undo it. e.g. test2.rb
146
+ # @param [String] text message
147
+ # @param [Event] PropertyChangeEvent object
148
+ # @since 1.4.0
149
+ class PropertyVetoException < RuntimeError
150
+ def initialize(string, event)
151
+ @string = string
152
+ @event = event
153
+ super(string)
154
+ end
155
+ attr_reader :string, :event
156
+ end
157
+
110
158
  # ActionEvent # {{{
111
159
  # source - as always is the object whose event has been fired
112
160
  # id - event identifier (seems redundant since we bind events often separately.
data/lib/umbra/field.rb CHANGED
@@ -4,7 +4,7 @@
4
4
  # Author: j kepler http://github.com/mare-imbrium/canis/
5
5
  # Date: 2018-03
6
6
  # License: MIT
7
- # Last update: 2018-04-14 08:55
7
+ # Last update: 2018-05-17 12:20
8
8
  # ----------------------------------------------------------------------------- #
9
9
  # field.rb Copyright (C) 2012-2018 j kepler
10
10
  #
@@ -38,7 +38,6 @@ class InputDataEvent # {{{
38
38
  end # }}}
39
39
  # Text edit field
40
40
  # TODO :
41
- # ? remove datatype, just use strings.
42
41
  # NOTE: +width+ is the length of the display whereas +maxlen+ is the maximum size that the value
43
42
  # can take. Thus, +maxlen+ can exceed +width+. Currently, +maxlen+ defaults to +width+ which
44
43
  # defaults to 20.
@@ -207,6 +206,9 @@ end # }}}
207
206
  # silently restores earlier value without firing handlers, use if exception and you want old value
208
207
  # Called when pressing <ESC> or <c-g>.
209
208
  def restore_original_value
209
+ $log.debug " FIELD: buffer:#{@buffer}. orig:#{@original_value}: "
210
+ $log.debug " original value is null " unless @original_value
211
+ $log.debug " buffer value is null " unless @buffer
210
212
  @buffer = @original_value.dup
211
213
  # earlier commented but trying again, since i am getting IndexError in insert 2188
212
214
  # Added next 3 lines to fix issue, now it comes back to beginning.
@@ -266,7 +268,7 @@ end # }}}
266
268
 
267
269
  def repaint
268
270
  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} ")
271
+ $log.debug("repaint FIELD: #{name}, r:#{row} c:#{col},wid:#{width},maxlen: #{@maxlen},pcol:#{@pcol}, #{focusable} st: #{@state} ")
270
272
  @width = 1 if width == 0
271
273
  printval = getvalue_for_paint().to_s # added 2009-01-06 23:27
272
274
  printval = mask()*printval.length unless @mask.nil?
@@ -480,6 +482,8 @@ end # }}}
480
482
  def on_enter
481
483
  #@original_value = getvalue.dup rescue getvalue
482
484
  @original_value = @buffer.dup # getvalue.dup rescue getvalue
485
+ $log.debug " FIELD ORIGINAL VALUE is null in on_enter" unless @original_value
486
+ $log.debug " on_enter: setting original_value to #{@original_value}"
483
487
  super
484
488
  end
485
489
  ##