rbcurse 0.1.3 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/CHANGELOG +126 -0
  2. data/Manifest.txt +53 -20
  3. data/README.markdown +423 -0
  4. data/Rakefile +3 -1
  5. data/examples/keytest.rb +177 -0
  6. data/examples/mpad2.rb +156 -0
  7. data/examples/newtesttabp.rb +121 -0
  8. data/examples/rfe.rb +48 -10
  9. data/examples/rfe_renderer.rb +4 -4
  10. data/examples/rvimsplit.rb +376 -0
  11. data/examples/sqlc.rb +97 -106
  12. data/examples/sqlm.rb +446 -0
  13. data/examples/test1.rb +4 -4
  14. data/examples/test2.rb +12 -12
  15. data/examples/testchars.rb +140 -0
  16. data/examples/testkeypress.rb +9 -4
  17. data/examples/testmulticomp.rb +72 -0
  18. data/examples/testscroller.rb +136 -0
  19. data/examples/testscrolllb.rb +86 -0
  20. data/examples/testscrollp.rb +87 -0
  21. data/examples/testscrollta.rb +80 -0
  22. data/examples/testscrolltable.rb +166 -0
  23. data/examples/testsplit.rb +87 -0
  24. data/examples/testsplit2.rb +123 -0
  25. data/examples/testsplit3.rb +215 -0
  26. data/examples/testsplit3_1.rb +244 -0
  27. data/examples/testsplit3a.rb +215 -0
  28. data/examples/testsplit3b.rb +237 -0
  29. data/examples/testsplitta.rb +148 -0
  30. data/examples/testsplittv.rb +142 -0
  31. data/examples/testsplittvv.rb +144 -0
  32. data/examples/testtable.rb +1 -1
  33. data/examples/testtabp.rb +3 -2
  34. data/examples/testtestw.rb +69 -0
  35. data/examples/testtodo.rb +5 -3
  36. data/examples/testtpane.rb +203 -0
  37. data/examples/testtpane2.rb +145 -0
  38. data/examples/testtpanetable.rb +199 -0
  39. data/examples/viewtodo.rb +5 -3
  40. data/lib/rbcurse.rb +1 -1
  41. data/lib/rbcurse/celleditor.rb +2 -2
  42. data/lib/rbcurse/colormap.rb +5 -5
  43. data/lib/rbcurse/defaultlistselectionmodel.rb +3 -3
  44. data/lib/rbcurse/io.rb +663 -0
  45. data/lib/rbcurse/listeditable.rb +306 -0
  46. data/lib/rbcurse/listkeys.rb +15 -15
  47. data/lib/rbcurse/listscrollable.rb +168 -27
  48. data/lib/rbcurse/mapper.rb +35 -13
  49. data/lib/rbcurse/rchangeevent.rb +28 -0
  50. data/lib/rbcurse/rform.rb +845 -0
  51. data/lib/rbcurse/rlistbox.rb +144 -34
  52. data/lib/rbcurse/rmessagebox.rb +10 -5
  53. data/lib/rbcurse/rmulticontainer.rb +325 -0
  54. data/lib/rbcurse/rmultitextview.rb +306 -0
  55. data/lib/rbcurse/rscrollform.rb +369 -0
  56. data/lib/rbcurse/rscrollpane.rb +511 -0
  57. data/lib/rbcurse/rsplitpane.rb +820 -0
  58. data/lib/rbcurse/rtabbedpane.rb +737 -109
  59. data/lib/rbcurse/rtabbedwindow.rb +326 -0
  60. data/lib/rbcurse/rtable.rb +220 -64
  61. data/lib/rbcurse/rtextarea.rb +340 -181
  62. data/lib/rbcurse/rtextview.rb +237 -101
  63. data/lib/rbcurse/rviewport.rb +203 -0
  64. data/lib/rbcurse/rwidget.rb +919 -95
  65. data/lib/rbcurse/scrollable.rb +7 -7
  66. data/lib/rbcurse/selectable.rb +4 -4
  67. data/lib/rbcurse/table/tablecellrenderer.rb +3 -0
  68. data/lib/rbcurse/undomanager.rb +181 -0
  69. data/lib/rbcurse/vieditable.rb +100 -0
  70. data/lib/ver/window.rb +471 -21
  71. metadata +66 -22
  72. data/README.txt +0 -312
  73. data/examples/testd.db +0 -0
  74. data/examples/todocsv.csv +0 -28
