rbcurse 1.5.0 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/Makefile +21 -0
  2. data/Manifest.txt +6 -0
  3. data/README.markdown +6 -4
  4. data/TODO +372 -0
  5. data/TODO2.txt +121 -0
  6. data/VERSION +1 -1
  7. data/examples/README.txt +67 -0
  8. data/examples/abasiclist.rb +33 -0
  9. data/examples/alpmenu.rb +42 -0
  10. data/examples/app.rb +859 -0
  11. data/examples/app.sample +17 -0
  12. data/examples/appdirtree.rb +74 -0
  13. data/examples/appemail.rb +191 -0
  14. data/examples/appemaillb.rb +308 -0
  15. data/examples/appgcompose.rb +315 -0
  16. data/examples/atree.rb +64 -0
  17. data/examples/common/file.rb +40 -0
  18. data/examples/common/rmail.rb +257 -0
  19. data/examples/data.txt +683 -0
  20. data/examples/data/README.markdown +9 -0
  21. data/examples/data/brew.txt +38 -0
  22. data/examples/data/color.2 +37 -0
  23. data/examples/data/gemlist.txt +60 -0
  24. data/examples/data/lotr.txt +12 -0
  25. data/examples/data/ports.txt +136 -0
  26. data/examples/data/tasks.txt +27 -0
  27. data/examples/data/todocsv.csv +28 -0
  28. data/examples/data/unix1.txt +21 -0
  29. data/examples/data/unix2.txt +11 -0
  30. data/examples/dbdemo.rb +495 -0
  31. data/examples/deprecated/appgmail.rb +952 -0
  32. data/examples/deprecated/splitp.rb +56 -0
  33. data/examples/deprecated/testscrolllb.rb +86 -0
  34. data/examples/deprecated/testscrollp.rb +88 -0
  35. data/examples/deprecated/testscrollta.rb +80 -0
  36. data/examples/deprecated/testscrolltable.rb +165 -0
  37. data/examples/deprecated/testsplit.rb +87 -0
  38. data/examples/deprecated/testsplit2.rb +123 -0
  39. data/examples/deprecated/testsplit3.rb +215 -0
  40. data/examples/deprecated/testsplit3_1.rb +244 -0
  41. data/examples/deprecated/testsplit3a.rb +215 -0
  42. data/examples/deprecated/testsplit3b.rb +237 -0
  43. data/examples/deprecated/testsplitta.rb +148 -0
  44. data/examples/deprecated/testsplittv.rb +142 -0
  45. data/examples/deprecated/testsplittvv.rb +144 -0
  46. data/examples/deprecated/testtpane.rb +215 -0
  47. data/examples/deprecated/testtpane2.rb +145 -0
  48. data/examples/deprecated/testtpanetable.rb +203 -0
  49. data/examples/dirtree.rb +88 -0
  50. data/examples/experimental/resultsetdemo.rb +280 -0
  51. data/examples/experimental/testmform.rb +35 -0
  52. data/examples/experimental/testscroller.rb +117 -0
  53. data/examples/experimental/teststackflow.rb +111 -0
  54. data/examples/menu1.rb +112 -0
  55. data/examples/multispl.rb +86 -0
  56. data/examples/newmessagebox.rb +131 -0
  57. data/examples/newtabbedwindow.rb +100 -0
  58. data/examples/newtesttabp.rb +121 -0
  59. data/examples/qdfilechooser.rb +68 -0
  60. data/examples/rfe.rb +1239 -0
  61. data/examples/rfe_renderer.rb +121 -0
  62. data/examples/sqlc.rb +454 -0
  63. data/examples/sqlm.rb +437 -0
  64. data/examples/sqlt.rb +408 -0
  65. data/examples/status.txt +68 -0
  66. data/examples/table1.rb +24 -0
  67. data/examples/term2.rb +84 -0
  68. data/examples/test1.rb +239 -0
  69. data/examples/test2.rb +674 -0
  70. data/examples/testapp.rb +44 -0
  71. data/examples/testapp2.rb +58 -0
  72. data/examples/testchars.rb +137 -0
  73. data/examples/testcombo.rb +91 -0
  74. data/examples/testkeypress.rb +66 -0
  75. data/examples/testlistbox.rb +113 -0
  76. data/examples/testmenu.rb +101 -0
  77. data/examples/testmulticomp.rb +70 -0
  78. data/examples/testmulticontainer.rb +94 -0
  79. data/examples/testmultispl.rb +199 -0
  80. data/examples/testree.rb +106 -0
  81. data/examples/testtable.rb +264 -0
  82. data/examples/testtabp.rb +107 -0
  83. data/examples/testtodo.rb +584 -0
  84. data/examples/testvimsplit.rb +112 -0
  85. data/examples/testwsshortcuts.rb +64 -0
  86. data/examples/testwsshortcuts2.rb +126 -0
  87. data/examples/todo.db +0 -0
  88. data/examples/todo.yml +191 -0
  89. data/examples/viewtodo.rb +574 -0
  90. data/lib/rbcurse/deprecated/README.markdown +12 -0
  91. data/lib/rbcurse/deprecated/rpad.rb +375 -0
  92. data/lib/rbcurse/deprecated/rscrollpane.rb +512 -0
  93. data/lib/rbcurse/deprecated/rsplitpane.rb +894 -0
  94. data/lib/rbcurse/deprecated/rsplitpane2.rb +1009 -0
  95. data/lib/rbcurse/deprecated/rviewport.rb +204 -0
  96. data/lib/rbcurse/deprecated/widgets/mapper.rb +130 -0
  97. data/lib/rbcurse/deprecated/widgets/rmessagebox.rb +348 -0
  98. data/lib/rbcurse/deprecated/widgets/rtabbedpane.rb +1158 -0
  99. data/lib/rbcurse/deprecated/widgets/rtabbedwindow.rb +167 -0
  100. data/lib/rbcurse/deprecated/widgets/scrollable.rb +301 -0
  101. data/lib/rbcurse/deprecated/widgets/stdscrwindow.rb +309 -0
  102. data/lib/ver/keyboard2.rb +170 -0
  103. data/test/test_rbcurse.rb +0 -0
  104. metadata +131 -9
