rkumar-rbcurse 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.
Files changed (52) hide show
  1. data/CHANGELOG +1577 -0
  2. data/README.txt +310 -0
  3. data/examples/qdfilechooser.rb +68 -0
  4. data/examples/rfe.rb +853 -0
  5. data/examples/rfe_renderer.rb +69 -0
  6. data/examples/test1.rb +242 -0
  7. data/examples/test2.rb +498 -0
  8. data/examples/testcombo.rb +95 -0
  9. data/examples/testkeypress.rb +61 -0
  10. data/examples/testmenu.rb +105 -0
  11. data/examples/testtable.rb +266 -0
  12. data/examples/testtabp.rb +106 -0
  13. data/examples/testtodo.rb +532 -0
  14. data/examples/viewtodo.rb +512 -0
  15. data/lib/rbcurse.rb +7 -0
  16. data/lib/rbcurse/action.rb +31 -0
  17. data/lib/rbcurse/applicationheader.rb +57 -0
  18. data/lib/rbcurse/celleditor.rb +120 -0
  19. data/lib/rbcurse/checkboxcellrenderer.rb +69 -0
  20. data/lib/rbcurse/colormap.rb +133 -0
  21. data/lib/rbcurse/comboboxcellrenderer.rb +45 -0
  22. data/lib/rbcurse/defaultlistselectionmodel.rb +49 -0
  23. data/lib/rbcurse/keylabelprinter.rb +143 -0
  24. data/lib/rbcurse/listcellrenderer.rb +99 -0
  25. data/lib/rbcurse/listkeys.rb +33 -0
  26. data/lib/rbcurse/listscrollable.rb +216 -0
  27. data/lib/rbcurse/listselectable.rb +67 -0
  28. data/lib/rbcurse/mapper.rb +108 -0
  29. data/lib/rbcurse/orderedhash.rb +77 -0
  30. data/lib/rbcurse/rcombo.rb +243 -0
  31. data/lib/rbcurse/rdialogs.rb +183 -0
  32. data/lib/rbcurse/rform.rb +845 -0
  33. data/lib/rbcurse/rinputdataevent.rb +36 -0
  34. data/lib/rbcurse/rlistbox.rb +804 -0
  35. data/lib/rbcurse/rmenu.rb +666 -0
  36. data/lib/rbcurse/rmessagebox.rb +325 -0
  37. data/lib/rbcurse/rpopupmenu.rb +754 -0
  38. data/lib/rbcurse/rtabbedpane.rb +259 -0
  39. data/lib/rbcurse/rtable.rb +1296 -0
  40. data/lib/rbcurse/rtextarea.rb +673 -0
  41. data/lib/rbcurse/rtextview.rb +335 -0
  42. data/lib/rbcurse/rwidget.rb +1731 -0
  43. data/lib/rbcurse/scrollable.rb +301 -0
  44. data/lib/rbcurse/selectable.rb +94 -0
  45. data/lib/rbcurse/table/tablecellrenderer.rb +85 -0
  46. data/lib/rbcurse/table/tabledatecellrenderer.rb +102 -0
  47. data/lib/ver/keyboard.rb +150 -0
  48. data/lib/ver/keyboard2.rb +170 -0
  49. data/lib/ver/ncurses.rb +102 -0
  50. data/lib/ver/window.rb +369 -0
  51. data/test/test_rbcurse.rb +0 -0
  52. metadata +117 -0
