rbcurse 0.1.3 → 1.1.1

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 (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