rbcurse 1.5.0 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/Makefile +21 -0
  2. data/Manifest.txt +6 -0
  3. data/README.markdown +6 -4
  4. data/TODO +372 -0
  5. data/TODO2.txt +121 -0
  6. data/VERSION +1 -1
  7. data/examples/README.txt +67 -0
  8. data/examples/abasiclist.rb +33 -0
  9. data/examples/alpmenu.rb +42 -0
  10. data/examples/app.rb +859 -0
  11. data/examples/app.sample +17 -0
  12. data/examples/appdirtree.rb +74 -0
  13. data/examples/appemail.rb +191 -0
  14. data/examples/appemaillb.rb +308 -0
  15. data/examples/appgcompose.rb +315 -0
  16. data/examples/atree.rb +64 -0
  17. data/examples/common/file.rb +40 -0
  18. data/examples/common/rmail.rb +257 -0
  19. data/examples/data.txt +683 -0
  20. data/examples/data/README.markdown +9 -0
  21. data/examples/data/brew.txt +38 -0
  22. data/examples/data/color.2 +37 -0
  23. data/examples/data/gemlist.txt +60 -0
  24. data/examples/data/lotr.txt +12 -0
  25. data/examples/data/ports.txt +136 -0
  26. data/examples/data/tasks.txt +27 -0
  27. data/examples/data/todocsv.csv +28 -0
  28. data/examples/data/unix1.txt +21 -0
  29. data/examples/data/unix2.txt +11 -0
  30. data/examples/dbdemo.rb +495 -0
  31. data/examples/deprecated/appgmail.rb +952 -0
  32. data/examples/deprecated/splitp.rb +56 -0
  33. data/examples/deprecated/testscrolllb.rb +86 -0
  34. data/examples/deprecated/testscrollp.rb +88 -0
  35. data/examples/deprecated/testscrollta.rb +80 -0
  36. data/examples/deprecated/testscrolltable.rb +165 -0
  37. data/examples/deprecated/testsplit.rb +87 -0
  38. data/examples/deprecated/testsplit2.rb +123 -0
  39. data/examples/deprecated/testsplit3.rb +215 -0
  40. data/examples/deprecated/testsplit3_1.rb +244 -0
  41. data/examples/deprecated/testsplit3a.rb +215 -0
  42. data/examples/deprecated/testsplit3b.rb +237 -0
  43. data/examples/deprecated/testsplitta.rb +148 -0
  44. data/examples/deprecated/testsplittv.rb +142 -0
  45. data/examples/deprecated/testsplittvv.rb +144 -0
  46. data/examples/deprecated/testtpane.rb +215 -0
  47. data/examples/deprecated/testtpane2.rb +145 -0
  48. data/examples/deprecated/testtpanetable.rb +203 -0
  49. data/examples/dirtree.rb +88 -0
  50. data/examples/experimental/resultsetdemo.rb +280 -0
  51. data/examples/experimental/testmform.rb +35 -0
  52. data/examples/experimental/testscroller.rb +117 -0
  53. data/examples/experimental/teststackflow.rb +111 -0
  54. data/examples/menu1.rb +112 -0
  55. data/examples/multispl.rb +86 -0
  56. data/examples/newmessagebox.rb +131 -0
  57. data/examples/newtabbedwindow.rb +100 -0
  58. data/examples/newtesttabp.rb +121 -0
  59. data/examples/qdfilechooser.rb +68 -0
  60. data/examples/rfe.rb +1239 -0
  61. data/examples/rfe_renderer.rb +121 -0
  62. data/examples/sqlc.rb +454 -0
  63. data/examples/sqlm.rb +437 -0
  64. data/examples/sqlt.rb +408 -0
  65. data/examples/status.txt +68 -0
  66. data/examples/table1.rb +24 -0
  67. data/examples/term2.rb +84 -0
  68. data/examples/test1.rb +239 -0
  69. data/examples/test2.rb +674 -0
  70. data/examples/testapp.rb +44 -0
  71. data/examples/testapp2.rb +58 -0
  72. data/examples/testchars.rb +137 -0
  73. data/examples/testcombo.rb +91 -0
  74. data/examples/testkeypress.rb +66 -0
  75. data/examples/testlistbox.rb +113 -0
  76. data/examples/testmenu.rb +101 -0
  77. data/examples/testmulticomp.rb +70 -0
  78. data/examples/testmulticontainer.rb +94 -0
  79. data/examples/testmultispl.rb +199 -0
  80. data/examples/testree.rb +106 -0
  81. data/examples/testtable.rb +264 -0
  82. data/examples/testtabp.rb +107 -0
  83. data/examples/testtodo.rb +584 -0
  84. data/examples/testvimsplit.rb +112 -0
  85. data/examples/testwsshortcuts.rb +64 -0
  86. data/examples/testwsshortcuts2.rb +126 -0
  87. data/examples/todo.db +0 -0
  88. data/examples/todo.yml +191 -0
  89. data/examples/viewtodo.rb +574 -0
  90. data/lib/rbcurse/deprecated/README.markdown +12 -0
  91. data/lib/rbcurse/deprecated/rpad.rb +375 -0
  92. data/lib/rbcurse/deprecated/rscrollpane.rb +512 -0
  93. data/lib/rbcurse/deprecated/rsplitpane.rb +894 -0
  94. data/lib/rbcurse/deprecated/rsplitpane2.rb +1009 -0
  95. data/lib/rbcurse/deprecated/rviewport.rb +204 -0
  96. data/lib/rbcurse/deprecated/widgets/mapper.rb +130 -0
  97. data/lib/rbcurse/deprecated/widgets/rmessagebox.rb +348 -0
  98. data/lib/rbcurse/deprecated/widgets/rtabbedpane.rb +1158 -0
  99. data/lib/rbcurse/deprecated/widgets/rtabbedwindow.rb +167 -0
  100. data/lib/rbcurse/deprecated/widgets/scrollable.rb +301 -0
  101. data/lib/rbcurse/deprecated/widgets/stdscrwindow.rb +309 -0
  102. data/lib/ver/keyboard2.rb +170 -0
  103. data/test/test_rbcurse.rb +0 -0
  104. metadata +131 -9
@@ -0,0 +1,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