@@ -0,0 +1,49 @@
1
+ module RubyCurses
2
+ class DefaultListSelectionModel
3
+ include EventHandler
4
+ attr_accessor :selection_mode
5
+ attr_reader :anchor_selection_index
6
+ attr_reader :lead_selection_index
7
+ def initialize
8
+ @selected_indices=[]
9
+ @anchor_selection_index = -1
10
+ @lead_selection_index = -1
11
+ @selection_mode = :MULTIPLE
12
+ end
13
+
14
+ def clear_selection
15
+ @selected_indices=[]
16
+ end
17
+ def is_selected_index ix
18
+ @selected_indices.include? ix
19
+ end
20
+ def get_max_selection_index
21
+ @selected_indices[-1]
22
+ end
23
+ def get_min_selection_index
24
+ @selected_indices[0]
25
+ end
26
+ def get_selected_rows
27
+ @selected_indices
28
+ end
29
+ ## TODO should go in sorted, and no dupes
30
+ def add_selection_interval ix0, ix1
31
+ if @selection_mode != :MULTIPLE
32
+ clear_selection
33
+ end
34
+ @anchor_selection_index = ix0
35
+ @lead_selection_index = ix1
36
+ ix0.upto(ix1) {|i| @selected_indices << i unless @selected_indices.include? i }
37
+ end
38
+ def remove_selection_interval ix0, ix1
39
+ @anchor_selection_index = ix0
40
+ @lead_selection_index = ix1
41
+ @selected_indices.delete_if {|x| x >= ix0 and x <= ix1}
42
+ end
43
+ def insert_index_interval ix0, len
44
+ @anchor_selection_index = ix0
45
+ @lead_selection_index = ix0+len
46
+ add_selection_interval @anchor_selection_index, @lead_selection_index
47
+ end
48
+ end # class DefaultListSelectionModel
49
+ end
@@ -0,0 +1,143 @@
1
+ require 'rbcurse/rwidget'
2
+ include Ncurses
3
+ include RubyCurses
4
+ module RubyCurses
5
+ class KeyLabelPrinter < Widget
6
+ attr_reader :key_labels
7
+ dsl_property :mode
8
+
9
+ def initialize form, key_labels, config={}, &block
10
+
11
+ super form, config, &block
12
+ @mode ||= :normal
13
+ #@key_labels = key_labels
14
+ @key_hash = {}
15
+ @key_hash[@mode] = key_labels
16
+ @editable = false
17
+ @focusable = false
18
+ @cols ||= Ncurses.COLS-1
19
+ @row ||= Ncurses.LINES-3
20
+ @col ||= 0
21
+ @repaint_required = true
22
+ @footer_color_pair ||= $bottomcolor
23
+ @footer_mnemonic_color_pair ||= $reversecolor #2
24
+ end
25
+ def key_labels mode=@mode
26
+ @key_hash[mode]
27
+ end
28
+ # returns the keys as printed. these may or may not help
29
+ # in validation depedign on what you passed as zeroth index
30
+ def get_current_keys
31
+ a = []
32
+ @key_hash[@mode].each do |arr|
33
+ a << arr[0] unless arr.nil?
34
+ end
35
+ return a
36
+ end
37
+ def getvalue
38
+ @key_hash
39
+ end
40
+ def set_key_labels _key_labels, mode=:normal
41
+ @key_hash[mode] = _key_labels
42
+ end
43
+
44
+ ##
45
+ # XXX need to move wrapping etc up and done once.
46
+ def repaint
47
+ return unless @repaint_required
48
+ r,c = rowcol
49
+ print_key_labels(arr = key_labels(), mode=@mode)
50
+ @repaint_required = false
51
+ end
52
+ def append_key_label key, label, mode=@mode
53
+ @key_labels << [key, label] if !@key_labels.include? [key, label]
54
+ @repaint_required = true
55
+ end
56
+ def print_key_labels(arr = key_labels(), mode=@mode)
57
+ #return if !@show_key_labels # XXX
58
+ @win ||= @form.window
59
+ @padding = @cols / (arr.length/2)
60
+ posx = 0
61
+ even = []
62
+ odd = []
63
+ arr.each_index { |i|
64
+ if i % 2 == 0
65
+ #arr[i+1] = ['',''] if arr[i+1].nil?
66
+ nextarr = arr[i+1] || ['', '']
67
+ keyw = [arr[i][0].length, nextarr[0].length].max
68
+ labelw = [arr[i][1].length, nextarr[1].length].max
69
+
70
+ even << [ sprintf("%*s", keyw, arr[i][0]), sprintf("%-*s", labelw, arr[i][1]) ]
71
+ odd << [ sprintf("%*s", keyw, nextarr[0]), sprintf("%-*s", labelw, nextarr[1]) ]
72
+ #$log.debug("loop even: #{even.inspect}")
73
+ else
74
+ end
75
+ }
76
+ #$log.debug("even: #{even.inspect}")
77
+ #$log.debug("odd : #{odd.inspect}")
78
+ #posy = @barrow-1
79
+ posy = @row
80
+ print_key_labels_row(posy, posx, even)
81
+ posy = @row+1
82
+ print_key_labels_row(posy, posx, odd)
83
+ #@win.wrefresh # needed else secod row not shown after askchoice XXX
84
+ end
85
+ def print_key_labels_row(posy, posx, arr)
86
+ # FIXME: this logic of padding needs to take into account
87
+ # width of window
88
+ padding = 8
89
+ padding = 4 if arr.length > 5
90
+ padding = 2 if arr.length > 7
91
+ padding = 0 if arr.length > 9
92
+ #padding = @padding # XXX 2008-11-13 23:01
93
+ my_form_win = @win
94
+ @win.printstring(posy,0, "%-*s" % [@cols," "], @footer_color_pair, @attr)
95
+ arr.each do |kl|
96
+ key = kl[0]
97
+ lab = kl[1]
98
+ if key !="" # don't print that white blank space for fillers
99
+ color_pair= @footer_mnemonic_color_pair # $reversecolor #2
100
+ x = posx + (key.length - key.strip.length)
101
+ my_form_win.attron(Ncurses.COLOR_PAIR(color_pair))
102
+ my_form_win.mvprintw(posy, x, "%s" % kl[0].strip );
103
+ my_form_win.attroff(Ncurses.COLOR_PAIR(color_pair))
104
+ end
105
+ color_pair=@footer_color_pair
106
+ posx = posx + kl[0].length
107
+ my_form_win.attron(Ncurses.COLOR_PAIR(color_pair))
108
+
109
+ #lab = sprintf(" %s %*s" , kl[1], padding, " ");
110
+ lab = sprintf(" %s %s" , kl[1], " "*padding);
111
+ my_form_win.mvprintw(posy, posx, lab)
112
+ my_form_win.attroff(Ncurses.COLOR_PAIR(color_pair))
113
+ posx = posx + lab.length
114
+ end
115
+ end
116
+ ##
117
+ # updates existing label with a new one.
118
+ # @return true if updated, else false
119
+ def update_application_key_label(display_code, new_display_code, text)
120
+ @repaint_required = true
121
+ labels = key_labels()
122
+ labels.each_index do |ix|
123
+ lab = labels[ix]
124
+ if lab[0] == display_code
125
+ labels[ix] = [new_display_code , text]
126
+ $log.debug("updated #{labels[ix]}")
127
+ return true
128
+ end
129
+ end
130
+ return false
131
+ end
132
+ ##
133
+ # inserts an application label at given index
134
+ # to add the key, use create_datakeys to add bindings
135
+ # remember to call restore_application_key_labels after updating/inserting
136
+ def insert_application_key_label(index, display_code, text)
137
+ @repaint_required = true
138
+ labels = key_labels()
139
+ labels.insert(index, [display_code , text] )
140
+ end
141
+ # ADD HERE KEYLABEL
142
+ end
143
+ end
@@ -0,0 +1,99 @@
1
+ require 'rubygems'
2
+ require 'ncurses'
3
+ require 'logger'
4
+ require 'rbcurse/rwidget'
5
+ module RubyCurses
6
+
7
+ ##
8
+ # This is a basic list cell renderer that will render the to_s value of anything.
9
+ # Using alignment one can use for numbers too.
10
+ # However, for booleans it will print true and false. If editing, you may want checkboxes
11
+ class ListCellRenderer
12
+ #include DSL
13
+ #include EventHandler
14
+ include RubyCurses::ConfigSetup
15
+ include RubyCurses::Utils
16
+ dsl_accessor :justify # :right, :left, :center # added 2008-12-22 19:02
17
+ dsl_accessor :display_length # please give this to ensure the we only print this much
18
+ dsl_accessor :height # if you want a multiline label.
19
+ dsl_accessor :text # text of label
20
+ dsl_accessor :color, :bgcolor
21
+ dsl_accessor :row, :col
22
+ dsl_accessor :parent #usuall the table to get colors and other default info
23
+
24
+ def initialize text="", config={}, &block
25
+ @text = text
26
+ @editable = false
27
+ @focusable = false
28
+ config_setup config # @config.each_pair { |k,v| variable_set(k,v) }
29
+ instance_eval &block if block_given?
30
+ init_vars
31
+ end
32
+ def init_vars
33
+ @justify ||= :left
34
+ @display_length ||= 10
35
+ end
36
+ def getvalue
37
+ @text
38
+ end
39
+ ##
40
+ # sets @color_pair and @attr
41
+ def prepare_default_colors focussed, selected
42
+ @color_pair = get_color $datacolor
43
+ #acolor =get_color $datacolor, @color || @parent.color, @bgcolor || @parent.bgcolor #unless @parent.nil?
44
+ @attr = @row_attr || Ncurses::A_NORMAL
45
+ ##@row_attr = Ncurses::A_NORMAL # added 2009-02-04 18:35 since overriding in rfe
46
+
47
+
48
+ ## determine bg and fg and attr
49
+ if selected
50
+ @attr = Ncurses::A_BOLD if selected
51
+ @color_pair =get_color $selectedcolor, @parent.selected_color, @parent.selected_bgcolor unless @parent.nil?
52
+ end
53
+ if focussed
54
+ @attr |= Ncurses::A_REVERSE
55
+ end
56
+ end
57
+
58
+ ##
59
+ #
60
+ def repaint graphic, r=@row,c=@col, row_index=-1,value=@text, focussed=false, selected=false
61
+ #$log.debug "label :#{@text}, #{value}, #{r}, #{c} col= #{@color}, #{@bgcolor} acolor= #{acolor} j:#{@justify} dlL: #{@display_length} "
62
+
63
+ prepare_default_colors focussed, selected
64
+
65
+ lablist = []
66
+ value=value.to_s # ??
67
+ if @height && @height > 1
68
+ lablist = wrap_text(value, @display_length).split("\n")
69
+ else
70
+ # ensure we do not exceed
71
+ if !@display_length.nil?
72
+ if value.length > @display_length
73
+ value = value[0..@display_length-1]
74
+ end
75
+ end
76
+ lablist << value
77
+ end
78
+ len = @display_length || value.length
79
+ _height = @height || 1
80
+ str = @justify.to_sym == :right ? "%*s" : "%-*s" # added 2008-12-22 19:05
81
+ # loop added for labels that are wrapped.
82
+ # clear separately since value can change in status like labels
83
+ #len -= @left_margin
84
+ 0.upto(_height-1) { |i|
85
+ graphic.printstring r+i, c, ( " " * len) , @color_pair,@attr
86
+ }
87
+ lablist.each_with_index do |_value, ix|
88
+ break if ix >= _height
89
+ if @justify.to_sym == :center
90
+ padding = (@display_length - _value.length)/2
91
+ _value = " "*padding + _value + " "*padding # so its cleared if we change it midway
92
+ end
93
+ graphic.printstring r, c, str % [len, _value], @color_pair,@attr
94
+ r += 1
95
+ end
96
+ end
97
+ # ADD HERE
98
+ end
99
+ end
@@ -0,0 +1,33 @@
1
+ module RubyCurses
2
+ module ListKeys
3
+ ## Note: keeping variables gives the false feeling that one can change the var anytime.
4
+ # That was possible earlier, but now that i am binding the key at construction time
5
+ # any changes to the vars after construction won't have an effect.
6
+ def install_list_keys
7
+ @KEY_ROW_SELECTOR ||= ?\C-x
8
+ @KEY_GOTO_TOP ||= ?\M-0
9
+ @KEY_GOTO_BOTTOM ||= ?\M-9
10
+ @KEY_ASK_FIND_FORWARD ||= ?\M-f
11
+ @KEY_ASK_FIND_BACKWARD ||= ?\M-F
12
+ @KEY_FIND_NEXT ||= ?\M-g
13
+ @KEY_FIND_PREV ||= ?\M-G
14
+ @KEY_SCROLL_FORWARD ||= ?\C-n
15
+ @KEY_SCROLL_BACKWARD ||= ?\C-p
16
+
17
+ @KEY_CLEAR_SELECTION ||= ?\M-e
18
+ @KEY_PREV_SELECTION ||= ?\M-"
19
+ @KEY_NEXT_SELECTION ||= ?\M-'
20
+
21
+ =begin
22
+ bind_key(@KEY_ROW_SELECTOR) { toggle_row_selection }
23
+ bind_key(@KEY_GOTO_TOP) { goto_top }
24
+ bind_key(@KEY_GOTO_BOTTOM) { goto_bottom }
25
+ bind_key(@KEY_CLEAR_SELECTION) { clear_selection }
26
+ bind_key(@KEY_ASK_FIND_FORWARD) { ask_search_forward }
27
+ bind_key(@KEY_ASK_FIND_BACKWARD) { ask_search_backward }
28
+ bind_key(@KEY_FIND_NEXT) { find_next }
29
+ bind_key(@KEY_FIND_PREV) { find_prev }
30
+ =end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,216 @@
1
+ # Provides the ability to scroll content, typically an array
2
+ # widget that includes may override on_enter_row and on_leave_row
3
+ # Caller should have
4
+ # row_count()
5
+ # scrollatrow() typically @height - 2 (unless a header row, then -3)
6
+ # @current_index (row of current index, starting with 0 usually)
7
+ # @toprow : set to 0 for starters, top row to be displayed
8
+ # @pcol (used for horiz scrolling, starts at 0)
9
+ #
10
+ module ListScrollable
11
+ def previous_row
12
+ @oldrow = @current_index
13
+ @current_index -= 1 if @current_index > 0
14
+ bounds_check
15
+ end
16
+ alias :up :previous_row
17
+ def next_row
18
+ @oldrow = @current_index
19
+ rc = row_count
20
+ @current_index += 1 if @current_index < rc
21
+ bounds_check
22
+ end
23
+ alias :down :next_row
24
+ def goto_bottom
25
+ @oldrow = @current_index
26
+ rc = row_count
27
+ @current_index = rc -1
28
+ bounds_check
29
+ end
30
+ alias :goto_end :goto_bottom
31
+ def goto_top
32
+ @oldrow = @current_index
33
+ @current_index = 0
34
+ bounds_check
35
+ end
36
+ alias :goto_start :goto_top
37
+ def scroll_backward
38
+ @oldrow = @current_index
39
+ h = scrollatrow()
40
+ @current_index -= h
41
+ bounds_check
42
+ end
43
+ def scroll_forward
44
+ @oldrow = @current_index
45
+ h = scrollatrow()
46
+ rc = row_count
47
+ # more rows than box
48
+ if h < rc
49
+ @toprow += h+1 #if @current_index+h < rc
50
+ @current_index = @toprow
51
+ else
52
+ # fewer rows than box
53
+ @current_index = rc -1
54
+ end
55
+ #@current_index += h+1 #if @current_index+h < rc
56
+ bounds_check
57
+ end
58
+
59
+ ##
60
+ # please set oldrow before calling this. Store current_index as oldrow before changing. NOTE
61
+ def bounds_check
62
+ h = scrollatrow()
63
+ rc = row_count
64
+ $log.debug " PRE CURR:#{@current_index}, TR: #{@toprow} RC: #{rc} H:#{h}"
65
+ @current_index = 0 if @current_index < 0 # not lt 0
66
+ @current_index = rc-1 if @current_index >= rc # not gt rowcount
67
+ @toprow = rc-h-1 if rc > h and @toprow > rc - h - 1 # toprow shows full page if possible
68
+ # curr has gone below table, move toprow forward
69
+ if @current_index - @toprow > h
70
+ @toprow = @current_index - h
71
+ elsif @current_index < @toprow
72
+ # curr has gone above table, move toprow up
73
+ @toprow = @current_index
74
+ end
75
+ #$log.debug " POST CURR:#{@current_index}, TR: #{@toprow} RC: #{rc} H:#{h}"
76
+ if @oldrow != @current_index
77
+ $log.debug "going to call on leave and on enter"
78
+ on_leave_row @oldrow if respond_to? :on_leave_row # to be defined by widget that has included this
79
+ on_enter_row @current_index if respond_to? :on_enter_row # to be defined by widget that has included this
80
+ end
81
+ set_form_row
82
+ @repaint_required = true
83
+ end
84
+ # the cursor should be appropriately positioned
85
+ def set_form_row
86
+ r,c = rowcol
87
+ @form.row = r + (@current_index-@toprow)
88
+ end
89
+ def right
90
+ @hscrollcols ||= @cols/2
91
+ @pcol += @hscrollcols if @pcol + @hscrollcols < @padcols
92
+ # window_erase @win XXX
93
+ end
94
+ def left
95
+ @hscrollcols ||= @cols/2
96
+ @pcol -= @hscrollcols if @pcol > 0
97
+ @pcol = 0 if @pcol < 0
98
+ end
99
+ # not that saving content_rows is buggy since we add rows.
100
+ ##
101
+ # caution, this now uses winrow not prow
102
+ ## for user to know which row is being focussed on
103
+ def focussed_index
104
+ @current_index # 2009-01-07 14:35
105
+ end
106
+ # only to be used in single selection cases as focussed item FIXME.
107
+ # best not to use, as can be implementation dep, use current_index
108
+ def selected_item
109
+ get_content()[focussed_index()]
110
+ end
111
+ #alias :current_index :focussed_index
112
+ alias :selected_index :focussed_index
113
+ def OLDscrollable_handle_key ch
114
+ begin
115
+ ###pre_key # 2009-01-07 13:23
116
+ case ch
117
+ when ?\C-n
118
+ scroll_forward
119
+ when 32
120
+ scroll_forward
121
+ when ?\C-p
122
+ scroll_backward
123
+ when ?0
124
+ #goto_start
125
+ goto_top
126
+ when ?9
127
+ #goto_end
128
+ goto_bottom
129
+ when KEY_UP
130
+ #select_prev_row
131
+ #up
132
+ $log.debug " GOT KEY UP NEW SCROLL"
133
+ previous_row
134
+ when KEY_LEFT
135
+ when KEY_RIGHT
136
+ when KEY_DOWN
137
+ #down
138
+ $log.debug " GOT KEY DOWN NEW SCROLL"
139
+ next_row
140
+ when KEY_ENTER, 10, 13
141
+ if respond_to? :fire
142
+ fire
143
+ end
144
+ when ?A..?Z, ?a..?z
145
+ ret = set_selection_for_char ch.chr
146
+ else
147
+ return :UNHANDLED #if ret == -1
148
+ end
149
+ ensure
150
+ #post_key
151
+ end
152
+ end # handle_k listb
153
+ ## 2008-12-18 18:03
154
+ # finds the next match for the char pressed
155
+ # returning the index
156
+ def next_match char
157
+ data = get_content
158
+ row = focussed_index + 1
159
+ row.upto(data.length-1) do |ix|
160
+ val = data[ix].chomp
161
+ #if val[0,1] == char #and val != currval
162
+ if val[0,1].casecmp(char) == 0 #AND VAL != CURRval
163
+ return ix
164
+ end
165
+ end
166
+ row = focussed_index - 1
167
+ 0.upto(row) do |ix|
168
+ val = data[ix].chomp
169
+ #if val[0,1] == char #and val != currval
170
+ if val[0,1].casecmp(char) == 0 #and val != currval
171
+ return ix
172
+ end
173
+ end
174
+ return -1
175
+ end
176
+ ## 2008-12-18 18:03
177
+ # sets the selection to the next row starting with char
178
+ def set_selection_for_char char
179
+ @oldrow = @current_index
180
+ ix = next_match char
181
+ @current_index = ix if ix != -1
182
+ bounds_check
183
+ return ix
184
+ end
185
+
186
+ ##
187
+ # ensures that the given row is focussed
188
+ # new version of older one that was not perfect.
189
+ # 2009-01-17 13:25
190
+ def set_focus_on arow
191
+ @oldrow = @current_index
192
+ @current_index = arow
193
+ bounds_check if @oldrow != @current_index
194
+ end
195
+ ##
196
+ # 2008-12-18 18:05
197
+ # set focus on given index
198
+ def OLDset_focus_on arow
199
+ return if arow > row_count()-1 or arow < 0
200
+ @oldrow = @current_index
201
+ total = row_count()
202
+ @current_index = arow
203
+ sar = scrollatrow + 1
204
+ @toprow = (@current_index / sar) * sar
205
+
206
+ $log.debug "1 set_focus #{total}, sar #{sar}, toprow #{@toprow}, current_index #{@current_index}"
207
+ if total - @toprow < sar
208
+ @toprow = (total - sar)
209
+ end
210
+ $log.debug "2 set_focus #{total}, sar #{sar}, toprow #{@toprow}, current_index #{@current_index}"
211
+ set_form_row # 2009-01-17 12:44
212
+ @repaint_required = true
213
+ #bounds_check
214
+ end
215
+
216
+ end