@@ -0,0 +1,820 @@
1
+ =begin
2
+ * Name: SplitPane
3
+ * $Id$
4
+ * Description: allows user to split 2 components vertically or horizontally
5
+ * NOTE that VERTICAL_SPLIT means the *divider* is vertical.
6
+ * Author: rkumar (arunachalesha)
7
+ * file created 2009-10-27 19:20
8
+ * major change: Feb 2010, removed buffers
9
+ Todo:
10
+ * TODO remove components
11
+
12
+ * XXX Does SPLP need to listen for changes in children
13
+ --------
14
+ * License:
15
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
16
+
17
+ =end
18
+ #require 'rubygems'
19
+ require 'ncurses'
20
+ require 'logger'
21
+ require 'rbcurse'
22
+
23
+ include Ncurses
24
+ include RubyCurses
25
+ module RubyCurses
26
+ extend self
27
+
28
+ ##
29
+ # A SplitPane allows user to split 2 components vertically or horizontally.
30
+ # such as textarea, table or a form, usually the underlying data is larger
31
+ # than what can be displayed.
32
+ # @since 0.1.3
33
+ # TODO -
34
+
35
+ class SplitPane < Widget
36
+ #dsl_property :height # added to widget and here as method
37
+ #dsl_accessor :width # already present in widget
38
+ # row and col also present int widget
39
+ #dsl_accessor :first_component # top or left component that is being viewed
40
+ #dsl_accessor :second_component # right or bottom component that is being viewed
41
+ dsl_property :orientation # :VERTICAL_SPLIT or :HORIZONTAL_SPLIT
42
+ attr_reader :divider_location #
43
+ attr_reader :resize_weight
44
+ attr_writer :last_divider_location
45
+ dsl_accessor :border_color
46
+ dsl_accessor :border_attrib
47
+ attr_accessor :one_touch_expandable # boolean, default true
48
+
49
+ def initialize form, config={}, &block
50
+ @focusable = true
51
+ @editable = false
52
+ #@left_margin = 1
53
+ @row = 0
54
+ @col = 0
55
+ super
56
+ @row_offset = @col_offset = 1
57
+ @orig_col = @col
58
+ @use_absolute = true; # set to true if not using subwins XXX
59
+ init_vars
60
+ @subwin_created = true # set to true if you don't want subwins created
61
+ @@ctr ||= 0
62
+ if @@ctr == 0
63
+ if @subwin_created == false
64
+ #layout = { :height => @height, :width => @width, :top => @row, :left => @col }
65
+ layout = { :height => @height-1, :width => @width-1, :top => @row+1, :left => @col+1 }
66
+ @graphic = @graphic._subwin(layout)
67
+ fw = form.window
68
+ raise "graphic nil #{@name} " unless @graphic
69
+ $log.debug " SUBWIN CREATED "
70
+ @subwin_created = true
71
+ @target_window = @graphic
72
+ @@ctr += 1
73
+ @use_absolute = false
74
+ bordercolor = @border_color || $datacolor
75
+ borderatt = @border_attrib || Ncurses::A_NORMAL
76
+ end
77
+ end
78
+ end
79
+ def init_vars
80
+ #should_create_buffer(true) #if should_create_buffer().nil?
81
+ @divider_location ||= 10
82
+ #@divider_offset ||= 1
83
+ @divider_offset ||= 0
84
+ #@curpos = @pcol = @toprow = @current_index = 0
85
+
86
+ # cascade_changes keeps the child exactly sized as per the pane which looks nice
87
+ #+ but may not really be what you want.
88
+ @cascade_changes=true
89
+ ## if this splp is increased (ht or wid) then expand the child
90
+ @cascade_boundary_changes = true
91
+ @orientation ||= :HORIZONTAL_SPLIT # added 2010-01-13 15:05 since not set
92
+
93
+ # true means will request child to create a buffer, since cropping will be needed
94
+ @_child_buffering = true # private, internal. not to be changed by callers.
95
+ @one_touch_expandable = true
96
+ @is_expanding = false
97
+
98
+ bind_key([?\C-w, ?o], :expand)
99
+ bind_key([?\C-w, ?1], :expand)
100
+ bind_key([?\C-w, ?2], :unexpand)
101
+ bind_key([?\C-w, ?x], :exchange)
102
+
103
+ end
104
+
105
+ ##
106
+ # Sets the first component (top or left)
107
+ #
108
+ # @param [String] comp comment
109
+ # @return [true, false] comment
110
+ #
111
+ # XXX This originally working fine if the child was also a splitpane
112
+ # Now with other comps, it works fine with them if they create a buffer in const
113
+ # but now SPLP bombs since it creates a buffer in repaint.
114
+
115
+ def first_component(comp)
116
+ screen_col = 1
117
+ screen_row = 1 # offset for copying pad 2010-02-09 19:02
118
+ @first_component = comp;
119
+ @first_component.parent_component = self ## added 2010-01-13 12:54
120
+ ## These setting are quite critical, otherwise on startup
121
+ ##+ it can create 2 tiled buffers.
122
+ a = 0 # =1
123
+ @first_component.row(@row + a)
124
+ @first_component.col(@col + a)
125
+ comp.should_create_buffer = @_child_buffering
126
+ # adding ext_offsets 2010-02-09 13:39
127
+ # setting the form is again adding top and left which are the row and col from here.
128
+ $log.debug "SPLP exp_row #{@name}, #{comp} #{comp.ext_row_offset} += #{@ext_row_offset} + #{@row} "
129
+ $log.debug "SPLP exp_col #{@name} #{comp.ext_col_offset} += #{@ext_col_offset} + #{@col} "
130
+ #XXX comp.ext_row_offset += @ext_row_offset + @row - @subform1.window.top #0# screen_row
131
+ #XXX comp.ext_col_offset += @ext_col_offset + @col -@subform1.window.left # 0# screen_col
132
+ comp.ext_row_offset += @ext_row_offset + @row #- @subform1.window.top #0# screen_row
133
+ comp.ext_col_offset += @ext_col_offset + @col #-@subform1.window.left # 0# screen_col
134
+
135
+ ## trying out 2010-01-16 12:11 so component does not have to set size
136
+ # The suggestd heights really depend on orientation.
137
+ a = 0 # = 2
138
+ if @orientation == :HORIZONTAL_SPLIT
139
+ @first_component.height ||= @first_component.preferred_height || @height/2 - 1 #1
140
+ @first_component.width ||= @first_component.preferred_width || @width - a
141
+ else
142
+ @first_component.height ||= @first_component.preferred_height || @height - a
143
+ @first_component.width ||= @first_component.preferred_width || @width/2 -1
144
+ end
145
+ #layout = { :height => @height-1, :width => @width-1, :top => @row, :left => @col }
146
+ comp.set_buffering(:target_window => @target_window || @form.window, :bottom => comp.height-1, :right => comp.width-1, :form => @form )
147
+ comp.set_buffering(:screen_top => @row, :screen_left => @col)
148
+ @first_component.min_height ||= 5
149
+ @first_component.min_width ||= 5
150
+
151
+
152
+ # if i set the above 2 to 0, it starts fine but then on any action loses the first row.
153
+ # Just begun happeing suddenly! 2010-01-11 23:38
154
+
155
+ # 2010-01-11 22:32 dang, if component is like splitpane which sets in repaint
156
+ # 2010-01-12 11:15 : for those who've created in constructor, i need to do this
157
+ # so they don't print off. i need to find a way to have create_buffer pick an
158
+ # explicit top and left.
159
+ if !@first_component.get_buffer().nil?
160
+ @first_component.get_buffer().set_screen_row_col(screen_row, screen_col) # check this out XXX
161
+ #@first_component.get_buffer().top=1; # 2010-01-08 13:24 trying out
162
+ #@first_component.get_buffer().left=1; # 2010-01-08 13:24 trying out
163
+ end
164
+ @current_component ||= @first_component # added 2010-01-13 15:39
165
+ end # first_component
166
+ ##
167
+ # Sets the second component (bottom or right)
168
+ #
169
+ # @param [String] comp comment
170
+ # @return [true, false] comment
171
+
172
+ def second_component(comp)
173
+ @second_component = comp;
174
+ @second_component.parent_component = self ## added 2010-01-13 12:54
175
+ comp.should_create_buffer = @_child_buffering
176
+ ## jeez, we;ve postponed create of buffer XX
177
+ ## trying out 2010-01-16 12:11 so component does not have to set size
178
+ # The suggestd heights really depend on orientation.
179
+ if @orientation == :HORIZONTAL_SPLIT
180
+ @second_component.row(@row+@divider_location)
181
+ @second_component.col(@col+@col_offset)
182
+ @second_component.height ||= @second_component.preferred_height || @height/2 - 1 #1
183
+ @second_component.width ||= @second_component.preferred_width || @width - 0 # 2
184
+ else
185
+ @second_component.row(@row+@row_offset)
186
+ @second_component.col(@col+@divider_location)
187
+ @second_component.height ||= @second_component.preferred_height || @height - 0 # 2
188
+ @second_component.width ||= @second_component.preferred_width || @width/2 -4 # 1 to 4 2010-01-16 22:10 TRYING COULD BREAK STUFF testsplit3a;s right splitpane
189
+ # added 2010-01-16 23:55
190
+ end
191
+ comp.ext_row_offset += @ext_row_offset + @row
192
+ $log.debug "SPLP exp_col #{@name} 2 #{comp}: #{comp.ext_col_offset} += #{@ext_col_offset} + #{@col} "
193
+ comp.ext_col_offset += @ext_col_offset + @col
194
+ layout = { :height => @height-1, :width => @width-1, :top => comp.row, :left => comp.col }
195
+ comp.set_buffering(:target_window => @target_window || @form.window, :bottom => comp.height-1,
196
+ :right => comp.width-1, :form => @form )
197
+ $log.debug " setting c2 screen_top n left to #{@row} #{@col} "
198
+ @second_component.set_buffering(:screen_top => @row, :screen_left => @col)
199
+ @second_component.min_height ||= 5 # added 2010-01-16 12:37
200
+ @second_component.min_width ||= 5 # added 2010-01-16 12:37
201
+ end # second_component
202
+
203
+ ## faster access to the 2 components
204
+ def c1; @first_component; end
205
+ def c2; @second_component; end
206
+
207
+ ##
208
+ #
209
+ # change height of splitpane
210
+ # @param val [int] new height of splitpane
211
+ # @return [int] old ht if nil passed
212
+ def height(*val)
213
+ return @height if val.empty?
214
+ oldvalue = @height || 0
215
+ super
216
+ @height = val[0]
217
+ return if @first_component.nil? or @second_component.nil?
218
+ delta = @height - oldvalue
219
+ @repaint_required = true
220
+ if !@cascade_boundary_changes.nil?
221
+ # must tell children if height changed which will happen in nested splitpanes
222
+ # must adjust to components own offsets too
223
+ if @orientation == :VERTICAL_SPLIT
224
+ @first_component.height += delta
225
+ @second_component.height += delta
226
+ # RFED16 2010-02-16 20:44 whenever we change dimensions need to update
227
+ # buffering_params since we are not using Pad's buffer_to_screen
228
+ @second_component.set_buffering(:bottom => @second_component.height-1)
229
+ @first_component.set_buffering(:bottom => @first_component.height-1)
230
+ else
231
+ @second_component.height += delta
232
+ @second_component.set_buffering(:bottom => @second_component.height-1)
233
+ end
234
+ end
235
+ end
236
+ ##
237
+ # change width of splitpane
238
+ # @param val [int, nil] new width of splitpane
239
+ # @return [int] old width if nil passed
240
+ # NOTE: if VERTICAL, then expand or contract only second
241
+ # If HORIZ then expand / contract both
242
+ # Actually this is very complicated since reducing should take into account min_width
243
+ def width(*val)
244
+ return @width if val.empty?
245
+ # must tell children if height changed which will happen in nested splitpanes
246
+ oldvalue = @width || 0
247
+ super
248
+ @width = val[0]
249
+ delta = @width - oldvalue
250
+ $log.debug " SPLP #{@name} width #{oldvalue}, #{@width}, #{delta} "
251
+ @repaint_required = true
252
+ if !@cascade_boundary_changes.nil?
253
+ # must adjust to components own offsets too
254
+ # NOTE: 2010-01-10 20:11 if we increase width by one, each time will both components get increased by one.
255
+ if @orientation == :HORIZONTAL_SPLIT
256
+ if @first_component != nil
257
+ old = @first_component.width
258
+ #@first_component.width = @width - @col_offset + @divider_offset
259
+ @first_component.width += delta
260
+ $log.debug "width() #{@name} set fc width to #{@first_component.width}, old was #{old} "
261
+ @first_component.set_buffering(:right => @first_component.width-1)
262
+ end
263
+ # added 2010-01-11 23:02 horiz 2c not displaying since width issue
264
+ if @second_component != nil
265
+ old = @second_component.width
266
+ #@first_component.width = @width - @col_offset + @divider_offset
267
+ @second_component.width += delta
268
+ @second_component.set_buffering(:right => @second_component.width-1)
269
+ $log.debug "width() #{@name} set 2c width to #{@second_component.width}, old was #{old} "
270
+ end
271
+ else
272
+ rc = @divider_location
273
+ # ## next change should only happen if sc w < ...
274
+ # 2010-01-11 22:11
275
+ # if @second_component.width < @width - (rc + @col_offset + @divider_offset + 1)
276
+ if @second_component != nil
277
+ if @second_component.width < @width - (rc + @col_offset + @divider_offset + 1)
278
+ old = @second_component.width
279
+ #@second_component.width = @width - @col_offset + @divider_offset
280
+ @second_component.width += delta
281
+ @second_component.set_buffering(:right => @second_component.width-1)
282
+ $log.debug "width() #{@name} set 2c width to #{@second_component.width} , old was #{old} "
283
+ end
284
+ end
285
+ end
286
+ end
287
+ end
288
+ # set location of divider (row or col depending on orientation)
289
+ # internally sets the second components row or col
290
+ # also to set widths or heights
291
+ # Check minimum sizes are not disrespected
292
+ # @param rc [int] row or column to place divider
293
+ # 2010-01-09 23:07 : added sections to prevent a process crash courtesy copywin
294
+ #+ when pane size exceeds buffer size, so in these cases we increase size of component
295
+ #+ and therefore buffer size. Needs to be tested for VERTICAL.
296
+ # If this returns :ERROR, caller may avoid repainting form needlessly.
297
+ # We may give more meaningful error retval in future. TODO
298
+ def set_divider_location rc
299
+ $log.debug " SPLP #{@name} setting divider to #{rc} "
300
+ # add a check for out of bounds since no buffering
301
+ v = 1 # earlier 2
302
+ if @orientation == :HORIZONTAL_SPLIT
303
+ if rc < v || rc > @height - v
304
+ return :ERROR
305
+ end
306
+ else
307
+ if rc < v || rc > @width - v
308
+ return :ERROR
309
+ end
310
+ end
311
+ @repaint_required = true
312
+ old_divider_location = @divider_location || 0
313
+ # we first check against min_sizes
314
+ # the calculation is repeated here, and in the actual change
315
+ # so if modifying, be sure to do in both places.
316
+ if !@is_expanding # if expanding then i can't check against min_width
317
+ if rc > old_divider_location
318
+ if @second_component != nil
319
+ if @orientation == :VERTICAL_SPLIT
320
+ # check second comps width
321
+ if @width - (rc + @col_offset + @divider_offset+1) < @second_component.min_width
322
+ $log.debug " #{@name} SORRY 2c min width prevents further resizing: #{@width} #{rc}"
323
+ return :ERROR
324
+ end
325
+ else
326
+ # check second comps ht
327
+ $log.debug " YYYY SORRY 2c H:#{@height} rc: #{rc} 2cmh: #{@second_component.name} "
328
+ if @height - rc -2 < @second_component.min_height
329
+ $log.debug " #{@name} SORRY 2c min height prevents further resizing"
330
+ return :ERROR
331
+ end
332
+ end
333
+ end
334
+ elsif rc < old_divider_location
335
+ if @first_component != nil
336
+ $log.debug " #{@name} fc min width #{rc}, #{@first_component.min_width} "
337
+ if @orientation == :VERTICAL_SPLIT
338
+ # check first comps width
339
+
340
+ if rc-1 < @first_component.min_width
341
+ $log.debug " SORRY fc min width prevents further resizing"
342
+ return :ERROR
343
+ end
344
+ else
345
+ if rc-1 < @first_component.min_height
346
+ $log.debug " SORRY fc min height prevents further resizing"
347
+ return :ERROR
348
+ end
349
+ end
350
+ end
351
+ end
352
+ end # expanding
353
+ @is_expanding = false
354
+ @old_divider_location = @divider_location
355
+ @divider_location = rc
356
+ if @first_component != nil
357
+
358
+ ## added in case not set. it will be set to a sensible default
359
+ @first_component.height ||= 0
360
+ @first_component.width ||= 0
361
+
362
+ $log.debug " #{@name} set div location, setting first comp width #{rc}"
363
+ if !@cascade_changes.nil?
364
+ if @orientation == :VERTICAL_SPLIT
365
+ @first_component.width(rc-0) #+ @col_offset + @divider_offset
366
+ @first_component.height(@height-0) #2+ @col_offset + @divider_offset
367
+ else
368
+ @first_component.height(rc+0) #-1) #1+ @col_offset + @divider_offset
369
+ @first_component.width(@width-0) #2+ @col_offset + @divider_offset
370
+ end
371
+ else
372
+ if @orientation == :VERTICAL_SPLIT
373
+ $log.debug " DOES IT COME HERE compare fc wt #{@first_component.width} to match #{rc}-1 "
374
+ # added 2010-01-09 19:00 increase fc to avoid copywin crashing process
375
+ if @first_component.width < rc -0 then
376
+ $log.debug " INCRease fc wt #{@first_component.width} to match #{rc}-1 "
377
+ @first_component.width(rc-0) #+ @col_offset + @divider_offset
378
+ @first_component.repaint_all(true) if !@first_component.nil?
379
+ @repaint_required = true
380
+ end
381
+ ## added this condition 2010-01-11 21:44 again switching needs this
382
+ a = 0 #2
383
+ if @first_component.height < @height - a then
384
+ $log.debug " INCRease fc ht #{@first_component.height} to match #{@height}- #{a} "
385
+ @first_component.height(@height-a) #+ @col_offset + @divider_offset
386
+ end
387
+ else
388
+ # added 2010-01-09 19:00 increase fc to avoid copywin crashing process
389
+ a = 0 #1
390
+ if @first_component.height < rc -a then
391
+ $log.debug " INCRease fc ht #{@first_component.height} to match #{rc}-1 "
392
+ @first_component.height(rc-a) #+ @col_offset + @divider_offset
393
+ @first_component.repaint_all(true) if !@first_component.nil?
394
+ @repaint_required = true
395
+ end
396
+ # added 2010-01-11 19:24 to match c2. Sometimes switching from V to H means
397
+ # fc's width needs to be expanded.
398
+ if @first_component.width < @width - 1 #+ @col_offset + @divider_offset
399
+ $log.debug " INCRease fc wi #{@first_component.width} to match #{@width}-2 "
400
+ @first_component.width = @width - 1 #+ @col_offset + @divider_offset
401
+ @first_component.repaint_all(true)
402
+ @repaint_required = true
403
+ end
404
+ end
405
+ end
406
+ $log.debug " #{@name} TA set C1 H W RC #{@first_component.height} #{@first_component.width} #{rc} "
407
+ @first_component.set_buffering(:bottom => @first_component.height-1, :right => @first_component.width-1, :form => @form )
408
+ end
409
+ if !@second_component.nil?
410
+
411
+ ## added 2010-01-11 23:09 since some cases don't set, like splits within split.
412
+ @second_component.height ||= 0
413
+ @second_component.width ||= 0
414
+
415
+ if @orientation == :VERTICAL_SPLIT
416
+ #@second_component.col = rc + @col_offset + @divider_offset
417
+ #@second_component.row = 0 # 1
418
+ @second_component.col = @col + rc #+ @col_offset + @divider_offset
419
+ @second_component.row = @row # 1
420
+ if !@cascade_changes.nil?
421
+ #@second_component.width = @width - (rc + @col_offset + @divider_offset + 1)
422
+ #@second_component.height = @height-2 #+ @row_offset + @divider_offset
423
+ @second_component.width = @width - rc #+ @col_offset + @divider_offset + 1)
424
+ @second_component.height = @height-0 #+ @row_offset + @divider_offset
425
+ else
426
+ # added 2010-01-09 22:49 to be tested XXX
427
+ # In a vertical split, if widgets w and thus buffer w is less than
428
+ #+ pane, a copywin can crash process, so we must expand component, and thus buffer
429
+ $log.debug " #{@name} 2c width does it come here? #{@second_component.name} #{@second_component.width} < #{@width} -( #{rc}+#{@col_offset}+#{@divider_offset} +1 "
430
+ if @second_component.width < @width - rc #+ @col_offset + @divider_offset + 1)
431
+ $log.debug " YES 2c width "
432
+ @second_component.width = @width - rc #+ @col_offset + @divider_offset + 1)
433
+ @second_component.repaint_all(true)
434
+ @repaint_required = true
435
+ end
436
+ # adding 2010-01-17 19:33 since when changing to VERT, it was not expanding
437
+ if @second_component.height < @height-0 #+ @row_offset + @divider_offset
438
+ $log.debug " JUST ADDED 2010-01-17 19:35 HOPE DOES NOT BREAK ANYTHING "
439
+ @second_component.height = @height-0 #+ @row_offset + @divider_offset
440
+ end
441
+ end
442
+ else
443
+ #rc += @row
444
+ ## HORIZ SPLIT
445
+ offrow = offcol = 0
446
+ #@second_component.row = offrow + rc + 0 #1 #@row_offset + @divider_offset
447
+ #@second_component.col = 0 + offcol # was 1
448
+ offrow = @row; offcol = @col
449
+ @second_component.row = offrow + rc + 0 #1 #@row_offset + @divider_offset
450
+ $log.debug "C2 Horiz row #{@second_component.row} = #{offrow} + #{rc} "
451
+ @second_component.col = 0 + offcol # was 1
452
+ if !@cascade_changes.nil?
453
+ #@second_component.width = @width - 2 #+ @col_offset + @divider_offset
454
+ #@second_component.height = @height - rc -2 #+ @row_offset + @divider_offset
455
+ @second_component.width = @width - 0 #+ @col_offset + @divider_offset
456
+ @second_component.height = @height - rc -0 #+ @row_offset + @divider_offset
457
+ else
458
+ # added 2010-01-16 19:14 -rc since its a HORIZ split
459
+ # 2010-01-16 20:45 made 2 to 3 for scrollpanes within splits!!! hope it doesnt
460
+ # break, and why 3.
461
+ # 2010-01-17 13:33 reverted to 2. 3 was required since i was not returning when error in set_screen_max.
462
+ if @second_component.height < @height-rc-1 #2 #+ @row_offset + @divider_offset
463
+ $log.debug " #{@name} INCRease 2c #{@second_component.name} ht #{@second_component.height} to match #{@height}-2- #{rc} "
464
+ @second_component.height = @height-rc-1 #2 #+ @row_offset + @divider_offset
465
+ @second_component.repaint_all(true)
466
+ @repaint_required = true
467
+ end
468
+ # # added 2010-01-10 15:36 still not expanding
469
+ if @second_component.width < @width - 2 #+ @col_offset + @divider_offset
470
+ $log.debug " #{@name} INCRease 2c #{@second_component.name} wi #{@second_component.width} to match #{@width}-2 "
471
+ @second_component.width = @width - 2 #+ @col_offset + @divider_offset
472
+ @second_component.repaint_all(true)
473
+ @repaint_required = true
474
+ end
475
+ end
476
+ end
477
+ # i need to keep top and left sync for print_border which uses it UGH !!!
478
+ if !@second_component.get_buffer().nil?
479
+ # now that TV and others are creating a buffer in repaint we need another way to set
480
+ #$log.debug " setting second comp row col offset - i think it doesn't come here till much later "
481
+ #XXX @second_component.get_buffer().set_screen_row_col(@second_component.row+@ext_row_offset+@row, @second_component.col+@ext_col_offset+@col)
482
+ # 2010-02-13 09:15 RFED16
483
+ @second_component.get_buffer().set_screen_row_col(@second_component.row, @second_component.col)
484
+ end
485
+ #@second_component.set_buffering(:screen_top => @row, :screen_left => @col)
486
+ #@second_component.set_buffering(:screen_top => @row+@second_component.row, :screen_left => @col+@second_component.col)
487
+ #@second_component.set_buffering(:screen_top => @row+@second_component.row, :screen_left => @col+@second_component.col)
488
+ $log.debug "sdl: #{@name} setting C2 screen_top n left to #{@second_component.row}, #{@second_component.col} "
489
+ @second_component.set_buffering(:screen_top => @second_component.row, :screen_left => @second_component.col)
490
+ @second_component.set_buffering(:bottom => @second_component.height-1, :right => @second_component.width-1, :form => @form )
491
+ #@second_component.ext_row_offset = @row + @ext_row_offset
492
+ #@second_component.ext_col_offset = @col + @ext_col_offset
493
+ $log.debug " #{@name} 2 set div location, rc #{rc} width #{@width} height #{@height}"
494
+ $log.debug " 2 set div location, setting r #{@second_component.row}, #{@ext_row_offset}, #{@row} "
495
+ $log.debug " 2 set div location, setting c #{@second_component.col}, #{@ext_col_offset}, #{@col} "
496
+ $log.debug " C2 set div location, setting w #{@second_component.width} "
497
+ $log.debug " C2 set div location, setting h #{@second_component.height} "
498
+
499
+ end
500
+ fire_property_change("divider_location", old_divider_location, @divider_location)
501
+
502
+ end
503
+
504
+ # calculate divider location based on weight
505
+ # Weight implies weight of first component, e.g. .70 for 70% of splitpane
506
+ # @param wt [float, :read] weight of first component
507
+ def set_resize_weight wt
508
+ raise ArgumentError if wt < 0 or wt >1
509
+ @repaint_required = true
510
+ oldvalue = @resize_weight
511
+ @resize_weight = wt
512
+ if @orientation == :VERTICAL_SPLIT
513
+ rc = (@width||@preferred_width) * wt
514
+ else
515
+ rc = (@height||@preferred_height) * wt
516
+ end
517
+ fire_property_change("resize_weight", oldvalue, @resize_weight)
518
+ rc = rc.ceil
519
+ set_divider_location rc
520
+ end
521
+ ##
522
+ # resets divider location based on preferred size of first component
523
+ # @return :ERROR if min sizes failed
524
+ # You may want to check for ERROR and if so, resize_weight to 0.50
525
+ def reset_to_preferred_sizes
526
+ return if @first_component.nil?
527
+ @repaint_required = true
528
+ ph, pw = @first_component.get_preferred_size
529
+ if @orientation == :VERTICAL_SPLIT
530
+ pw ||= @width/2-1 # added 2010-01-16 12:31 so easier to use, 1 to 2 2010-01-16 22:13
531
+ rc = pw+1 ## added 1 2010-01-11 23:26 else divider overlaps comp
532
+ @first_component.width ||= pw ## added 2010-01-11 23:19
533
+ else
534
+ ph ||= @height/2 - 0 # 1 # added 2010-01-16 12:31 so easier to use
535
+ rc = ph+0 #1 ## added 1 2010-01-11 23:26 else divider overlaps comp
536
+ @first_component.height ||= ph ## added 2010-01-11 23:19
537
+ end
538
+ set_divider_location rc
539
+ end
540
+ def update_first_component
541
+ $log.debug " #{@name} update+first dl: #{@divider_location} "
542
+ return if @divider_location == 0
543
+ @first_component.row(@row)
544
+ @first_component.col(@col)
545
+ $log.debug "UCF #{@name} #{@first_component.row} #{@first_component.col} "
546
+ @first_component.set_buffering(:screen_top => @first_component.row, :screen_left => @first_component.col)
547
+ end
548
+ def update_second_component
549
+ $log.debug " #{@name} update+secoond dl: #{@divider_location} "
550
+ return if @divider_location == 0
551
+ if @orientation == :HORIZONTAL_SPLIT
552
+ @second_component.row(@row+@divider_location)
553
+ @second_component.col(@col)
554
+ else
555
+ @second_component.row(@row)
556
+ @second_component.col(@col+@divider_location)
557
+ end
558
+ $log.debug "UCS #{@name} #{@second_component.row} #{@second_component.col} "
559
+ @second_component.set_buffering(:screen_top => @second_component.row, :screen_left => @second_component.col)
560
+ end
561
+ def repaint # splitpane
562
+ if @graphic.nil?
563
+ @graphic = @target_window || @form.window
564
+ raise "graphic nil in rsplitpane #{@name} " unless @graphic
565
+ end
566
+ #XXX safe_create_buffer
567
+ # this is in case, not called by form
568
+ # we need to clip components
569
+ # note that splitpanes can be nested
570
+
571
+ if @repaint_required
572
+ # Note: this only if major change
573
+ #XXX @graphic.wclear
574
+ @first_component.repaint_all(true) if !@first_component.nil?
575
+ @second_component.repaint_all(true) if !@second_component.nil?
576
+ end
577
+ if @repaint_required
578
+ ## paint border and divider
579
+ $log.debug "SPLP #{@name} repaint split H #{@height} W #{@width} "
580
+ bordercolor = @border_color || $datacolor
581
+ borderatt = @border_attrib || Ncurses::A_NORMAL
582
+ absrow = abscol = 0
583
+ if @use_absolute
584
+ absrow = @row
585
+ abscol = @col
586
+ end
587
+ if @use_absolute
588
+ $log.debug " #{@graphic} calling print_border #{@row} #{@col} "
589
+ @graphic.print_border(@row, @col, @height-1, @width-1, bordercolor, borderatt)
590
+ else
591
+ $log.debug " #{@graphic} calling print_border 0,0"
592
+ @graphic.print_border(0, 0, @height-1, @width-1, bordercolor, borderatt)
593
+ end
594
+ rc = @divider_location
595
+
596
+ @graphic.attron(Ncurses.COLOR_PAIR(bordercolor) | borderatt)
597
+ # 2010-02-14 18:23 - non buffered, have to make relative coords into absolute
598
+ #+ by adding row and col
599
+ if @orientation == :VERTICAL_SPLIT
600
+ $log.debug "SPLP #{@name} prtingign split vline divider 1, rc: #{rc}, h:#{@height} - 2 "
601
+ @graphic.mvvline(absrow+1, rc+abscol, 0, @height-2)
602
+ else
603
+ $log.debug "SPLP #{@name} prtingign split hline divider rc: #{rc} , 1 , w:#{@width} - 2"
604
+ @graphic.mvhline(rc+absrow, abscol+1, 0, @width-2)
605
+ end
606
+ @graphic.attroff(Ncurses.COLOR_PAIR(bordercolor) | borderatt)
607
+ end
608
+ if @first_component != nil
609
+ $log.debug " SPLP #{@name} repaint 1c ..."
610
+ # this means that some components will create a buffer with default top and left of 0 the
611
+ # first time. Is there no way we can tell FC what top and left to use.
612
+ update_first_component
613
+ @first_component.repaint
614
+ # earlier before repaint but bombs since some chaps create buffer in repaint
615
+ #XXX @first_component.get_buffer().set_screen_row_col(1, 1) # check this out XXX
616
+ ## the next block is critical for when we switch from one orientation to the other
617
+ ##+ We want first component to expand as much as possible
618
+ if @orientation == :VERTICAL_SPLIT
619
+ #XXX @first_component.get_buffer().set_screen_max_row_col(@height-2, @divider_location-1)
620
+ else
621
+ #XXX @first_component.get_buffer().set_screen_max_row_col(@divider_location-1, @width-2)
622
+ end
623
+ #XXX ret = @first_component.buffer_to_screen(@graphic)
624
+ #XXX $log.debug " SPLP repaint #{@name} fc ret = #{ret} "
625
+ end
626
+ if @second_component != nil
627
+ $log.debug " SPLP repaint #{@name} 2c ... dl: #{@divider_location} "
628
+ # this is required since c2 gets its row and col only after divider has been set
629
+ update_second_component
630
+ @second_component.repaint unless @divider_location == 0
631
+
632
+ # we need to keep top and left of buffer synced with components row and col.
633
+ # Since buffer has no link to comp therefore it can't check back.
634
+ #XXX @second_component.get_buffer().set_screen_row_col(@second_component.row, @second_component.col)
635
+ if @orientation == :VERTICAL_SPLIT
636
+ #XXX @second_component.get_buffer().set_screen_max_row_col(@height-2, @width-2)
637
+ else
638
+ #XXX @second_component.get_buffer().set_screen_max_row_col(@height-2, @width-2)
639
+ end
640
+
641
+ #XXX ret = @second_component.buffer_to_screen(@graphic)
642
+ #XXX $log.debug " SPLP repaint #{@name} 2c ret = #{ret} "
643
+ end
644
+ #XXX @buffer_modified = true
645
+ @graphic.wrefresh # 2010-02-14 20:18 SUBWIN ONLY ??? what is this doing here ? XXX
646
+ paint
647
+ # TODO
648
+ end
649
+ def getvalue
650
+ # TODO
651
+ end
652
+ def _switch_component
653
+ if @current_component != nil
654
+ if @current_component == @first_component
655
+ @current_component = @second_component
656
+ else
657
+ @current_component = @first_component
658
+ end
659
+ set_form_row
660
+ else
661
+ # this happens in one_tab_expand
662
+ @current_component = @second_component if @first_component.nil?
663
+ @current_component = @first_component if @second_component.nil?
664
+ set_form_row
665
+ end
666
+ end
667
+ ## Handles key for splitpanes
668
+ ## By default, first component gets focus, not the SPL itself.
669
+ ##+ Mostly passing to child, and handling child's left-overs.
670
+ ## NOTE: How do we switch to the other outer SPL?
671
+ def handle_key ch
672
+ _multiplier = ($multiplier == 0 ? 1 : $multiplier )
673
+ @current_component ||= @first_component
674
+ ## 2010-01-15 12:57 this helps me switch between highest level
675
+ ## However, i should do as follows:
676
+ ## If tab on second component, return UNHA so form can take to next field
677
+ ## If B_tab on second comp, switch to first
678
+ ## If B_tab on first comp, return UNHA so form can take to prev field
679
+ if ch == 9
680
+ _switch_component
681
+ return 0
682
+ end
683
+
684
+ if @current_component != nil
685
+ ret = @current_component.handle_key ch
686
+ return ret if ret != :UNHANDLED
687
+ else
688
+ ## added 2010-01-07 18:59 in case nothing in there.
689
+ $log.debug " SPLP #{@name} - no component installed in splitpane"
690
+ #return :UNHANDLED
691
+ end
692
+ $log.debug " splitpane #{@name} gets KEY #{ch}"
693
+ case ch
694
+ when ?\M-w.getbyte(0)
695
+ # switch panes
696
+ if @current_component != nil
697
+ if @current_component == @first_component
698
+ @current_component = @second_component
699
+ else
700
+ @current_component = @first_component
701
+ end
702
+ set_form_row
703
+ else
704
+ _switch_component
705
+ return 0
706
+ # if i've expanded bottom pane, tabbed to opposite higher level, tabbing back
707
+ # brings me to null first pane and i can't go to second, so switch
708
+ # this was added for a non-realistic test program with embedded splitpanes
709
+ #+ but no component inside them. At least one can go from one outer to another.
710
+ #+ In real life, this should not come.
711
+
712
+ return :UNHANDLED
713
+ end
714
+ when ?\M-V.getbyte(0)
715
+ self.orientation(:VERTICAL_SPLIT)
716
+ @repaint_required = true
717
+ when ?\M-H.getbyte(0)
718
+ self.orientation(:HORIZONTAL_SPLIT)
719
+ @repaint_required = true
720
+ when ?\M--.getbyte(0)
721
+ self.set_divider_location(self.divider_location-_multiplier)
722
+ when ?\M-\+.getbyte(0)
723
+ self.set_divider_location(self.divider_location+_multiplier)
724
+ when ?\M-\=.getbyte(0)
725
+ self.set_resize_weight(0.50)
726
+ #when ?\C-u.getbyte(0)
727
+ ## multiplier. Series is 4 16 64
728
+ #@multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
729
+ #return 0
730
+ when ?\C-c.getbyte(0)
731
+ $multiplier = 0
732
+ return 0
733
+ else
734
+ # check for bindings, these cannot override above keys since placed at end
735
+ ret = process_key ch, self
736
+ return :UNHANDLED if ret == :UNHANDLED
737
+ end
738
+ $multiplier = 0
739
+ return 0
740
+ end
741
+ def paint
742
+ @repaint_required = false
743
+ end
744
+ def on_enter
745
+ set_form_row
746
+ end
747
+ def set_form_row
748
+ if !@current_component.nil?
749
+ $log.debug " #{@name} set_form_row calling sfr for #{@current_component.name} "
750
+ @current_component.set_form_row
751
+ @current_component.set_form_col
752
+ end
753
+ end
754
+ # added 2010-02-09 10:10
755
+ # sets the forms cursor column correctly
756
+ # earlier the super was being called which missed out on child's column.
757
+ # Note: splitpane does not use the cursor, so it does not know where cursor should be displayed,
758
+ #+ the child has to decide where it should be displayed.
759
+ def set_form_col
760
+ if !@current_component.nil?
761
+ $log.debug " #{@name} set_form_col calling sfc for #{@current_component.name} "
762
+ @current_component.set_form_col
763
+ end
764
+ end
765
+ private
766
+ #def _other_component
767
+ #if @current_component == @first_component
768
+ #return @second_component
769
+ #end
770
+ #return @first_component
771
+ #end
772
+ ## expand a split to maximum. This is the one_touch_expandable feature
773
+ # Currently mapped to C-w 1 (mnemonic for one touch), or C-w o (vim's only)
774
+ # To revert, you have to unexpand
775
+ # Note: basically, i nil the component that we don't want to see
776
+ def expand
777
+ @is_expanding = true # this is required so i don't check for min_width later
778
+ $log.debug " callign expand "
779
+ if @current_component == @first_component
780
+ @saved_component = @second_component
781
+ @second_component = nil
782
+ if @orientation == :VERTICAL_SPLIT
783
+ set_divider_location @width - 1
784
+ else
785
+ set_divider_location @height - 1
786
+ end
787
+ $log.debug " callign expand 2 nil #{@divider_location}, h:#{@height} w: #{@width} "
788
+ else
789
+ @saved_component = @first_component
790
+ @first_component = nil
791
+ set_divider_location 1
792
+ $log.debug " callign expand 1 nil #{@divider_location}, h:#{@height} w: #{@width} "
793
+ end
794
+ @repaint_required = true
795
+ end
796
+ # after expanding one split, revert to original - actually i reset, rather than revert
797
+ # This only works after expand has been done
798
+ def unexpand
799
+ $log.debug " inside unexpand "
800
+ return unless @saved_component
801
+ if @first_component.nil?
802
+ @first_component = @saved_component
803
+ else
804
+ @second_component = @saved_component
805
+ end
806
+ @saved_component = nil
807
+ @repaint_required = true
808
+ reset_to_preferred_sizes
809
+ end
810
+
811
+ # exchange 2 splits, bound to C-w x
812
+ def exchange
813
+ tmp = @first_component
814
+ @first_component = @second_component
815
+ @second_component = tmp
816
+ @repaint_required = true
817
+ reset_to_preferred_sizes
818
+ end
819
+ end # class SplitPane
820
+ end # module