rbcurse 1.5.0 → 1.5.2

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