@@ -0,0 +1,12 @@
1
+ == Short Story
2
+
3
+ If you are new here, don't touch anything in this directory.
4
+
5
+ == Long Story
6
+
7
+ This directory contains stuff that was once used, but has since been rewritten in a simpler form.
8
+ Thus, I've replaced this with the simpler form. This still exists for anyone who was using it.
9
+
10
+ Some old stuff was either rather ambitiously rewritten or written awfully like MessageBox. I've got a more sensible version up now. Stuff here will *NOT* be maintained by me anylonger.
11
+
12
+ There's also stuff here that will *NOT* work any longer such as SplitPanes and ScrollPanes. Support for them has been removed from the core (Form, widget and window) since it was complicating the core too much.
@@ -0,0 +1,375 @@
1
+ require 'ver/window'
2
+
3
+ # This contains pad and subwin.
4
+ #
5
+ # 1. IMHO, subwins and derwins are not very stable. Avoid using them. I've tinkered
6
+ # with them quite a bit and given them up.
7
+ # 2. Pads are quite okay, I tried something too complex, and copywin often can give
8
+ # errors, or seg faults. So i've steered away from the Pad class. I may try a simpler
9
+ # less clever pad approach to textview sometime again.
10
+
11
+ module VER
12
+ ##
13
+ # Pad
14
+ # This is EXPERIMENTAL
15
+ # A pad cannot be used interchangeable since some application functions such as wrefresh
16
+ # are illegal. Cannot expect the application to take care.
17
+ # Internally we can make it easier. Mostly a pad is used to map to one portion of the screen.
18
+ # So we allow that to be defined once. Then only start row and col of pad change.
19
+ # Maybe we should check pad coordinates so no errors
20
+ # Also check screen coordinates (if we know)
21
+ # We need padheight and padwidth only to ensure we don't keep recreating.
22
+ # Howevre, when comp's height increases, then decreases, pad height remains larger
23
+ # but we keep printing an extra row in copywin. so Pad needs to maintain comp height
24
+ # and padheight.
25
+ # @since 0.1.3
26
+ # NOTE used only by TabbedPane. If we rewrite without using it in 1.3.1 then scrap.
27
+ # 2011-11-8 Now the new simpler TabbedPane does not use pads.
28
+ # The aim o this class was to act as a replacement for window, making it seamless
29
+ # to use a pad instead
30
+ class Pad < VER::Window
31
+ # top and left correspond to screen's top and left wich will mostly be fixed
32
+ attr_accessor :top, :left
33
+ # start row and col correspond to pad's top and left which will change if scrolling
34
+ attr_accessor :pminrow, :pmincol
35
+ # screen's height and width, now it reflects components height and width
36
+ attr_accessor :sheight, :swidth
37
+ attr_reader :otherwin
38
+ # dimensions the pad was created with, used so we don't keep recreating pad, only if increase.
39
+ attr_reader :padheight, :padwidth
40
+ #attr_accessor :name # more for debugging log files. 2010-02-02 19:58
41
+ def initialize(height, width)
42
+ @visible = true
43
+ # do we set height and width ?? XXX
44
+ @window = Ncurses.newpad(height, width)
45
+ @padheight = height
46
+ @padwidth = width
47
+ @height = height
48
+ @width = width
49
+ @sheight = height
50
+ @swidth = width
51
+ init_vars
52
+ end
53
+ def init_vars
54
+ super
55
+ @top ||= 0; @left ||= 0
56
+ @pmincol ||= 0 # pad will print from this col
57
+ @pminrow ||= 0 # pad will print from this row
58
+ @window_type = :PAD
59
+ @name ||="#{self}"
60
+ $log.debug " PAD constructor #{self} , #{@window} "
61
+ end
62
+ #
63
+ # @param layout is a hash (@see Window.initialize)
64
+ def self.create_with_layout(layout)
65
+ @window = Pad.new(layout[:height], layout[:width])
66
+ @window.reset_layout(layout)
67
+ return @window
68
+ end
69
+ ##
70
+ # increases the pad size, since the widget may have been resized
71
+ # checks that one of ht or width has been increased
72
+ # destroys earlier pad and returns new one
73
+ # Updates sheight and swidth even if reduced so copywin works fine.
74
+ # @param [Fixnum] height to resize to
75
+ # @param [Fixnum] width to resize to
76
+ # @return [Pad]
77
+ # 2009-10-29 23:18
78
+ def resize(ht = 0, w = 0)
79
+ # update sheight and swidth even if reduced, so that pad doesn't overwrite.
80
+ @sheight = ht if ht > 0
81
+ @swidth = w if w > 0
82
+ return if ht < @padheight and w < @padwidth
83
+ @padheight = ht if ht > @padheight
84
+ @padwidth = w if w > @padwidth
85
+ destroy
86
+ $log.debug " L502 resize, creating newpad with #{@padheight} and #{@padwidth} "
87
+ @window = Ncurses.newpad(@padheight, @padwidth)
88
+ $log.debug " L502 resize created #{@window} "
89
+ return @window
90
+ end
91
+ ## used if pad and window are same size only
92
+ # creates a similar sized window
93
+ # assumes window is backed by this pad
94
+ # @param object of Window class
95
+ def self.create_for_window(win)
96
+ # get coordinates for win
97
+ @otherwin = win
98
+ smaxx = win.getmaxx()
99
+ smaxy = win.getmaxy()
100
+ top = win.getminx()
101
+ left = win.getminy()
102
+ sheight = win.height
103
+ swidth = win.width
104
+ # make pad based on size of window
105
+ window = Pad.create_with_layout(layout = { :height => sheight, :width => swidth, :top => top, :left => sleft })
106
+ window.sheight = sheight
107
+ window.swidth = swidth
108
+ return window
109
+
110
+ end
111
+ # top and left correspond to screen's top and left wich will mostly be fixed.
112
+ # In cases where the component may float around, as in Splitpanes second component
113
+ # this would be set using component's row and col.
114
+ def set_screen_row_col top, left=-1
115
+ @top = top
116
+ @left = left unless left < 0
117
+ end
118
+ alias :set_screen_pad_left :set_screen_row_col
119
+
120
+ ## added user setting screens max row and col (e.g splitpanes first component)
121
+ def set_screen_max_row_col mr, mc
122
+ $log.debug "#{@name} set_screen_max_row_col #{mr},#{mc}. earlier #{@screen_maxrow}, #{@screen_maxcol} "
123
+ # added || check on 2010-01-09 18:39 since crashing if mr > sh + top ..
124
+ # I removed the check, since it results in a blank area on screen since the
125
+ # widget has not expanded itself. Without the check it will crash on copywin so you
126
+ # should increase widget size or disallow calling this in this situation.
127
+ if mr > (@sheight + @top -1 -@pminrow)
128
+ $log.warn " ->>> ** set_screen_max_row_col #{mr} > #{@sheight} + #{@top} -1 - #{@pminrow} ** "
129
+ $log.warn " ->>> can result in error in copy_win or in some rows not displaying"
130
+ return # some situations actually require this ...
131
+ end unless mr.nil?
132
+ @screen_maxrow = mr unless mr.nil? # || mr > (@sheight + @top -1 -@pminrow)
133
+ @screen_maxcol = mc unless mc.nil?
134
+ end
135
+ # start row and col correspond to pad's top and left which will change if scrolling
136
+ # However, if we use this as a backing store for subwindows it could remain the same
137
+ def set_pad_top_left top, left=-1
138
+ $log.debug "#{@name} inside set_pad_top_left to #{top} #{left} earlier #{@pminrow}, #{@pmincol}"
139
+ @pminrow = top unless top < 0
140
+ @pmincol = left unless left < 0
141
+ end
142
+ # return screen max row which will be used for writing to window
143
+ # XXX what if user sets/overrides sheight
144
+ def smaxrow
145
+ #$log.debug " ... niside smaxrow #{@sheight} + #{@top} -1 "
146
+ #@sheight + @top -1
147
+ $log.debug "smr: #{@screen_maxrow} ... niside smaxrow #{@sheight} + #{@top} -1 - #{@pminrow}"
148
+ @screen_maxrow || @sheight + @top -1 -@pminrow
149
+ end
150
+ ##
151
+ # return screen max col which will be used for writing to window
152
+ def smaxcol
153
+ #$log.debug " ... niside smaxcol #{@swidth} + #{@left} -1 "
154
+ #@swidth + @left -1
155
+ # $log.debug " ... niside smaxcol #{@swidth} + #{@left} -1 - #{@pmincol} "
156
+ @screen_maxcol || @swidth + @left -1 - @pmincol
157
+ end
158
+ ##
159
+ # specify the window or subwin that the pad is writing to
160
+ # 2010-02-20 22:45 - actually since there are pad methods smaxrow used on otherwin
161
+ # therefor it can only be a Pad !! NOTE
162
+ def set_backing_window win
163
+ @otherwin = win
164
+ # XX should we extract the coordinates and use for printing ??
165
+ # or for setting maxrow and maxcol
166
+ end
167
+ # trying to make things as easy as possible
168
+ # returns -1 if error in prefresh
169
+ def wrefresh
170
+ $log.debug " inside pad's wrefresh #{@window}. minr,minc,top,left,smaxr,c: #{@pminrow}, #{@pmincol}, #{@top} #{@left} #{smaxrow()} #{smaxcol()} self: #{self.name} "
171
+
172
+ # caution, prefresh uses maxrow and maxcol not height and width
173
+ # so we have to add top and less one since we are zero based
174
+ ret = @window.prefresh(@pminrow, @pmincol, @top, @left, smaxrow(), smaxcol())
175
+ $log.warn " WREFRESH returns -1 ERROR - width or height must be exceeding " if ret == -1
176
+ @modified = false
177
+ return ret
178
+ end
179
+ ##
180
+ # copy the window to the pad (assumes we are writing onto win and keeping
181
+ # pad as backup
182
+ # also assuming only one win so, window not passed as param
183
+ # @return return value of copywin which should be 0 (-1 is ERR)
184
+ def copy_pad_to_win
185
+ $log.warn " DEPRECATED copy_pad_to_win" # CLEANUP
186
+ raise "DEPREC copy_pad_to_win deprecated. Will be removed. Let me know if it is needed"
187
+ # check that we don't exceed other windows height/maxrow
188
+ smr = smaxrow()
189
+ # SHIT, this means the otherwin has to be a Pad, cannot be a window
190
+ osw = @otherwin.width
191
+ osh = @otherwin.height
192
+ osh = @height if osh == 0 # root window has 0
193
+ osw = @width if osw == 0 # root window has 0
194
+ osmr = @otherwin.smaxrow() rescue osh # TRYING for windows
195
+ osmc = @otherwin.smaxcol() rescue osw
196
+ if smr >= osmr
197
+ $log.debug " adjusted smr from #{smr} to #{osmr} -1 causing issues in viewfooter"
198
+ smr = osmr-1 # XXX causing issues in viewport, wont print footer with this
199
+ end
200
+ if smr > @sheight + @top -1 -@pminrow # 2010-01-17 13:27
201
+ smr = @sheight + @top -1 -@pminrow
202
+ $log.debug " adjusted smr to #{smr} to prevent crash "
203
+ end
204
+ smc = smaxcol()
205
+ $log.debug " SMC original = #{smc} "
206
+ if smc >= osmc
207
+ smc = osmc-1
208
+ smc = @width # XXX ??? THIS WAS WORKING< but throwing error in viewport case
209
+ smc = [osmc-1, @width].min # yet another hack
210
+ $log.debug " SMC o-1 #{osmc-1} wdth #{@width}, smc #{smc} "
211
+ end
212
+ ### XXX commented out since it doesn't let a comp print fully if widget expanded (splitpane)
213
+ #smc = osw -1 if smc >= osw; # added 2009-11-02 17:01 for tabbedpanes
214
+
215
+ # dang, this is coming up a lot. 2010-01-16 20:34
216
+ # the second scrollpane was one row too large in testsplit3a.rb
217
+ if smr - @top > @padheight
218
+ $log.debug " fixing smr to padheight 2010-01-16 20:35 HOPE THIS DOESNT BREAK ANYTHING"
219
+ smr = @padheight
220
+ end
221
+ @pminrow = 0 if @pminrow < 0
222
+ @pmincol = 0 if @pmincol < 0
223
+ $log.debug " COPYING #{self.name} to #{@otherwin.name} "
224
+ $log.debug " calling copy pad #{@pminrow} #{@pmincol}, #{@top} #{@left}, #{smr} #{smc} self #{self.name} "
225
+ $log.debug " calling copy pad H: #{@height} W: #{@width}, PH #{@padheight} PW #{@padwidth} WIN:#{@window} "
226
+ # $log.debug " -otherwin target copy pad #{@otherwin.pminrow} #{@otherwin.pmincol}, #{@otherwin.top} #{@otherwin.left}, #{osmr} #{osmc} OTHERWIN:#{@otherwin.name} "
227
+ ret="-"
228
+ #if ret == -1
229
+ #x XXX $log.debug " #{ret} otherwin copy pad #{@otherwin.pminrow} #{@otherwin.pmincol}, #{@otherwin.top} #{@otherwin.left}, #{osmr} #{osmc} "
230
+ $log.debug " #{ret} otherwin copy pad H: #{osh} W: #{osw}"
231
+ if @top >= osh
232
+ $log.debug " #{ret} ERROR top exceeds other ht #{@top} H: #{osh} "
233
+ end
234
+ if @left >= osw
235
+ $log.debug " #{ret} ERROR left exceeds other wt #{@left} W: #{osw} "
236
+ end
237
+ if smr >= osh
238
+ $log.debug " #{ret} ERROR smrow exceeds other ht #{smr} H: #{osh} "
239
+ smr = osh() -1 # testing 2010-01-31 21:47 , again 2010-02-05 20:22
240
+ end
241
+ if smc >= osw
242
+ $log.debug " #{ret} ERROR smcol exceeds other wt #{smc} W: #{osw} "
243
+ end
244
+ if smc - @left > @padwidth
245
+ $log.debug " #{ret} ERROR smcol - left exceeds padwidth #{smc}- #{@left} PW: #{@padwidth} "
246
+ end
247
+ if smr - @top > @padheight
248
+ $log.debug " #{ret} ERROR smr - top exceeds padheight #{smr}- #{@top} PH: #{@padheight} "
249
+ end
250
+ ret = @window.copywin(@otherwin.get_window,@pminrow,@pmincol, @top, @left, smr, smc, 0)
251
+ $log.debug " copywin ret #{ret} "
252
+ # 2010-01-11 19:42 one more cause of -1 coming is that padheight (actual height which never
253
+ # changes unless pad increases) or padwidth is smaller than area being printed. Solution: increase
254
+ # buffer by increasing widgets w or h. smc - left should not exceed padwidth. smr-top should not
255
+ # exceed padheight
256
+ #end
257
+ @modified = false
258
+ return ret
259
+ end
260
+ # @deprecated
261
+ def copy_win_to_pad
262
+ $log.warn " DEPRECATED copy_win_to_pad" # CLEANUP 2011-09-29
263
+ raise "DEPREC copy_win_to_pad deprecated. Will be removed. Let me know if it is needed"
264
+ smr = smaxrow()
265
+ if smr >= @window.smaxrow()
266
+ smr = @window.smaxrow()-1
267
+ end
268
+ $log.debug " copy_win_to_pad #{@otherwin.name}, #{@window.name}, pminr:#{@pminrow} pminc:#{@pmincol} top:#{@top} left:#{@left} smr:#{smr} "
269
+ ret = @otherwin.copywin(@window.get_window,@pminrow,@pmincol, @top, @left, smr, smaxcol(), 1)
270
+ @modified = false
271
+ return ret
272
+ end
273
+ ##
274
+ #Used to overwrite the pad onto the screen window
275
+ # A window should have been specified as window to back (@see set_backing_window) or (@see create_with_window)
276
+ def overwrite_window
277
+ return @window.overwrite(@otherwin.get_window)
278
+ end
279
+
280
+ ##
281
+ # convenience method so that pad can use printstring but remove screen's row and col
282
+ # The absolute row and col will be taken into consideration when printing on screen.
283
+ #
284
+ # @param [Fixnum] row row to print on
285
+ # @param [Fixnum] col column to print on
286
+ # @param [String] value to print
287
+ # @param [Fixnum] color - color combination
288
+ # @param [Fixnum, nil] attrib defaults to NORMAL
289
+
290
+ # Pls remove the raise once the program is working, extra line can slow things down
291
+ # Keep it on when testing.
292
+ # If the raise is thrown, it means your object could be positioned higher than it should be,
293
+ # or at some point you have increased top, without increasing the objects row.
294
+ def printstring(row,col,value,color,attrib=Ncurses::A_NORMAL)
295
+ #$log.debug " pad printstring #{row} - #{@top} , #{col} - #{@left} "
296
+ raise "printstring row < top, pls correct code #{row} #{@top}, #{col} #{@left} " if row < @top or col < @left
297
+ #$log.warn "printstring row < top, pls correct code #{row} #{@top} " if row < @top
298
+ super(row - @top, col - @left, value, color, attrib)
299
+ end # printstring
300
+ # convenience method so that pad can use print_border but remove screen's row and col
301
+ # Please note that this requires that buffer have latest top and left.
302
+ def print_border row, col, height, width, color, att=Ncurses::A_NORMAL
303
+ $log.debug " pad printborder #{row} - #{@top} , #{col} - #{@left}, #{height} , #{width} "
304
+ raise "print_border: row < top, pls correct code #{row} #{@top}, #{col} #{@left} " if row < @top or col < @left
305
+ #$log.warn "print_border: row < top, pls correct code #{row} #{@top} " if row < @top
306
+ super(row - @top, col - @left, height, width, color, att)
307
+ end
308
+ def print_border_only row, col, height, width, color, att=Ncurses::A_NORMAL
309
+ $log.debug " pad printborder_only #{row} - #{@top} , #{col} - #{@left}, #{height} , #{width} "
310
+ raise "print_border row < top, pls correct code #{row} #{@top}, #{col} #{@left} " if row < @top or col < @left
311
+ super(row - @top, col - @left, height, width, color, att)
312
+ end
313
+ # use in place of mvwhline if your widget could be using a pad or window
314
+ def rb_mvwhline row, col, char, width
315
+ super(row-@top, col-@left, char, width)
316
+ end
317
+ # use in place of mvwvline if your widget could be using a pad or window
318
+ def rb_mvwvline row, col, char, width
319
+ super(row-@top, col-@left, char, width)
320
+ end
321
+ # use in place of mvaddch if your widget could be using a pad or window
322
+ def rb_mvaddch row, col, char
323
+ super(row-@top, col-@left, char)
324
+ end
325
+ end # class Pad
326
+ #-------------------------------- deprecated stuff ------------------ #
327
+ ##
328
+ # added RK 2009-10-08 23:57 for tabbedpanes
329
+ # THIS IS EXPERIMENTAL -
330
+ # I have not called super in the initializer so any methods you try on subwin
331
+ # that exist in the superclass which use @window will bomb
332
+ # @since 0.1.3 REMOVE UNUSED.
333
+ # @deprecated
334
+ class SubWindow < VER::Window
335
+ attr_reader :width, :height, :top, :left
336
+ attr_accessor :layout
337
+ attr_reader :panel # XXX reader requires so he can del it in end
338
+ attr_reader :subwin #
339
+ attr_reader :parent #
340
+
341
+ def initialize(parent, layout)
342
+ @visible = true
343
+ reset_layout(layout)
344
+
345
+ @parent = parent
346
+ #@subwin = @parent.get_window().derwin(@height, @width, @top, @left)
347
+ @subwin = @parent.get_window().subwin(@height, @width, @top, @left)
348
+ $log.debug "SUBWIN init #{@height} #{@width} #{@top} #{@left} "
349
+ #$log.debug "SUBWIN init #{@subwin.getbegx} #{@subwin.getbegy} #{@top} #{@left} "
350
+ @panel = Ncurses::Panel.new_panel(@subwin)
351
+
352
+ @window = @subwin # makes more mthods available
353
+ init_vars
354
+
355
+ end
356
+ # no need really now
357
+ def reset_layout layout
358
+ @layout = layout # 2010-02-13 22:23
359
+ @height = layout[:height]
360
+ @width = layout[:width]
361
+ @top = layout[:top]
362
+ @left = layout[:left]
363
+ end
364
+ def _destroy
365
+ # typically the ensure block should have this
366
+ # or should window do it for all subwins, or would we want to wait that long ?
367
+ $log.debug "subwin destroy"
368
+
369
+ Ncurses::Panel.del_panel(panel.pointer) if !panel.nil? # FFI
370
+ #@window.delwin(@window) if !@window.nil? # added FFI 2011-09-7
371
+ delwin if !@window.nil? # added FFI 2011-09-7
372
+ end
373
+ end
374
+
375
+ end
@@ -0,0 +1,512 @@
1
+ =begin
2
+ * Name: Scrollpane
3
+ * Description: a scrollable widget allowing user to scroll and view
4
+ parts of underlying object that typically are larger than screen area.
5
+ Mainly, contains a viewport, scrollbars and manages viewport through usage
6
+ of scrollbars.
7
+ Also contains viewport for row and columns.
8
+ * Author: rkumar
9
+ Todo section:
10
+ - add events, property changed etc at least for scrolling - DONE
11
+ SCrollpane normall should listen in to changes in viewport, however Scro calls those very methods
12
+ and what's more, other classes would listen to SCR and not to VP.
13
+ - scrollbars to be classes - shall we avoid over-engineering, and KISS
14
+ - if scrollpane reduced it should also resize, as example inside splitpane.
15
+ * file created 2009-10-27 19:20
16
+ * Added a call to child's set_form_col from set_form_row
17
+ Major changes 2010-02-11 19:51 to simplify version RFED16
18
+ * Still need to clean up this and viewport. make as light as possible
19
+ * If scrolling, no repainting should happen. Scrollpane could get the buffer
20
+ and scroll itself. Or ensure that inner object does not rework...
21
+
22
+ Pass handle_key to child, also repaint refer child.
23
+ Avoid passing to viewport as this would slow down alot.
24
+
25
+ NOTE: if a caller is interested in knowing what scrolling has happened, pls bind to :STATE_CHANGE, you will receive the viewport object. If you find this cumbersome, and wish to know only about scrolling, we can put in a scrolling event and inform of row or col scrolling. Or we can fire a property change with row or col increment.
26
+
27
+
28
+ --------
29
+ * License:
30
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
31
+
32
+ =end
33
+ #require 'rubygems'
34
+ #require 'ncurses'
35
+ require 'logger'
36
+ require 'rbcurse'
37
+ require 'rbcurse/rviewport'
38
+
39
+ #include Ncurses # FFI 2011-09-8
40
+ include RubyCurses
41
+ module RubyCurses
42
+ extend self
43
+
44
+ ##
45
+ # A scrollable box throgh which one can see portions of underlying object
46
+ # such as textarea, table or a form, usually the underlying data is larger
47
+ # than what can be displayed.
48
+
49
+ class ScrollPane < Widget
50
+ # viewport
51
+ # row_viewport
52
+ # column_viewport
53
+ # horizontal scrollbar 0-NONE, 1=ALWAYS, 2=AS_NEEDED
54
+ # vertical scrollbar 0-NONE, 1=ALWAYS, 2=AS_NEEDED
55
+ attr_accessor :cascade_changes # should changes in size go down to child, default false
56
+
57
+ def initialize form, config={}, &block
58
+ @focusable = true
59
+ @editable = false
60
+ #@left_margin = 1
61
+ @row = 0
62
+ @col = 0
63
+ super
64
+ @row_offset = @col_offset = 1
65
+ init_vars
66
+ @_events.push :STATE_CHANGE
67
+ # $log.debug " SCROLLPANE recvs form #{form.name}, #{form.window.name} " unless form.nil?
68
+
69
+
70
+ end
71
+ ##
72
+ # set child component being used in viewport
73
+ # @see set_viewport_view
74
+ def child ch
75
+ if ch != nil
76
+ @child = ch # added 2010-02-11 15:28 we might do away with viewport, setting panned to child
77
+ @child.rows_panned = @child.cols_panned = 0
78
+
79
+ ch.parent_component = self # added 2010-01-13 12:55 so offsets can go down ?
80
+
81
+ @child.should_create_buffer = true
82
+ @form.add_rows += 2 # related to scr_top XXX What if form not set. i cannot keep accumulating
83
+ update_child
84
+ # -3 since we start row +1 to get indented by 1, also we use
85
+ # height -1 in scrollpane, so we need -2 to indent, and one more
86
+ # for row
87
+ set_viewport_view(ch)
88
+ end
89
+ end
90
+ ##
91
+ # update of child's coordinates, needs to be called whenever it
92
+ # changes, so i need to call it before calling child's update
93
+ # FIXME - this is become 2 calls, make it one - becoming expensive
94
+ # if called often
95
+ def update_child
96
+ scr_top = 3 # for Pad, if Pad passed as in SplitPane
97
+ scr_left = 1 # for Pad, if Pad passed as in SplitPane
98
+ if @form.window.window_type == :WINDOW
99
+ scr_top = @row + 1
100
+ scr_left = @col + 1
101
+ @child.row(@row+@row_offset)
102
+ @child.col(@col+@col_offset)
103
+ else
104
+ # PAD case
105
+ @child.row(scr_top)
106
+ @child.col(scr_left)
107
+ end
108
+ @child.set_buffering(:target_window => @target_window || @form.window, :form => @form, :bottom => @height-3, :right => @width-3 )
109
+ @child.set_buffering(:screen_top => scr_top, :screen_left => scr_left)
110
+ # lets set the childs ext offsets
111
+ $log.debug "SCRP #{name} adding (to #{@child.name}) ext_row_off: #{@child.ext_row_offset} += #{@ext_row_offset} +#{@row_offset} "
112
+ $log.debug "SCRP adding ext_col_off: #{@child.ext_col_offset} += #{@ext_col_offset} +#{@col_offset} "
113
+ ## 2010-02-09 18:58 i think we should not put col_offset since the col
114
+ ## of child would take care of that. same for row_offset. XXX
115
+ @child.ext_col_offset += @ext_col_offset + @col + @col_offset - @screen_left # 2010-02-09 19:14
116
+ # added row and col setting to child RFED16 2010-02-17 00:22 as
117
+ # in splitpane. seems we are not using ext_offsets now ? texta
118
+ # and TV are not. and i've commented off from widget
119
+
120
+ $log.debug " #{@child.ext_row_offset} += #{@ext_row_offset} + #{@row} -#{@screen_top} "
121
+ @child.ext_row_offset += @ext_row_offset + @row + @row_offset - @screen_top
122
+ # adding this since child's ht should not be less. or we have a
123
+ # copywin failure
124
+ @child.height ||= @height
125
+ @child.width ||= @width
126
+ if @child.height < @height
127
+ @child.height = @height
128
+ end
129
+ if @child.width < @width
130
+ @child.width = @width
131
+ end
132
+
133
+ end
134
+ def init_vars
135
+ #@curpos = @pcol = @toprow = @current_index = 0
136
+ @hsb_policy = :AS_NEEDED
137
+ @vsb_policy = :AS_NEEDED
138
+ @repaint_required = true
139
+ @repaint_border = true
140
+ @row_outofbounds=0
141
+ @col_outofbounds=0
142
+ @border_width = 2
143
+ @screen_top = 0
144
+ @screen_left = 0
145
+ end
146
+ # set the component to be viewed
147
+ def set_viewport_view ch
148
+ @viewport = Viewport.new nil
149
+ @viewport.set_view ch
150
+ ## this -2 should depend on whether we are putting border/scrollbars or not.
151
+ # -1 added on 2010-02-16 23:35 since we are red 1, and bw
152
+ @viewport.set_view_size(@height-@border_width-0, @width-@border_width-0) # XXX make it one less
153
+ @viewport.cascade_changes = @cascade_changes # added 2010-02-04 18:19
154
+ @viewport.bind(:STATE_CHANGE) { |e| view_state_changed(e) }
155
+ @viewport.bind(:PROPERTY_CHANGE) { |e| view_property_changed(e) }
156
+ end
157
+ # return underlying viewport
158
+ # in order to run some of its methods
159
+ def get_viewport
160
+ return @viewport
161
+ end
162
+ # Directly set the viewport.
163
+ # Usually it is best to use set_viewport_view instead
164
+ def set_viewport vp
165
+ old = @viewport
166
+ @viewport = vp
167
+ fire_property_change "viewport", old, @viewport
168
+ end
169
+ # sets the component to be used as a rowheader TODO
170
+ def set_rowheader_view ch
171
+ old = @rowheader
172
+ @rowheader = Viewport.new
173
+ @rowheader.set_view ch
174
+ fire_property_change "row_header", old, @rowheader
175
+ end
176
+ # sets the component to be used as a column header TODO
177
+ def set_columnheader_view ch
178
+ old = @columnheader
179
+ @columnheader = Viewport.new
180
+ @columnheader.set_view ch
181
+ fire_property_change "column_header", old, @columnheader
182
+ end
183
+ def set_view_size h,w
184
+ # calling the property shoudl uniformally trigger fire_property_change
185
+ @viewport.set_view_size h,w
186
+ #height(h)
187
+ #width(w)
188
+ #fire_handler :PROPERTY_CHANGE, self # XXX should it be an event STATE_CHANGED with details
189
+ end
190
+ ## seems i wrote this only so i could set repaint_required to true
191
+ # However, now that VP calls state changed, that will happen XXX
192
+ def set_view_position r,c
193
+ ret = @viewport.set_view_position r,c
194
+ if ret
195
+ @repaint_required = true if ret
196
+ # fire_property_change("view_position",
197
+ end
198
+ return ret
199
+ end
200
+ # this method is registered with Viewport for changes
201
+ def view_state_changed ev
202
+ fire_handler :STATE_CHANGE, ev #???
203
+ @repaint_required = true
204
+ end
205
+ # this method is registered with Viewport for changes to properties
206
+ def view_property_changed ev
207
+ fire_handler :PROPERTY_CHANGE, ev #???
208
+ @repaint_required = true
209
+ end
210
+ # @return [true, false] false if r,c not changed
211
+ def increment_view_row num
212
+ #x r = @viewport.row() #- @viewport.top_margin
213
+ #x c = @viewport.col() #- @viewport.left_margin
214
+ r, c = @viewport.get_pad_top_left()
215
+ $log.debug " SCR inc viewport currently : r #{r} c #{c} "
216
+ r += num
217
+ ret = set_view_position r, c
218
+ v_scroll_bar if ret
219
+ return ret
220
+ end
221
+ # @return [true, false] false if r,c not changed
222
+ def increment_view_col num
223
+ r, c = @viewport.get_pad_top_left()
224
+ #r = @viewport.row() #- @viewport.top_margin
225
+ #c = @viewport.col() #- @viewport.left_margin
226
+ c += num
227
+ ret = set_view_position r, c
228
+ h_scroll_bar if ret
229
+ return ret
230
+ end
231
+ def repaint # scrollpane
232
+ # viewports child should repaint onto pad
233
+ # viewport then clips
234
+ # this calls viewports refresh from its refresh
235
+ return unless @repaint_required
236
+ if @viewport
237
+ update_child
238
+ $log.debug "SCRP #{@name} calling viewport repaint"
239
+ #@viewport.repaint_all true # 2010-01-16 23:09
240
+ @viewport.repaint_required true # changed 2010-01-19 19:34
241
+ @viewport.repaint # child's repaint should do it on its pad
242
+ $log.debug " #{@name} SCRP scrollpane repaint #{@graphic.name} "
243
+ end
244
+ # TODO this only if major change
245
+ if @repaint_border && @repaint_all # added 2010-01-16 20:15
246
+ #@graphic.wclear
247
+ $log.debug " #{@name} repaint all scroll: r #{@row} c #{@col} h #{@height}-1 w #{@width} "
248
+ bordercolor = @border_color || $datacolor
249
+ borderatt = @border_attrib || Ncurses::A_NORMAL
250
+ # NOTE - should be width-1 print_b reduces one from width, but
251
+ # not height !
252
+
253
+ @graphic.print_border_only(@row, @col, @height-1, @width, bordercolor, borderatt)
254
+ h_scroll_bar
255
+ v_scroll_bar
256
+ #x XXX @viewport.repaint_all(true) unless @viewport.nil? # brought here 2010-01-19 19:34
257
+ #@repaint_border = false # commented off on 2010-01-16 20:15 so repaint_all can have effect
258
+ end
259
+ return if @viewport == nil
260
+ $log.debug "SCRP #{@name} calling viewport to SCRP b2s #{@graphic.name} "
261
+ paint
262
+ end
263
+ def getvalue
264
+ # TODO
265
+ end
266
+ ## handle keys for scrollpane.
267
+ # First hands key to child object
268
+ # If unused, checks to see if it has anything mapped.
269
+ # If not consumed, returns :UNHANDLED, else 0.
270
+ def handle_key ch
271
+ # if this gets key it should just hand it to child
272
+ return :UNHANDLED if @viewport.nil? # added 2010-02-02 12:44
273
+ if @viewport != nil
274
+ $log.debug " calling child handle_key #{ch} "
275
+ ret = @viewport.handle_key ch
276
+ # XXX ret returns 0under normal circumstance, so will next line work ?
277
+ # what i mean is if ret == 0
278
+
279
+ @repaint_required = true if ret == 0 # added 2009-12-27 22:21 BUFFERED
280
+ $log.debug " ... child ret #{ret}"
281
+
282
+
283
+ ## Here's the only option scrollpane has of checking whether the child has
284
+ ##+ exceeded boundary BUFFERED 2009-12-29 23:12
285
+ # TEMPORARILY COMMENTED WHILE TESTING SCROLL UP AND DOWN XXX
286
+ #fr = @form.row
287
+ #fc = @form.col
288
+ #if fr >= @row + @height -2
289
+ #@form.setrowcol @row + @height -2, fc
290
+ #elsif fr < @row
291
+ #@form.setrowcol @row, fc
292
+ #end
293
+ #if fc >= @col + @width -1
294
+ #@form.setrowcol fr, @col + @width -1
295
+ #end
296
+ ##
297
+
298
+ return ret if ret != :UNHANDLED
299
+ end
300
+ ret = 0 # default return value
301
+ ks = keycode_tos(ch)
302
+ $log.debug " scrollpane gets KEY #{ch}, ks #{ks} "
303
+ case ch
304
+ when ?\M-n.getbyte(0)
305
+ ## scroll down one row (unless multiplier set)
306
+ ret = down
307
+ when ?\M-p.getbyte(0)
308
+ ## scroll up one row (unless multiplier set)
309
+ ret = up
310
+ #when ?0.getbyte(0), ?\C-[.getbyte(0)
311
+ #goto_start #start of buffer # cursor_start
312
+ #when ?\C-].getbyte(0)
313
+ #goto_end # end / bottom cursor_end # TODO
314
+ when ?\M-\<.getbyte(0)
315
+ @height.times { up ; }
316
+ when ?\M-\>.getbyte(0)
317
+ @height.times { down ; }
318
+ when KEY_DOWN
319
+ ret = down
320
+ #check_curpos
321
+ when ?\M-h.getbyte(0)
322
+ ## scroll left one position
323
+ repeatm {
324
+ ret = cursor_backward
325
+ @child.cols_panned = @child.cols_panned+1 if ret
326
+ @form.setrowcol @form.row, @form.col+1+@col_outofbounds if ret
327
+ }
328
+ when ?\M-l.getbyte(0)
329
+ ## scroll right one position
330
+ repeatm {
331
+ ret = cursor_forward
332
+ @child.cols_panned = @child.cols_panned-1 if ret
333
+ @form.setrowcol @form.row, @form.col-1+@col_outofbounds if ret
334
+ }
335
+ when KEY_BACKSPACE, KEY_BSPACE
336
+ ret = cursor_backward
337
+ #when ?\C-u.getbyte(0)
338
+ ## multiplier. Series is 4 16 64
339
+ #@multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
340
+ #return 0
341
+ when ?\C-c.getbyte(0)
342
+ $multiplier = 0
343
+ return 0
344
+ else
345
+ return :UNHANDLED
346
+ end
347
+ ret = :UNHANDLED if !ret
348
+ $multiplier = 0
349
+ return ret # 0 2010-02-04 18:47 returning ret else repaint is happening when UNHANDLED
350
+ end
351
+ # private
352
+ def _down
353
+ increment_view_row(1)
354
+ end
355
+ # private
356
+ def _up
357
+ increment_view_row(-1)
358
+ end
359
+ def cursor_forward
360
+ increment_view_col(1)
361
+ end
362
+ def cursor_backward
363
+ increment_view_col(-1)
364
+ end
365
+ def down
366
+ ## scroll down one row (currently one only)
367
+ $log.debug " MULT DOWN #{$multiplier} "
368
+ repeatm {
369
+ ret = _down
370
+ return unless ret # 2010-02-04 18:29
371
+ ## we've scrolled down, but we need to keep the cursor where
372
+ ##+ editing actually is. Isn't this too specific to textarea ?
373
+ $log.debug " SCRP setting row to #{@form.row-1} upon scrolling down "
374
+ ## only move up the cursor if its within bounds
375
+ # if @form.row > @row
376
+ @child.rows_panned = @child.rows_panned-1 if ret
377
+ @form.setrowcol @form.row-1+@row_outofbounds, @form.col if ret
378
+ }
379
+ end
380
+ def up
381
+ ## scroll up one row (currently one only)
382
+ repeatm {
383
+ ret = _up
384
+ return unless ret # 2010-02-04 18:29
385
+ $log.debug " SCRP setting row to #{@form.row+1} upon scrolling up R:#{@row} H:#{@height} "
386
+ # if @form.row < @row + @height
387
+ @child.rows_panned = @child.rows_panned+1 if ret
388
+ @form.setrowcol @form.row+1+@row_outofbounds, @form.col if ret
389
+ }
390
+ end
391
+ def on_enter
392
+ #super 2010-01-02 18:53 leading to a stack overflow XXX ???
393
+ set_form_row
394
+ end
395
+ # this is called once externally, on on_enter
396
+ #+ after that its called internally only, which in this case is never
397
+ def set_form_row
398
+ #@form.row = @row + 1 unless @form.nil?
399
+ if @viewport != nil
400
+ #$log.debug " calling scrollpane set_form_row"
401
+ ret = @viewport.child.set_form_row # added 2009-12-27 23:23 BUFFERED
402
+ ret = @viewport.child.set_form_col # added 2010-01-16 21:09
403
+ end
404
+ $log.debug " FORM SCRP #{@form.name} "
405
+ $log.debug "SCRP set_form_row #{@form.row} #{@form.col} "
406
+ end
407
+ ## added 2010-02-09 10:17
408
+ # Sometimes some parent objects may just call this.
409
+ # Would be better if they only called row and row called both ??? or is that less reliable
410
+ # In any case we have to combine this someday!!
411
+ def set_form_col
412
+ #@form.row = @row + 1 unless @form.nil?
413
+ if @viewport != nil
414
+ #$log.debug " calling scrollpane set_form_row"
415
+ ret = @viewport.child.set_form_col # added 2010-01-16 21:09
416
+ end
417
+ $log.debug " FORM SCRP #{@form.name} "
418
+ $log.debug "SCRP set_form_col #{@form.row} #{@form.col} "
419
+ end
420
+
421
+ ## this is called once only, on select_field by form.
422
+ ##+ after that not at all.
423
+ def rowcol
424
+ r1 = @row #+@row_offset
425
+ c1 = @col #+@col_offset
426
+ return r1, c1 if @viewport.nil? # added 2010-02-02 12:41
427
+
428
+ r,c = @viewport.child.rowcol # added 2009-12-28 15:23 BUFFERED
429
+ $log.debug "SCRP rowcol: #{r1} + #{r} , #{c1} + #{c} "
430
+ return r1+r, c1+c
431
+ end
432
+
433
+ def paint
434
+ @repaint_required = false
435
+ @repaint_all = false
436
+ end
437
+ def h_scroll_bar
438
+ return if @viewport.nil?
439
+ sz = (@viewport.width*1.00/@viewport.child().width)*@viewport.width
440
+ #$log.debug " h_scroll_bar sz #{sz}, #{@viewport.width} #{@viewport.child().width}"
441
+ sz = sz.ceil
442
+ return if sz < 1
443
+ start = 1
444
+ start = ((@viewport.col*1.00+@viewport.width)/@viewport.child().width)*@viewport.width
445
+ start -= sz
446
+ start = start.ceil
447
+ # # the problem with next 2 lines is that attributes of border could be overwritten
448
+ # draw horiz line
449
+ r = @row #+ @ext_row_offset # 2010-02-11 11:57 RFED16
450
+ c = @col #+ @ext_col_offset # 2010-02-11 11:57 RFED16
451
+ $log.debug " h_scroll_bar start #{start}, r #{r} c #{c} h:#{@height} "
452
+ @graphic.rb_mvwhline(r+@height-1, c+1, FFI::NCurses::ACS_HLINE, @width-2)
453
+ # draw scroll bar
454
+ #sz.times{ |i| @graphic.mvaddch(r+@height-1, c+start+1+i, FFI::NCurses::ACS_CKBOARD) }
455
+ sz.times{ |i| @graphic.rb_mvaddch(r+@height-1, c+start+1+i, FFI::NCurses::ACS_CKBOARD) }
456
+ end
457
+ def v_scroll_bar
458
+ return if @viewport.nil?
459
+ sz = (@viewport.height*1.00/@viewport.child().height)*@viewport.height
460
+ #$log.debug " v_scroll_bar sz #{sz}, #{@viewport.width} #{@viewport.child().width}"
461
+ sz = sz.ceil
462
+ return if sz < 1
463
+ start = 1
464
+ start = ((@viewport.row*1.00+@viewport.height)/@viewport.child().height)*@viewport.height
465
+ start -= sz
466
+ r = @row #+ @ext_row_offset # 2010-02-11 11:57 RFED16
467
+ c = @col #+ @ext_col_offset # 2010-02-11 11:57 RFED16
468
+ $log.debug " v_scroll_bar start #{start}, col:#{@col} w:#{@width}, r #{r}+1 c #{c}+w-1 "
469
+ start = start.ceil
470
+ # # the problem with next 2 lines is that attributes of border could be overwritten
471
+ # draw verti line
472
+ # this is needed to erase previous bar when shrinking
473
+ #@graphic.mvwvline(r+1,c+@width-1, FFI::NCurses::ACS_VLINE, @height-2)
474
+ @graphic.rb_mvwvline(r+1,c+@width-1, FFI::NCurses::ACS_VLINE, @height-2)
475
+ # draw scroll bar
476
+ #sz.times{ |i| @graphic.mvaddch(r+start+1+i, c+@width-1, FFI::NCurses::ACS_CKBOARD) }
477
+ sz.times{ |i| @graphic.rb_mvaddch(r+start+1+i, c+@width-1, FFI::NCurses::ACS_CKBOARD) }
478
+ end
479
+ # set height
480
+ # a container must pass down changes in size to it's children
481
+ # 2010-02-04 18:06 - i am not sure about this. When viewport is set then it passes down
482
+ # changes to child which user did not intend. Maybe in splitpane it is okay but other cases?
483
+ # Perhaps its okay if scrollpane gets larger than child, not otherwise.
484
+ # added 2010-01-16 23:55
485
+ def height(*val)
486
+ return @height if val.empty?
487
+ oldvalue = @height || 0
488
+ super
489
+ @height = val[0]
490
+ return if @viewport == nil
491
+ delta = @height - oldvalue
492
+ return if delta == 0
493
+ @repaint_required = true
494
+ @viewport.height += delta
495
+ end
496
+ # set width
497
+ # a container must pass down changes in size to it's children
498
+ # added 2010-01-16 23:55
499
+ def width(*val)
500
+ return @width if val.empty?
501
+ oldvalue = @width || 0
502
+ super
503
+ @width = val[0]
504
+ return if @viewport == nil
505
+ delta = @width - oldvalue
506
+ return if delta == 0
507
+ @repaint_required = true
508
+ @viewport.width += delta
509
+ end
510
+
511
+ end # class ScrollPane
512
+ end # module