rbcurse 1.1.5 → 1.2.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. data/CHANGELOG +45 -0
  2. data/Makefile +1 -1
  3. data/Manifest.txt +91 -0
  4. data/NOTES +349 -2
  5. data/README.markdown +12 -0
  6. data/VERSION +1 -1
  7. data/examples/abasiclist.rb +25 -0
  8. data/examples/alpmenu.rb +42 -0
  9. data/examples/app.rb +883 -0
  10. data/examples/appcombo.rb +17 -0
  11. data/examples/appdirtree.rb +73 -0
  12. data/examples/appemail.rb +164 -0
  13. data/examples/appemaillb.rb +308 -0
  14. data/examples/appgcompose.rb +303 -0
  15. data/examples/appgmail.rb +951 -0
  16. data/examples/atree.rb +56 -0
  17. data/examples/dirtree.rb +78 -0
  18. data/examples/focusmanager.rb +31 -0
  19. data/examples/imap.rb +48 -0
  20. data/examples/menu1.rb +79 -0
  21. data/examples/multispl.rb +86 -0
  22. data/examples/rfe.rb +3 -4
  23. data/examples/rmail.rb +188 -0
  24. data/examples/s.rb +10 -0
  25. data/examples/scrollbar.rb +104 -0
  26. data/examples/splitp.rb +56 -0
  27. data/examples/table1.rb +30 -0
  28. data/examples/term.rb +48 -0
  29. data/examples/term2.rb +54 -0
  30. data/examples/test1.rb +4 -2
  31. data/examples/test2.rb +9 -9
  32. data/examples/testapp.rb +44 -0
  33. data/examples/testapp2.rb +51 -0
  34. data/examples/testcombo.rb +2 -2
  35. data/examples/testgmail.rb +46 -0
  36. data/examples/testlistbox.rb +0 -1
  37. data/examples/testmultispl.rb +199 -0
  38. data/examples/testree.rb +127 -0
  39. data/examples/testscroller.rb +0 -1
  40. data/examples/testscrolllb.rb +1 -1
  41. data/examples/testscrollp.rb +2 -1
  42. data/examples/testscrollta.rb +1 -1
  43. data/examples/testscrolltable.rb +1 -2
  44. data/examples/testsplit.rb +1 -1
  45. data/examples/testsplit2.rb +1 -1
  46. data/examples/testsplit3.rb +1 -1
  47. data/examples/testsplit3_1.rb +1 -1
  48. data/examples/testsplit3a.rb +1 -1
  49. data/examples/testsplit3b.rb +1 -1
  50. data/examples/testsplitta.rb +1 -1
  51. data/examples/testsplittv.rb +1 -1
  52. data/examples/testsplittvv.rb +1 -1
  53. data/examples/testtodo.rb +491 -488
  54. data/examples/testvimsplit.rb +111 -0
  55. data/examples/todo.db +0 -0
  56. data/examples/todocsv.csv +28 -0
  57. data/examples/viewtodo.rb +408 -403
  58. data/lib/rbcurse/action.rb +1 -0
  59. data/lib/rbcurse/app.rb +1294 -0
  60. data/lib/rbcurse/applicationheader.rb +7 -2
  61. data/lib/rbcurse/checkboxcellrenderer.rb +0 -12
  62. data/lib/rbcurse/colormap.rb +34 -8
  63. data/lib/rbcurse/comboboxcellrenderer.rb +0 -11
  64. data/lib/rbcurse/defaultlistselectionmodel.rb +23 -7
  65. data/lib/rbcurse/extras/bottomline.rb +1681 -0
  66. data/lib/rbcurse/extras/directorylist.rb +445 -0
  67. data/lib/rbcurse/extras/directorytree.rb +69 -0
  68. data/lib/rbcurse/extras/divider.rb +310 -0
  69. data/lib/rbcurse/extras/focusmanager.rb +31 -0
  70. data/lib/rbcurse/extras/listselectable.rb +222 -0
  71. data/lib/rbcurse/extras/masterdetail.rb +164 -0
  72. data/lib/rbcurse/extras/menutree.rb +63 -0
  73. data/lib/rbcurse/extras/rlink.rb +27 -0
  74. data/lib/rbcurse/extras/rmenulink.rb +21 -0
  75. data/lib/rbcurse/extras/scrollbar.rb +134 -0
  76. data/lib/rbcurse/extras/stdscrwindow.rb +247 -0
  77. data/lib/rbcurse/extras/tabular.rb +258 -0
  78. data/lib/rbcurse/extras/tabularwidget.rb +1070 -0
  79. data/lib/rbcurse/extras/viewer.rb +106 -0
  80. data/lib/rbcurse/io.rb +137 -80
  81. data/lib/rbcurse/keylabelprinter.rb +4 -0
  82. data/lib/rbcurse/listcellrenderer.rb +91 -59
  83. data/lib/rbcurse/listscrollable.rb +93 -95
  84. data/lib/rbcurse/listselectable.rb +60 -7
  85. data/lib/rbcurse/ractionevent.rb +67 -0
  86. data/lib/rbcurse/rbasiclistbox.rb +688 -0
  87. data/lib/rbcurse/rcombo.rb +5 -5
  88. data/lib/rbcurse/rcommandwindow.rb +555 -0
  89. data/lib/rbcurse/rinputdataevent.rb +12 -0
  90. data/lib/rbcurse/rlistbox.rb +305 -124
  91. data/lib/rbcurse/rmenu.rb +99 -46
  92. data/lib/rbcurse/rmessagebox.rb +13 -6
  93. data/lib/rbcurse/rmulticontainer.rb +54 -93
  94. data/lib/rbcurse/rmultisplit.rb +731 -0
  95. data/lib/rbcurse/rmultitextview.rb +3 -2
  96. data/lib/rbcurse/rpopupmenu.rb +0 -1
  97. data/lib/rbcurse/rprogress.rb +117 -0
  98. data/lib/rbcurse/rscrollpane.rb +2 -1
  99. data/lib/rbcurse/rsplitpane.rb +94 -20
  100. data/lib/rbcurse/rsplitpane2.rb +1009 -0
  101. data/lib/rbcurse/rtabbedpane.rb +3 -2
  102. data/lib/rbcurse/rtabbedwindow.rb +0 -1
  103. data/lib/rbcurse/rtable.rb +92 -64
  104. data/lib/rbcurse/rtextarea.rb +91 -57
  105. data/lib/rbcurse/rtextview.rb +223 -70
  106. data/lib/rbcurse/rtree.rb +723 -0
  107. data/lib/rbcurse/rviewport.rb +2 -1
  108. data/lib/rbcurse/rvimsplit.rb +768 -0
  109. data/lib/rbcurse/rwidget.rb +524 -325
  110. data/lib/rbcurse/table/tablecellrenderer.rb +1 -1
  111. data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -1
  112. data/lib/rbcurse/tree/treecellrenderer.rb +137 -0
  113. data/lib/rbcurse/tree/treemodel.rb +428 -0
  114. data/lib/rbcurse/vieditable.rb +14 -13
  115. data/lib/ver/ncurses.rb +6 -0
  116. data/lib/ver/window.rb +67 -32
  117. metadata +99 -23
  118. data/bin/rbcurse +0 -0
  119. data/examples/rvimsplit.rb +0 -376
  120. data/examples/todo.rb +0 -1
  121. data/lib/rbcurse/rform.rb +0 -845
  122. data/lib/rbcurse/selectable.rb +0 -94
  123. data/rbcurse.gemspec +0 -188
@@ -175,8 +175,9 @@ module RubyCurses
175
175
  $log.debug " file edit got cb : #{@current_buffer} "
176
176
  set_current_buffer
177
177
  rescue => err
178
- $error_message = "Error: #{err} "
179
- @form.window.print_error_message
178
+ # $error_message = "Error: #{err} " # changed 2010 dts
179
+ $error_message.value = "Error: #{err} "
180
+ #@form.window.print_error_message
180
181
  Ncurses.beep
181
182
  return -1
182
183
  end
@@ -705,7 +705,6 @@ module RubyCurses
705
705
  end # menubar
706
706
 
707
707
  class CheckBoxMenuItem < MenuItem
708
- include DSL
709
708
  attr_reader :checkbox
710
709
  def initialize text, mnemonic=nil, &block
711
710
  @checkbox = CheckBox.new nil
@@ -0,0 +1,117 @@
1
+ require 'ncurses'
2
+ require 'logger'
3
+ require 'rbcurse'
4
+
5
+ include Ncurses
6
+ include RubyCurses
7
+ module RubyCurses
8
+ extend self
9
+ ##
10
+ # TODO user may want to print a label on progress: like not started or complete.
11
+ class Progress < Widget
12
+ dsl_property :width # please give this to ensure the we only print this much
13
+ dsl_property :fraction # how much to cover
14
+ dsl_property :char # what char to use for filling, default space
15
+ dsl_property :text # text to put over bar
16
+ dsl_accessor :style # :old or nil/anything else
17
+ dsl_accessor :surround_chars # "[]"
18
+
19
+ def initialize form, config={}, &block
20
+
21
+ @row = config.fetch("row",-1)
22
+ @col = config.fetch("col",-1)
23
+ @bgcolor = config.fetch("bgcolor", $def_bg_color)
24
+ @color = config.fetch("color", $def_fg_color)
25
+ @editable = false
26
+ @focusable = false
27
+ super
28
+ @surround_chars ||= "[]" # for :old style
29
+ @repaint_required = true
30
+ end
31
+ def getvalue
32
+ @fraction || 0.0
33
+ end
34
+
35
+ ##
36
+ #
37
+ def repaint
38
+ return unless @repaint_required
39
+ $log.debug " XXXX PBAR inside repaint #{@color} , #{@fraction} "
40
+ r,c = rowcol
41
+ #value = getvalue_for_paint
42
+ acolor = get_color @bgcolor
43
+ bcolor = get_color @color
44
+ @graphic = @form.window if @graphic.nil? ## HACK messagebox givig this in repaint, 423 not working ??
45
+ len = 0
46
+ w2 = @width - 6 #2 account for brackets and printing of percentage
47
+ if @fraction
48
+ @fraction = 1.0 if @fraction > 1.0
49
+ @fraction = 0 if @fraction < 0
50
+ if @fraction > 0
51
+ len = @fraction * @width
52
+ end
53
+ end
54
+ if @style == :old
55
+ ftext=""
56
+ char = @char || "="
57
+ if @fraction && @fraction >= 0
58
+ len = @fraction * (w2)
59
+ ftext << sprintf("%3d%s",(@fraction * 100).to_i, "%")
60
+ end
61
+ incomplete = w2 - len
62
+ complete = len
63
+ # I am printing 2 times since sometimes the ending bracket gets printed one position less
64
+ str = @surround_chars[0] + " "*w2 + @surround_chars[1] + ftext
65
+ @graphic.printstring r, c, str , acolor,@attr
66
+ str = char*complete
67
+ str[-1] = ">" if char == "=" && complete > 2
68
+ @graphic.printstring r, c+1, str , acolor,@attr
69
+ else
70
+
71
+ char = @char || " "
72
+ # first print the background horizonal bar
73
+ @graphic.printstring r, c, " " * @width , acolor,@attr
74
+
75
+ # if the user has passed a percentage we need to print that in @color
76
+ if @fraction
77
+ #bcolor = get_color @color
78
+ #@fraction = 1.0 if @fraction > 1.0
79
+ #@fraction = 0 if @fraction < 0
80
+ #if @fraction > 0
81
+ #len = @fraction * @width
82
+ #char = @char || " "
83
+
84
+ # if text is to printed over the bar
85
+ if @text
86
+ textcolor = get_color $datacolor, 'black'
87
+ txt = @text
88
+ txt = @text[0..@width] if @text.length > @width
89
+ textattr = 'bold'
90
+ # write the text in a color that contrasts with the background
91
+ # typically black
92
+ @graphic.printstring r, c, txt , textcolor, textattr if @text
93
+
94
+ # now write the text again, in a color that contrasts with the progress
95
+ # bar color that is expanding. However, the text must be padded to len and truncated
96
+ # to len as well. it must be exactly len in size.
97
+ txt = sprintf("%-*s", len, txt)
98
+ if len > 0
99
+ if len < txt.length
100
+ txt = txt[0..len]
101
+ end
102
+ textcolor = get_color $datacolor, 'white', @color
103
+ @graphic.printstring r, c, txt , textcolor, textattr if @text
104
+ end
105
+ else
106
+ # no text was given just print a horizontal bar
107
+ @graphic.printstring r, c, char * len , bcolor, 'reverse'
108
+ end
109
+ end # frac > 0
110
+ end # fraction
111
+ end # style
112
+ @repaint_required = false
113
+ end
114
+ def repaint_old
115
+ end
116
+ # ADD HERE progress
117
+ end
@@ -63,6 +63,7 @@ module RubyCurses
63
63
  super
64
64
  @row_offset = @col_offset = 1
65
65
  init_vars
66
+ @_events.push :STATE_CHANGE
66
67
  # $log.debug " SCROLLPANE recvs form #{form.name}, #{form.window.name} " unless form.nil?
67
68
 
68
69
 
@@ -331,7 +332,7 @@ module RubyCurses
331
332
  @child.cols_panned = @child.cols_panned-1 if ret
332
333
  @form.setrowcol @form.row, @form.col-1+@col_outofbounds if ret
333
334
  }
334
- when KEY_BACKSPACE, 127
335
+ when KEY_BACKSPACE, KEY_BSPACE
335
336
  ret = cursor_backward
336
337
  #when ?\C-u.getbyte(0)
337
338
  ## multiplier. Series is 4 16 64
@@ -1,15 +1,17 @@
1
1
  =begin
2
2
  * Name: SplitPane
3
- * $Id$
3
+
4
4
  * Description: allows user to split 2 components vertically or horizontally
5
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.
6
10
  * Author: rkumar (arunachalesha)
7
11
  * file created 2009-10-27 19:20
8
12
  * major change: Feb 2010, removed buffers
9
13
  Todo:
10
- * TODO remove components
11
14
 
12
- * XXX Does SPLP need to listen for changes in children
13
15
  --------
14
16
  * License:
15
17
  Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
@@ -91,7 +93,7 @@ module RubyCurses
91
93
  @orientation ||= :HORIZONTAL_SPLIT # added 2010-01-13 15:05 since not set
92
94
 
93
95
  # 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.
96
+ @_child_buffering = false # private, internal. not to be changed by callers.
95
97
  @one_touch_expandable = true
96
98
  @is_expanding = false
97
99
 
@@ -125,25 +127,32 @@ module RubyCurses
125
127
  comp.should_create_buffer = @_child_buffering
126
128
  # adding ext_offsets 2010-02-09 13:39
127
129
  # 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
+ #$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} "
130
132
  #XXX comp.ext_row_offset += @ext_row_offset + @row - @subform1.window.top #0# screen_row
131
133
  #XXX comp.ext_col_offset += @ext_col_offset + @col -@subform1.window.left # 0# screen_col
132
134
  comp.ext_row_offset += @ext_row_offset + @row #- @subform1.window.top #0# screen_row
133
135
  comp.ext_col_offset += @ext_col_offset + @col #-@subform1.window.left # 0# screen_col
134
136
 
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
+ # The suggestd heights depend on orientation.
137
138
  a = 0 # = 2
138
139
  if @orientation == :HORIZONTAL_SPLIT
140
+ $log.debug "H FC ht #{comp.height} , w #{comp.width} #{comp.name}, #{comp.class} "
139
141
  @first_component.height ||= @first_component.preferred_height || @height/2 - 1 #1
140
142
  @first_component.width ||= @first_component.preferred_width || @width - a
143
+ $log.debug " FC2 ht #{comp.height} , w #{comp.width} #{comp.name} "
141
144
  else
145
+ $log.debug "V FC ht #{comp.height} , w #{comp.width} #{comp.name} "
142
146
  @first_component.height ||= @first_component.preferred_height || @height - a
143
147
  @first_component.width ||= @first_component.preferred_width || @width/2 -1
148
+ $log.debug " FC2 ht #{comp.height} , w #{comp.width} #{comp.name} "
144
149
  end
145
150
  #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 )
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
147
156
  comp.set_buffering(:screen_top => @row, :screen_left => @col)
148
157
  @first_component.min_height ||= 5
149
158
  @first_component.min_width ||= 5
@@ -191,9 +200,9 @@ module RubyCurses
191
200
  comp.ext_row_offset += @ext_row_offset + @row
192
201
  $log.debug "SPLP exp_col #{@name} 2 #{comp}: #{comp.ext_col_offset} += #{@ext_col_offset} + #{@col} "
193
202
  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 )
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 )
197
206
  $log.debug " setting c2 screen_top n left to #{@row} #{@col} "
198
207
  @second_component.set_buffering(:screen_top => @row, :screen_left => @col)
199
208
  @second_component.min_height ||= 5 # added 2010-01-16 12:37
@@ -362,9 +371,12 @@ module RubyCurses
362
371
  $log.debug " #{@name} set div location, setting first comp width #{rc}"
363
372
  if !@cascade_changes.nil?
364
373
  if @orientation == :VERTICAL_SPLIT
374
+ $log.warn " SPLP height nil in #{@name} #{@first_component.name} " unless @height
375
+ @height ||= 23
365
376
  @first_component.width(rc-0) #+ @col_offset + @divider_offset
366
377
  @first_component.height(@height-0) #2+ @col_offset + @divider_offset
367
378
  else
379
+ $log.warn " SPLP width nil in #{@name} #{@first_component.name} " unless @width
368
380
  @first_component.height(rc+0) #-1) #1+ @col_offset + @divider_offset
369
381
  @first_component.width(@width-0) #2+ @col_offset + @divider_offset
370
382
  end
@@ -421,7 +433,7 @@ module RubyCurses
421
433
  #@second_component.width = @width - (rc + @col_offset + @divider_offset + 1)
422
434
  #@second_component.height = @height-2 #+ @row_offset + @divider_offset
423
435
  @second_component.width = @width - rc #+ @col_offset + @divider_offset + 1)
424
- @second_component.height = @height-0 #+ @row_offset + @divider_offset
436
+ @second_component.height = @height #+ @row_offset + @divider_offset
425
437
  else
426
438
  # added 2010-01-09 22:49 to be tested XXX
427
439
  # In a vertical split, if widgets w and thus buffer w is less than
@@ -474,6 +486,8 @@ module RubyCurses
474
486
  end
475
487
  end
476
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
477
491
  # i need to keep top and left sync for print_border which uses it UGH !!!
478
492
  if !@second_component.get_buffer().nil?
479
493
  # now that TV and others are creating a buffer in repaint we need another way to set
@@ -543,10 +557,13 @@ module RubyCurses
543
557
  @first_component.row(@row)
544
558
  @first_component.col(@col)
545
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 )
546
562
  @first_component.set_buffering(:screen_top => @first_component.row, :screen_left => @first_component.col)
547
563
  end
548
564
  def update_second_component
549
565
  $log.debug " #{@name} update+secoond dl: #{@divider_location} "
566
+ comp = @second_component
550
567
  return if @divider_location == 0
551
568
  if @orientation == :HORIZONTAL_SPLIT
552
569
  @second_component.row(@row+@divider_location)
@@ -556,6 +573,8 @@ module RubyCurses
556
573
  @second_component.col(@col+@divider_location)
557
574
  end
558
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 )
559
578
  @second_component.set_buffering(:screen_top => @second_component.row, :screen_left => @second_component.col)
560
579
  end
561
580
  def repaint # splitpane
@@ -649,12 +668,22 @@ module RubyCurses
649
668
  def getvalue
650
669
  # TODO
651
670
  end
652
- def _switch_component
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
653
674
  if @current_component != nil
654
675
  if @current_component == @first_component
655
- @current_component = @second_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
656
683
  else
657
- @current_component = @first_component
684
+ #@current_component = @first_component
685
+ @current_component.on_leave
686
+ return :UNHANDLED # try to get him out.
658
687
  end
659
688
  set_form_row
660
689
  else
@@ -663,6 +692,31 @@ module RubyCurses
663
692
  @current_component = @first_component if @second_component.nil?
664
693
  set_form_row
665
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
666
720
  end
667
721
  ## Handles key for splitpanes
668
722
  ## By default, first component gets focus, not the SPL itself.
@@ -677,11 +731,12 @@ module RubyCurses
677
731
  ## If B_tab on second comp, switch to first
678
732
  ## If B_tab on first comp, return UNHA so form can take to prev field
679
733
  if ch == 9
680
- _switch_component
681
- return 0
734
+ #return goto_next_component
735
+ #return 0
682
736
  end
683
737
 
684
738
  if @current_component != nil
739
+ # give the child the key to handle, this is the last current child
685
740
  ret = @current_component.handle_key ch
686
741
  return ret if ret != :UNHANDLED
687
742
  else
@@ -691,6 +746,11 @@ module RubyCurses
691
746
  end
692
747
  $log.debug " splitpane #{@name} gets KEY #{ch}"
693
748
  case ch
749
+ when KEY_TAB
750
+ return goto_next_component
751
+ when KEY_BTAB
752
+ return goto_prev_component
753
+ #return 0
694
754
  when ?\M-w.getbyte(0)
695
755
  # switch panes
696
756
  if @current_component != nil
@@ -701,8 +761,8 @@ module RubyCurses
701
761
  end
702
762
  set_form_row
703
763
  else
704
- _switch_component
705
- return 0
764
+ return goto_next_component
765
+ #return 0
706
766
  # if i've expanded bottom pane, tabbed to opposite higher level, tabbing back
707
767
  # brings me to null first pane and i can't go to second, so switch
708
768
  # this was added for a non-realistic test program with embedded splitpanes
@@ -741,9 +801,23 @@ module RubyCurses
741
801
  def paint
742
802
  @repaint_required = false
743
803
  end
804
+ # on entering this component
805
+ # place user on first child
806
+ # TODO if he backtabs in then place on last
744
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
+
745
816
  set_form_row
746
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.
747
821
  def set_form_row
748
822
  if !@current_component.nil?
749
823
  $log.debug " #{@name} set_form_row calling sfr for #{@current_component.name} "
@@ -0,0 +1,1009 @@
1
+ =begin
2
+ * Name: SplitPane
3
+ * Description: allows user to split 2 components vertically or horizontally
4
+ Try to make it simpler for user to use.
5
+ Should work with no constraints, and take percentage or integer for div location. No more.
6
+ **** THIS IS EXPERIMENTAL AND NEW
7
+ NOTE: it can crash if you change orientation after painting and if you try too much resizing.
8
+ Also it will not notify children of changes in size. it avoids all complexity and tries
9
+ to be as simple as possible.
10
+ * NOTE that VERTICAL_SPLIT means the *divider* is vertical.
11
+ * Recommend you move to rvimsplit.rb
12
+ * If you insist on using this, please copy it off into your own
13
+ * application folder in case i deprecate it.
14
+ * Author: rkumar (arunachalesha)
15
+ * file created 2010-09-14 10:31
16
+ * major change: Feb 2010, removed buffers
17
+ Todo:
18
+
19
+ --------
20
+ * License:
21
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
22
+
23
+ =end
24
+ #require 'rubygems'
25
+ require 'ncurses'
26
+ require 'logger'
27
+ require 'rbcurse'
28
+
29
+ include Ncurses
30
+ include RubyCurses
31
+ module RubyCurses
32
+ extend self
33
+
34
+ ##
35
+ # A simpler SplitPane allows user to split 2 components vertically or horizontally.
36
+ # such as textarea, table or a list.
37
+ # Besides components, it allows user to set position of divider using divider_at (fraction).
38
+ # @since 1.2.0
39
+ # TODO -
40
+
41
+ class SplitPane < Widget
42
+ #dsl_property :height # added to widget and here as method
43
+ #dsl_accessor :width # already present in widget
44
+ # row and col also present int widget
45
+ #dsl_accessor :first_component # top or left component that is being viewed
46
+ #dsl_accessor :second_component # right or bottom component that is being viewed
47
+ # dsl_property` :orientation # :VERTICAL_SPLIT or :HORIZONTAL_SPLIT # changed 2010
48
+ attr_reader :orientation # :VERTICAL_SPLIT or :HORIZONTAL_SPLIT
49
+ attr_reader :divider_location #
50
+ attr_reader :resize_weight
51
+ attr_writer :last_divider_location
52
+ dsl_accessor :border_color
53
+ dsl_accessor :border_attrib
54
+ attr_accessor :one_touch_expandable # boolean, default true
55
+
56
+ def initialize form, config={}, &block
57
+ @focusable = true
58
+ @editable = false
59
+ #@left_margin = 1
60
+ @row = 0
61
+ @col = 0
62
+ super
63
+ @row_offset = @col_offset = 1
64
+ @orig_col = @col
65
+ #@use_absolute = true; # set to true if not using subwins XXX
66
+ init_vars
67
+ end
68
+ def init_vars
69
+ @orientation ||= :HORIZONTAL_SPLIT # added 2010-01-13 15:05 since not set
70
+ @divider_at ||= 0.5
71
+ if @orientation == :VERTICAL_SPLIT
72
+ @divider_location ||= (@width * @divider_at).to_i
73
+ else
74
+ @divider_location ||= (@height * @divider_at).to_i
75
+ end
76
+ @divider_offset ||= 0
77
+
78
+ # cascade_changes keeps the child exactly sized as per the pane which looks nice
79
+ #+ but may not really be what you want.
80
+ @cascade_changes=true
81
+ ## if this splp is increased (ht or wid) then expand the child
82
+ @cascade_boundary_changes = true
83
+
84
+ # true means will request child to create a buffer, since cropping will be needed
85
+ @_child_buffering = false # private, internal. not to be changed by callers.
86
+ @one_touch_expandable = true
87
+ @is_expanding = false
88
+
89
+ bind_key([?\C-w, ?o], :expand)
90
+ bind_key([?\C-w, ?1], :expand)
91
+ bind_key([?\C-w, ?2], :unexpand)
92
+ bind_key([?\C-w, ?x], :exchange)
93
+
94
+ end
95
+ def orientation(*val)
96
+ if val.empty?
97
+ return @orientation
98
+ else
99
+ if @orientation.nil?
100
+ @orientation = val[0]
101
+ $log.debug " orientation returning without changing divi loc to #{@divider_location} "
102
+ return
103
+ end
104
+ $log.debug " orientation CAME HERE #{val[0]} prev div loc was #{@divider_location} "
105
+ case val[0]
106
+ when :VERTICAL_SPLIT
107
+ @divider_location = (@width * @divider_at).to_i
108
+ when :HORIZONTAL_SPLIT
109
+ @divider_location = (@height * @divider_at).to_i
110
+ else
111
+ raise ArgumentError "orientation value is wrong"
112
+ end
113
+ @orientation = val[0]
114
+ @repaint_required = true
115
+ $log.debug " orientation set divi loc to #{@divider_location} "
116
+ end
117
+ end
118
+ # sets a fraction to use to determine placement of divider_location and consequently
119
+ # size of components
120
+ # @param [Float] percent for placing divider e.g. 0.5. Should be between 0.2 and 0.8
121
+ # @return [Float] fraction if no param passed
122
+ def divider_at(*val)
123
+ if val.empty?
124
+ return @divider_at
125
+ else
126
+ where = val[0]
127
+ raise ArgumentError "divider_at value should be between 0.2 and 0.8" if where < 0.2 || where > 0.8
128
+ @divider_at = where
129
+ @repaint_required = true
130
+ end
131
+ self
132
+ end
133
+
134
+ ##
135
+ # Sets the first component (top or left)
136
+ #
137
+ # @param [String] comp comment
138
+ # @return [true, false] comment
139
+ #
140
+ # XXX This originally working fine if the child was also a splitpane
141
+ # Now with other comps, it works fine with them if they create a buffer in const
142
+ # but now SPLP bombs since it creates a buffer in repaint.
143
+
144
+ def first_component(comp)
145
+ screen_col = 1
146
+ screen_row = 1 # offset for copying pad 2010-02-09 19:02
147
+ @first_component = comp;
148
+ @first_component.parent_component = self ## added 2010-01-13 12:54
149
+ ## These setting are quite critical, otherwise on startup
150
+ ##+ it can create 2 tiled buffers.
151
+ a = 0 # =1
152
+ @first_component.row(@row + a)
153
+ @first_component.col(@col + a)
154
+ @first_component.min_height ||= 5
155
+ @first_component.min_width ||= 5
156
+ comp.should_create_buffer = @_child_buffering
157
+ comp.ext_row_offset += @ext_row_offset + @row #- @subform1.window.top #0# screen_row
158
+ comp.ext_col_offset += @ext_col_offset + @col #-@subform1.window.left # 0# screen_col
159
+
160
+ return # XXX
161
+
162
+ # The suggestd heights depend on orientation.
163
+ a = 0 # = 2
164
+ if @orientation == :HORIZONTAL_SPLIT
165
+ raise "SPLP width of #{comp.name} required " unless @width
166
+ $log.debug "H FC ht #{comp.height} , w #{comp.width} #{comp.name}, #{comp.class} "
167
+ @first_component.height = (@height * @divider_at - 1).to_i #1
168
+ @first_component.width = @width - a
169
+ $log.debug " FC2 ht #{comp.height} , w #{comp.width} #{comp.name} "
170
+ @divider_location = comp.height + 1
171
+ else
172
+ raise "SPLP height of #{comp.name} required " unless @height
173
+ $log.debug "V FC ht #{comp.height} , w #{comp.width} #{comp.name} "
174
+ @first_component.height = @height - a
175
+ @first_component.width = (@width * @divider_at -1).to_i
176
+ @divider_location = comp.width + 1
177
+ $log.debug " FC2 ht #{comp.height} , w #{comp.width} #{comp.name} "
178
+ end
179
+ # form may not be available at this point if setting internal componnedts FC first
180
+ #comp.set_buffering(:target_window => @target_window || @form.window, :bottom => comp.height-1, :right => comp.width-1, :form => @form )
181
+ # added 2010-09-13 23:33 XXX
182
+ raise "first components height or preferred height is required" unless comp.height
183
+ raise "first components width or preferred width is required" unless comp.width
184
+ comp.set_buffering(:screen_top => @row, :screen_left => @col)
185
+ @first_component.min_height ||= 5
186
+ @first_component.min_width ||= 5
187
+
188
+
189
+ # if i set the above 2 to 0, it starts fine but then on any action loses the first row.
190
+ # Just begun happeing suddenly! 2010-01-11 23:38
191
+
192
+ # explicit top and left.
193
+ if !@first_component.get_buffer().nil?
194
+ @first_component.get_buffer().set_screen_row_col(screen_row, screen_col)
195
+ end
196
+ @current_component ||= @first_component # added 2010-01-13 15:39
197
+ end # first_component
198
+ ##
199
+ # Sets the second component (bottom or right)
200
+ #
201
+ # @param [String] comp comment
202
+ # @return [true, false] comment
203
+
204
+ def second_component(comp)
205
+ $log.debug " #{@name}: #{comp.name} inside second component, div loc: #{@divider_location}, #{@col_offset} parent #{@row} #{@col}, h #{@height} w #{@width} "
206
+ @second_component = comp;
207
+ @second_component.parent_component = self ## added 2010-01-13 12:54
208
+ comp.should_create_buffer = @_child_buffering
209
+ @second_component.min_height ||= 5 # added 2010-01-16 12:37
210
+ @second_component.min_width ||= 5 # added 2010-01-16 12:37
211
+ return # XXX
212
+
213
+ ## jeez, we;ve postponed create of buffer XX
214
+ ## trying out 2010-01-16 12:11 so component does not have to set size
215
+ # The suggestd heights really depend on orientation.
216
+ if @orientation == :HORIZONTAL_SPLIT
217
+ @second_component.row(@row+@divider_location)
218
+ @second_component.col(@col+@col_offset)
219
+ @second_component.height = (@height * @divider_at - 1).to_i #1
220
+ @second_component.width = @width - 0 # 2
221
+ $log.debug "H SC2 ht #{comp.height} , w #{comp.width} #{comp.name} "
222
+ $log.debug "H SC2 rc #{comp.row} , c #{comp.col} #{comp.name} "
223
+ else
224
+ @second_component.row(@row+@row_offset)
225
+ @second_component.col(@col+@divider_location)
226
+ @second_component.height = @height - 0 # 2
227
+ @second_component.width = (@width * @divider_at -4).to_i # 1 to 4 2010-01-16 22:10 TRYING COULD BREAK STUFF testsplit3a;s right splitpane
228
+ $log.debug "V SC2 ht #{comp.height} , w #{comp.width} #{comp.name} "
229
+ $log.debug "V SC2 rc #{comp.row} , c #{comp.col} #{comp.name} "
230
+ # added 2010-01-16 23:55
231
+ end
232
+ comp.ext_row_offset += @ext_row_offset + @row
233
+ $log.debug "SPLP exp_col #{@name} 2 #{comp}: #{comp.ext_col_offset} += #{@ext_col_offset} + #{@col} "
234
+ comp.ext_col_offset += @ext_col_offset + @col
235
+ #comp.set_buffering(:target_window => @target_window || @form.window, :bottom => comp.height-1,
236
+ #:right => comp.width-1, :form => @form )
237
+ $log.debug " setting c2 screen_top n left to #{@row} #{@col} "
238
+ @second_component.set_buffering(:screen_top => @row, :screen_left => @col)
239
+ end # second_component
240
+
241
+ ## faster access to the 2 components
242
+ def c1; @first_component; end
243
+ def c2; @second_component; end
244
+
245
+ ##
246
+ #
247
+ # change height of splitpane
248
+ # @param val [int] new height of splitpane
249
+ # @return [int] old ht if nil passed
250
+ def OLDheight(*val)
251
+ return @height if val.empty?
252
+ oldvalue = @height || 0
253
+ super
254
+ @height = val[0]
255
+ return if @first_component.nil? or @second_component.nil?
256
+ delta = @height - oldvalue
257
+ @repaint_required = true
258
+ if !@cascade_boundary_changes.nil?
259
+ # must tell children if height changed which will happen in nested splitpanes
260
+ # must adjust to components own offsets too
261
+ if @orientation == :VERTICAL_SPLIT
262
+ @first_component.height += delta
263
+ @second_component.height += delta
264
+ # RFED16 2010-02-16 20:44 whenever we change dimensions need to update
265
+ # buffering_params since we are not using Pad's buffer_to_screen
266
+ @second_component.set_buffering(:bottom => @second_component.height-1)
267
+ @first_component.set_buffering(:bottom => @first_component.height-1)
268
+ else
269
+ @second_component.height += delta
270
+ @second_component.set_buffering(:bottom => @second_component.height-1)
271
+ end
272
+ end
273
+ end
274
+ ##
275
+ # change width of splitpane
276
+ # @param val [int, nil] new width of splitpane
277
+ # @return [int] old width if nil passed
278
+ # NOTE: if VERTICAL, then expand or contract only second
279
+ # If HORIZ then expand / contract both
280
+ # Actually this is very complicated since reducing should take into account min_width
281
+ def OLDwidth(*val)
282
+ return @width if val.empty?
283
+ # must tell children if height changed which will happen in nested splitpanes
284
+ oldvalue = @width || 0
285
+ super
286
+ @width = val[0]
287
+ delta = @width - oldvalue
288
+ $log.debug " SPLP #{@name} width #{oldvalue}, #{@width}, #{delta} "
289
+ @repaint_required = true
290
+ if !@cascade_boundary_changes.nil?
291
+ # must adjust to components own offsets too
292
+ # NOTE: 2010-01-10 20:11 if we increase width by one, each time will both components get increased by one.
293
+ if @orientation == :HORIZONTAL_SPLIT
294
+ if @first_component != nil
295
+ old = @first_component.width
296
+ #@first_component.width = @width - @col_offset + @divider_offset
297
+ @first_component.width += delta
298
+ $log.debug "width() #{@name} set fc width to #{@first_component.width}, old was #{old} "
299
+ @first_component.set_buffering(:right => @first_component.width-1)
300
+ end
301
+ # added 2010-01-11 23:02 horiz 2c not displaying since width issue
302
+ if @second_component != nil
303
+ old = @second_component.width
304
+ #@first_component.width = @width - @col_offset + @divider_offset
305
+ @second_component.width += delta
306
+ @second_component.set_buffering(:right => @second_component.width-1)
307
+ $log.debug "width() #{@name} set 2c width to #{@second_component.width}, old was #{old} "
308
+ end
309
+ else
310
+ rc = @divider_location
311
+ # ## next change should only happen if sc w < ...
312
+ # 2010-01-11 22:11
313
+ # if @second_component.width < @width - (rc + @col_offset + @divider_offset + 1)
314
+ if @second_component != nil
315
+ if @second_component.width < @width - (rc + @col_offset + @divider_offset + 1)
316
+ old = @second_component.width
317
+ #@second_component.width = @width - @col_offset + @divider_offset
318
+ @second_component.width += delta
319
+ @second_component.set_buffering(:right => @second_component.width-1)
320
+ $log.debug "width() #{@name} set 2c width to #{@second_component.width} , old was #{old} "
321
+ end
322
+ end
323
+ end
324
+ end
325
+ end
326
+ # set location of divider (row or col depending on orientation)
327
+ # internally sets the second components row or col
328
+ # also to set widths or heights
329
+ # Check minimum sizes are not disrespected
330
+ # @param rc [int] row or column to place divider
331
+ # 2010-01-09 23:07 : added sections to prevent a process crash courtesy copywin
332
+ #+ when pane size exceeds buffer size, so in these cases we increase size of component
333
+ #+ and therefore buffer size. Needs to be tested for VERTICAL.
334
+ # If this returns :ERROR, caller may avoid repainting form needlessly.
335
+ # We may give more meaningful error retval in future. TODO
336
+ def set_divider_location rc
337
+ # add a check for out of bounds since no buffering
338
+ v = 2 # earlier 2
339
+ if @orientation == :HORIZONTAL_SPLIT
340
+ if rc < v || rc > @height - v
341
+ Ncurses.beep
342
+ return :ERROR
343
+ end
344
+ else
345
+ if rc < v || rc > @width - v
346
+ Ncurses.beep
347
+ return :ERROR
348
+ end
349
+ end
350
+ # check min_h
351
+ $log.debug " XXXX setting div location to #{rc} "
352
+ @repaint_required = true
353
+ old_divider_location = @divider_location || 0
354
+ # we first check against min_sizes
355
+ # the calculation is repeated here, and in the actual change
356
+ # so if modifying, be sure to do in both places.
357
+ if !@is_expanding # if expanding then i can't check against min_width
358
+ if rc > old_divider_location
359
+ if @second_component != nil
360
+ if @orientation == :VERTICAL_SPLIT
361
+ # check second comps width
362
+ if @width - (rc + @col_offset + @divider_offset+1) < @second_component.min_width
363
+ $log.debug " #{@name} SORRY 2c min width prevents further resizing: #{@width} #{rc}"
364
+ Ncurses.beep
365
+ return :ERROR
366
+ end
367
+ else
368
+ # check second comps ht
369
+ $log.debug " YYYY SORRY 2c H:#{@height} rc: #{rc} 2cmh: #{@second_component.name} "
370
+ if @height - rc -2 < @second_component.min_height
371
+ Ncurses.beep
372
+ $log.debug " #{@name} SORRY 2c min height prevents further resizing"
373
+ return :ERROR
374
+ end
375
+ end
376
+ end
377
+ elsif rc < old_divider_location
378
+ if @first_component != nil
379
+ $log.debug " #{@name} fc min width #{rc}, #{@first_component.min_width} "
380
+ if @orientation == :VERTICAL_SPLIT
381
+ # check first comps width
382
+
383
+ if rc-1 < @first_component.min_width
384
+ Ncurses.beep
385
+ $log.debug " SORRY fc min width prevents further resizing"
386
+ return :ERROR
387
+ end
388
+ else
389
+ if rc-1 < @first_component.min_height
390
+ $log.debug " SORRY fc min height prevents further resizing"
391
+ Ncurses.beep
392
+ return :ERROR
393
+ end
394
+ end
395
+ end
396
+ end
397
+ end # expanding
398
+ @divider_location = rc
399
+ end
400
+ def OLDset_divider_location rc
401
+ $log.debug " SPLP #{@name} setting divider to #{rc} "
402
+ # add a check for out of bounds since no buffering
403
+ v = 1 # earlier 2
404
+ if @orientation == :HORIZONTAL_SPLIT
405
+ if rc < v || rc > @height - v
406
+ return :ERROR
407
+ end
408
+ else
409
+ if rc < v || rc > @width - v
410
+ return :ERROR
411
+ end
412
+ end
413
+ @repaint_required = true
414
+ old_divider_location = @divider_location || 0
415
+ # we first check against min_sizes
416
+ # the calculation is repeated here, and in the actual change
417
+ # so if modifying, be sure to do in both places.
418
+ if !@is_expanding # if expanding then i can't check against min_width
419
+ if rc > old_divider_location
420
+ if @second_component != nil
421
+ if @orientation == :VERTICAL_SPLIT
422
+ # check second comps width
423
+ if @width - (rc + @col_offset + @divider_offset+1) < @second_component.min_width
424
+ $log.debug " #{@name} SORRY 2c min width prevents further resizing: #{@width} #{rc}"
425
+ return :ERROR
426
+ end
427
+ else
428
+ # check second comps ht
429
+ $log.debug " YYYY SORRY 2c H:#{@height} rc: #{rc} 2cmh: #{@second_component.name} "
430
+ if @height - rc -2 < @second_component.min_height
431
+ $log.debug " #{@name} SORRY 2c min height prevents further resizing"
432
+ return :ERROR
433
+ end
434
+ end
435
+ end
436
+ elsif rc < old_divider_location
437
+ if @first_component != nil
438
+ $log.debug " #{@name} fc min width #{rc}, #{@first_component.min_width} "
439
+ if @orientation == :VERTICAL_SPLIT
440
+ # check first comps width
441
+
442
+ if rc-1 < @first_component.min_width
443
+ $log.debug " SORRY fc min width prevents further resizing"
444
+ return :ERROR
445
+ end
446
+ else
447
+ if rc-1 < @first_component.min_height
448
+ $log.debug " SORRY fc min height prevents further resizing"
449
+ return :ERROR
450
+ end
451
+ end
452
+ end
453
+ end
454
+ end # expanding
455
+ @is_expanding = false
456
+ @old_divider_location = @divider_location
457
+ @divider_location = rc
458
+ if @first_component != nil
459
+
460
+ ## added in case not set. it will be set to a sensible default
461
+ @first_component.height ||= 0
462
+ @first_component.width ||= 0
463
+
464
+ $log.debug " #{@name} set div location, setting first comp width #{rc}"
465
+ if !@cascade_changes.nil?
466
+ if @orientation == :VERTICAL_SPLIT
467
+ $log.warn " SPLP height nil in #{@name} #{@first_component.name} " unless @height
468
+ @height ||= 23
469
+ @first_component.width(rc-0) #+ @col_offset + @divider_offset
470
+ @first_component.height(@height-0) #2+ @col_offset + @divider_offset
471
+ else
472
+ $log.warn " SPLP width nil in #{@name} #{@first_component.name} " unless @width
473
+ @first_component.height(rc+0) #-1) #1+ @col_offset + @divider_offset
474
+ @first_component.width(@width-0) #2+ @col_offset + @divider_offset
475
+ end
476
+ else
477
+ if @orientation == :VERTICAL_SPLIT
478
+ $log.debug " DOES IT COME HERE compare fc wt #{@first_component.width} to match #{rc}-1 "
479
+ # added 2010-01-09 19:00 increase fc to avoid copywin crashing process
480
+ if @first_component.width < rc -0 then
481
+ $log.debug " INCRease fc wt #{@first_component.width} to match #{rc}-1 "
482
+ @first_component.width(rc-0) #+ @col_offset + @divider_offset
483
+ @first_component.repaint_all(true) if !@first_component.nil?
484
+ @repaint_required = true
485
+ end
486
+ ## added this condition 2010-01-11 21:44 again switching needs this
487
+ a = 0 #2
488
+ if @first_component.height < @height - a then
489
+ $log.debug " INCRease fc ht #{@first_component.height} to match #{@height}- #{a} "
490
+ @first_component.height(@height-a) #+ @col_offset + @divider_offset
491
+ end
492
+ else
493
+ # added 2010-01-09 19:00 increase fc to avoid copywin crashing process
494
+ a = 0 #1
495
+ if @first_component.height < rc -a then
496
+ $log.debug " INCRease fc ht #{@first_component.height} to match #{rc}-1 "
497
+ @first_component.height(rc-a) #+ @col_offset + @divider_offset
498
+ @first_component.repaint_all(true) if !@first_component.nil?
499
+ @repaint_required = true
500
+ end
501
+ # added 2010-01-11 19:24 to match c2. Sometimes switching from V to H means
502
+ # fc's width needs to be expanded.
503
+ if @first_component.width < @width - 1 #+ @col_offset + @divider_offset
504
+ $log.debug " INCRease fc wi #{@first_component.width} to match #{@width}-2 "
505
+ @first_component.width = @width - 1 #+ @col_offset + @divider_offset
506
+ @first_component.repaint_all(true)
507
+ @repaint_required = true
508
+ end
509
+ end
510
+ end
511
+ $log.debug " #{@name} TA set C1 H W RC #{@first_component.height} #{@first_component.width} #{rc} "
512
+ @first_component.set_buffering(:bottom => @first_component.height-1, :right => @first_component.width-1, :form => @form )
513
+ end
514
+ if !@second_component.nil?
515
+
516
+ ## added 2010-01-11 23:09 since some cases don't set, like splits within split.
517
+ @second_component.height ||= 0
518
+ @second_component.width ||= 0
519
+
520
+ if @orientation == :VERTICAL_SPLIT
521
+ #@second_component.col = rc + @col_offset + @divider_offset
522
+ #@second_component.row = 0 # 1
523
+ @second_component.col = @col + rc #+ @col_offset + @divider_offset
524
+ @second_component.row = @row # 1
525
+ if !@cascade_changes.nil?
526
+ #@second_component.width = @width - (rc + @col_offset + @divider_offset + 1)
527
+ #@second_component.height = @height-2 #+ @row_offset + @divider_offset
528
+ @second_component.width = @width - rc #+ @col_offset + @divider_offset + 1)
529
+ @second_component.height = @height #+ @row_offset + @divider_offset
530
+ else
531
+ # added 2010-01-09 22:49 to be tested XXX
532
+ # In a vertical split, if widgets w and thus buffer w is less than
533
+ #+ pane, a copywin can crash process, so we must expand component, and thus buffer
534
+ $log.debug " #{@name} 2c width does it come here? #{@second_component.name} #{@second_component.width} < #{@width} -( #{rc}+#{@col_offset}+#{@divider_offset} +1 "
535
+ if @second_component.width < @width - rc #+ @col_offset + @divider_offset + 1)
536
+ $log.debug " YES 2c width "
537
+ @second_component.width = @width - rc #+ @col_offset + @divider_offset + 1)
538
+ @second_component.repaint_all(true)
539
+ @repaint_required = true
540
+ end
541
+ # adding 2010-01-17 19:33 since when changing to VERT, it was not expanding
542
+ if @second_component.height < @height-0 #+ @row_offset + @divider_offset
543
+ $log.debug " JUST ADDED 2010-01-17 19:35 HOPE DOES NOT BREAK ANYTHING "
544
+ @second_component.height = @height-0 #+ @row_offset + @divider_offset
545
+ end
546
+ end
547
+ else
548
+ #rc += @row
549
+ ## HORIZ SPLIT
550
+ offrow = offcol = 0
551
+ #@second_component.row = offrow + rc + 0 #1 #@row_offset + @divider_offset
552
+ #@second_component.col = 0 + offcol # was 1
553
+ offrow = @row; offcol = @col
554
+ @second_component.row = offrow + rc + 0 #1 #@row_offset + @divider_offset
555
+ $log.debug "C2 Horiz row #{@second_component.row} = #{offrow} + #{rc} "
556
+ @second_component.col = 0 + offcol # was 1
557
+ if !@cascade_changes.nil?
558
+ #@second_component.width = @width - 2 #+ @col_offset + @divider_offset
559
+ #@second_component.height = @height - rc -2 #+ @row_offset + @divider_offset
560
+ @second_component.width = @width - 0 #+ @col_offset + @divider_offset
561
+ @second_component.height = @height - rc -0 #+ @row_offset + @divider_offset
562
+ else
563
+ # added 2010-01-16 19:14 -rc since its a HORIZ split
564
+ # 2010-01-16 20:45 made 2 to 3 for scrollpanes within splits!!! hope it doesnt
565
+ # break, and why 3.
566
+ # 2010-01-17 13:33 reverted to 2. 3 was required since i was not returning when error in set_screen_max.
567
+ if @second_component.height < @height-rc-1 #2 #+ @row_offset + @divider_offset
568
+ $log.debug " #{@name} INCRease 2c #{@second_component.name} ht #{@second_component.height} to match #{@height}-2- #{rc} "
569
+ @second_component.height = @height-rc-1 #2 #+ @row_offset + @divider_offset
570
+ @second_component.repaint_all(true)
571
+ @repaint_required = true
572
+ end
573
+ # # added 2010-01-10 15:36 still not expanding
574
+ if @second_component.width < @width - 2 #+ @col_offset + @divider_offset
575
+ $log.debug " #{@name} INCRease 2c #{@second_component.name} wi #{@second_component.width} to match #{@width}-2 "
576
+ @second_component.width = @width - 2 #+ @col_offset + @divider_offset
577
+ @second_component.repaint_all(true)
578
+ @repaint_required = true
579
+ end
580
+ end
581
+ end
582
+ raise "2nd components height or preferred height is required (#{@second_component.name})" unless @second_component.height
583
+ raise "2nd components width or preferred width is required(#{@second_component.name})" unless @second_component.width
584
+ # i need to keep top and left sync for print_border which uses it UGH !!!
585
+ if !@second_component.get_buffer().nil?
586
+ # now that TV and others are creating a buffer in repaint we need another way to set
587
+ #$log.debug " setting second comp row col offset - i think it doesn't come here till much later "
588
+ #XXX @second_component.get_buffer().set_screen_row_col(@second_component.row+@ext_row_offset+@row, @second_component.col+@ext_col_offset+@col)
589
+ # 2010-02-13 09:15 RFED16
590
+ @second_component.get_buffer().set_screen_row_col(@second_component.row, @second_component.col)
591
+ end
592
+ #@second_component.set_buffering(:screen_top => @row, :screen_left => @col)
593
+ #@second_component.set_buffering(:screen_top => @row+@second_component.row, :screen_left => @col+@second_component.col)
594
+ #@second_component.set_buffering(:screen_top => @row+@second_component.row, :screen_left => @col+@second_component.col)
595
+ $log.debug "sdl: #{@name} setting C2 screen_top n left to #{@second_component.row}, #{@second_component.col} "
596
+ @second_component.set_buffering(:screen_top => @second_component.row, :screen_left => @second_component.col)
597
+ @second_component.set_buffering(:bottom => @second_component.height-1, :right => @second_component.width-1, :form => @form )
598
+ #@second_component.ext_row_offset = @row + @ext_row_offset
599
+ #@second_component.ext_col_offset = @col + @ext_col_offset
600
+ $log.debug " #{@name} 2 set div location, rc #{rc} width #{@width} height #{@height}"
601
+ $log.debug " 2 set div location, setting r #{@second_component.row}, #{@ext_row_offset}, #{@row} "
602
+ $log.debug " 2 set div location, setting c #{@second_component.col}, #{@ext_col_offset}, #{@col} "
603
+ $log.debug " C2 set div location, setting w #{@second_component.width} "
604
+ $log.debug " C2 set div location, setting h #{@second_component.height} "
605
+
606
+ end
607
+ fire_property_change("divider_location", old_divider_location, @divider_location)
608
+
609
+ end
610
+
611
+ # calculate divider location based on weight
612
+ # Weight implies weight of first component, e.g. .70 for 70% of splitpane
613
+ # @param wt [float, :read] weight of first component
614
+ def set_resize_weight wt
615
+ raise ArgumentError if wt < 0 or wt >1
616
+ @repaint_required = true
617
+ oldvalue = @resize_weight
618
+ @resize_weight = wt
619
+ if @orientation == :VERTICAL_SPLIT
620
+ rc = (@width||@preferred_width) * wt
621
+ else
622
+ rc = (@height||@preferred_height) * wt
623
+ end
624
+ fire_property_change("resize_weight", oldvalue, @resize_weight)
625
+ rc = rc.ceil
626
+ set_divider_location rc
627
+ end
628
+ ##
629
+ # resets divider location based on preferred size of first component
630
+ # @return :ERROR if min sizes failed
631
+ # You may want to check for ERROR and if so, resize_weight to 0.50
632
+ def reset_to_preferred_sizes
633
+ raise "not using now please remove or redo"
634
+ return if @first_component.nil?
635
+ @repaint_required = true
636
+ ph, pw = @first_component.get_preferred_size
637
+ if @orientation == :VERTICAL_SPLIT
638
+ pw ||= (@width * @divider_at-1).to_i # added 2010-01-16 12:31 so easier to use, 1 to 2 2010-01-16 22:13
639
+ rc = pw+1 ## added 1 2010-01-11 23:26 else divider overlaps comp
640
+ @first_component.width ||= pw ## added 2010-01-11 23:19
641
+ else
642
+ ph ||= (@height * @divider_at - 0).to_i # 1 # added 2010-01-16 12:31 so easier to use
643
+ rc = ph+0 #1 ## added 1 2010-01-11 23:26 else divider overlaps comp
644
+ @first_component.height ||= ph ## added 2010-01-11 23:19
645
+ end
646
+ set_divider_location rc
647
+ end
648
+ # is vertical
649
+ def v?
650
+ @orientation == :VERTICAL_SPLIT
651
+ end
652
+ def h?
653
+ !v?
654
+ end
655
+ def update_first_component
656
+ $log.debug " #{@name} update+first dl: #{@divider_location} "
657
+ raise "XXX 540 SPLP" if @divider_location == 0
658
+ @first_component.row(@row)
659
+ @first_component.col(@col)
660
+ $log.debug "UCF #{@name} #{@first_component.row} #{@first_component.col} "
661
+ comp = @first_component
662
+ if v?
663
+ comp.width(@divider_location)
664
+ comp.height(@height)
665
+ else
666
+ comp.height(@divider_location)
667
+ comp.width(@width)
668
+ end
669
+ comp.set_buffering(:target_window => @target_window || @form.window, :bottom => comp.height-1, :right => comp.width-1, :form => @form )
670
+ @first_component.set_buffering(:screen_top => @first_component.row, :screen_left => @first_component.col)
671
+ end
672
+ def update_second_component
673
+ $log.debug " #{@name} update+secoond dl: #{@divider_location} "
674
+ comp = @second_component
675
+ return if @divider_location == 0
676
+ if @orientation == :HORIZONTAL_SPLIT
677
+ @second_component.row(@row+@divider_location)
678
+ @second_component.col(@col)
679
+ else
680
+ @second_component.row(@row)
681
+ @second_component.col(@col+@divider_location)
682
+ end
683
+ if v?
684
+ $log.debug " width of parent #{@name} is #{@width} , w - dl "
685
+ comp.width(@width - @divider_location)
686
+ comp.height(@height)
687
+ else
688
+ $log.debug " height of parent is #{height} , w - dl "
689
+ comp.height(@height - @divider_location)
690
+ comp.width(@width)
691
+ end
692
+ $log.debug "UCS #{@name} #{@second_component.row} #{@second_component.col}, hw #{comp.height} #{comp.width} "
693
+ comp.set_buffering(:target_window => @target_window || @form.window, :bottom => comp.height-1,
694
+ :right => comp.width-1, :form => @form )
695
+ @second_component.set_buffering(:screen_top => @second_component.row, :screen_left => @second_component.col)
696
+ end
697
+ def repaint # splitpane
698
+ if @graphic.nil?
699
+ @graphic = @target_window || @form.window
700
+ raise "graphic nil in rsplitpane #{@name} " unless @graphic
701
+ end
702
+ #XXX safe_create_buffer
703
+ # this is in case, not called by form
704
+ # we need to clip components
705
+ # note that splitpanes can be nested
706
+
707
+ if @repaint_required
708
+ # Note: this only if major change
709
+ #XXX @graphic.wclear
710
+ @first_component.repaint_all(true) if !@first_component.nil?
711
+ @second_component.repaint_all(true) if !@second_component.nil?
712
+ end
713
+ if @repaint_required
714
+ ## paint border and divider
715
+ $log.debug "SPLP #{@name} repaint split H #{@height} W #{@width} dl #{@divider_location} "
716
+ if v?
717
+ if @divider_location >= @width
718
+ @divider_location = (@width*@divider_at).to_i
719
+ $log.debug " SPLP correcting div loc to #{@divider_location} "
720
+ end
721
+ end
722
+ bordercolor = @border_color || $datacolor
723
+ borderatt = @border_attrib || Ncurses::A_NORMAL
724
+ absrow = @row
725
+ abscol = @col
726
+ $log.debug " #{@graphic} calling print_border #{@row} #{@col} "
727
+ @graphic.print_border(@row, @col, @height-1, @width-1, bordercolor, borderatt)
728
+ rc = @divider_location
729
+
730
+ @graphic.attron(Ncurses.COLOR_PAIR(bordercolor) | borderatt)
731
+ # 2010-02-14 18:23 - non buffered, have to make relative coords into absolute
732
+ #+ by adding row and col
733
+ if @orientation == :VERTICAL_SPLIT
734
+ $log.debug "SPLP #{@name} prtingign split vline divider 1, rc: #{rc}, h:#{@height} - 2 "
735
+ @graphic.mvvline(absrow+1, rc+abscol, 0, @height-2)
736
+ else
737
+ $log.debug "SPLP #{@name} prtingign split hline divider rc: #{rc} , 1 , w:#{@width} - 2"
738
+ @graphic.mvhline(rc+absrow, abscol+1, 0, @width-2)
739
+ end
740
+ @graphic.attroff(Ncurses.COLOR_PAIR(bordercolor) | borderatt)
741
+ end
742
+ if @first_component != nil
743
+ $log.debug " SPLP #{@name} repaint 1c ..."
744
+ # this means that some components will create a buffer with default top and left of 0 the
745
+ # first time. Is there no way we can tell FC what top and left to use.
746
+ update_first_component
747
+ @first_component.repaint
748
+ # earlier before repaint but bombs since some chaps create buffer in repaint
749
+ #XXX @first_component.get_buffer().set_screen_row_col(1, 1) # check this out XXX
750
+ ## the next block is critical for when we switch from one orientation to the other
751
+ ##+ We want first component to expand as much as possible
752
+ if @orientation == :VERTICAL_SPLIT
753
+ #XXX @first_component.get_buffer().set_screen_max_row_col(@height-2, @divider_location-1)
754
+ else
755
+ #XXX @first_component.get_buffer().set_screen_max_row_col(@divider_location-1, @width-2)
756
+ end
757
+ #XXX ret = @first_component.buffer_to_screen(@graphic)
758
+ #XXX $log.debug " SPLP repaint #{@name} fc ret = #{ret} "
759
+ end
760
+ if @second_component != nil
761
+ $log.debug " SPLP repaint #{@name} 2c ... dl: #{@divider_location} "
762
+ # this is required since c2 gets its row and col only after divider has been set
763
+ update_second_component
764
+ @second_component.repaint unless @divider_location == 0
765
+
766
+ # we need to keep top and left of buffer synced with components row and col.
767
+ # Since buffer has no link to comp therefore it can't check back.
768
+ #XXX @second_component.get_buffer().set_screen_row_col(@second_component.row, @second_component.col)
769
+ if @orientation == :VERTICAL_SPLIT
770
+ #XXX @second_component.get_buffer().set_screen_max_row_col(@height-2, @width-2)
771
+ else
772
+ #XXX @second_component.get_buffer().set_screen_max_row_col(@height-2, @width-2)
773
+ end
774
+
775
+ #XXX ret = @second_component.buffer_to_screen(@graphic)
776
+ #XXX $log.debug " SPLP repaint #{@name} 2c ret = #{ret} "
777
+ end
778
+ #XXX @buffer_modified = true
779
+ @graphic.wrefresh # 2010-02-14 20:18 SUBWIN ONLY ??? what is this doing here ? XXX
780
+ paint
781
+ # TODO
782
+ end
783
+ def getvalue
784
+ # TODO
785
+ end
786
+ # we forgot to call the on_enter and on_leave
787
+ # this switches between components. Now we tab out after last.
788
+ def goto_next_component
789
+ if @current_component != nil
790
+ if @current_component == @first_component
791
+ @current_component.on_leave
792
+ if @second_component
793
+ @current_component = @second_component
794
+ @current_component.on_enter
795
+ else
796
+ return :UNHANDLED
797
+ end
798
+ else
799
+ #@current_component = @first_component
800
+ @current_component.on_leave
801
+ return :UNHANDLED # try to get him out.
802
+ end
803
+ set_form_row
804
+ else
805
+ # this happens in one_tab_expand
806
+ @current_component = @second_component if @first_component.nil?
807
+ @current_component = @first_component if @second_component.nil?
808
+ set_form_row
809
+ end
810
+ 0
811
+ end
812
+ def goto_prev_component
813
+ if @current_component != nil
814
+ if @current_component == @second_component
815
+ @current_component.on_leave
816
+ if @first_component
817
+ @current_component = @first_component
818
+ @current_component.on_enter
819
+ else
820
+ return :UNHANDLED
821
+ end
822
+ else
823
+ #@current_component = @first_component
824
+ @current_component.on_leave
825
+ return :UNHANDLED # try to get him out.
826
+ end
827
+ set_form_row
828
+ else
829
+ # this happens in one_tab_expand
830
+ @current_component = @second_component if @first_component.nil?
831
+ @current_component = @first_component if @second_component.nil?
832
+ set_form_row
833
+ end
834
+ 0
835
+ end
836
+ ## Handles key for splitpanes
837
+ ## By default, first component gets focus, not the SPL itself.
838
+ ##+ Mostly passing to child, and handling child's left-overs.
839
+ ## NOTE: How do we switch to the other outer SPL?
840
+ def handle_key ch
841
+ _multiplier = ($multiplier == 0 ? 1 : $multiplier )
842
+ @current_component ||= @first_component
843
+ ## 2010-01-15 12:57 this helps me switch between highest level
844
+ ## However, i should do as follows:
845
+ ## If tab on second component, return UNHA so form can take to next field
846
+ ## If B_tab on second comp, switch to first
847
+ ## If B_tab on first comp, return UNHA so form can take to prev field
848
+ if ch == 9
849
+ #return goto_next_component
850
+ #return 0
851
+ end
852
+
853
+ if @current_component != nil
854
+ # give the child the key to handle, this is the last current child
855
+ ret = @current_component.handle_key ch
856
+ return ret if ret != :UNHANDLED
857
+ else
858
+ ## added 2010-01-07 18:59 in case nothing in there.
859
+ $log.debug " SPLP #{@name} - no component installed in splitpane"
860
+ #return :UNHANDLED
861
+ end
862
+ $log.debug " splitpane #{@name} gets KEY #{ch}"
863
+ case ch
864
+ when KEY_TAB
865
+ return goto_next_component
866
+ when KEY_BTAB
867
+ return goto_prev_component
868
+ #return 0
869
+ when ?\M-w.getbyte(0)
870
+ # switch panes
871
+ if @current_component != nil
872
+ if @current_component == @first_component
873
+ @current_component = @second_component
874
+ else
875
+ @current_component = @first_component
876
+ end
877
+ set_form_row
878
+ else
879
+ return goto_next_component
880
+ #return 0
881
+ # if i've expanded bottom pane, tabbed to opposite higher level, tabbing back
882
+ # brings me to null first pane and i can't go to second, so switch
883
+ # this was added for a non-realistic test program with embedded splitpanes
884
+ #+ but no component inside them. At least one can go from one outer to another.
885
+ #+ In real life, this should not come.
886
+
887
+ return :UNHANDLED
888
+ end
889
+ when ?\M-V.getbyte(0)
890
+ self.orientation(:VERTICAL_SPLIT)
891
+ @repaint_required = true
892
+ when ?\M-H.getbyte(0)
893
+ self.orientation(:HORIZONTAL_SPLIT)
894
+ @repaint_required = true
895
+ when ?\M--.getbyte(0)
896
+ self.set_divider_location(self.divider_location-_multiplier)
897
+ when ?\M-\+.getbyte(0)
898
+ self.set_divider_location(self.divider_location+_multiplier)
899
+ when ?\M-\=.getbyte(0)
900
+ self.set_resize_weight(0.50)
901
+ #when ?\C-u.getbyte(0)
902
+ ## multiplier. Series is 4 16 64
903
+ #@multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
904
+ #return 0
905
+ when ?\C-c.getbyte(0)
906
+ $multiplier = 0
907
+ return 0
908
+ else
909
+ # check for bindings, these cannot override above keys since placed at end
910
+ ret = process_key ch, self
911
+ return :UNHANDLED if ret == :UNHANDLED
912
+ end
913
+ $multiplier = 0
914
+ return 0
915
+ end
916
+ def paint
917
+ @repaint_required = false
918
+ end
919
+ # on entering this component
920
+ # place user on first child
921
+ # TODO if he backtabs in then place on last
922
+ def on_enter
923
+ # 2010-09-14 00:58 forcing first always
924
+ if $current_key == KEY_BTAB
925
+ @current_component = @second_component
926
+ else
927
+ @current_component = @first_component
928
+ end
929
+ @current_component.on_enter if @current_component
930
+
931
+ set_form_row
932
+ end
933
+ # used to set form to whatever was current last
934
+ # now we set to first so user can cycle through. User does not see it as a split
935
+ # within split, just as panes.
936
+ def set_form_row
937
+ if !@current_component.nil?
938
+ $log.debug " #{@name} set_form_row calling sfr for #{@current_component.name} "
939
+ @current_component.set_form_row
940
+ @current_component.set_form_col
941
+ end
942
+ end
943
+ # added 2010-02-09 10:10
944
+ # sets the forms cursor column correctly
945
+ # earlier the super was being called which missed out on child's column.
946
+ # Note: splitpane does not use the cursor, so it does not know where cursor should be displayed,
947
+ #+ the child has to decide where it should be displayed.
948
+ def set_form_col
949
+ if !@current_component.nil?
950
+ $log.debug " #{@name} set_form_col calling sfc for #{@current_component.name} "
951
+ @current_component.set_form_col
952
+ end
953
+ end
954
+ private
955
+ #def _other_component
956
+ #if @current_component == @first_component
957
+ #return @second_component
958
+ #end
959
+ #return @first_component
960
+ #end
961
+ ## expand a split to maximum. This is the one_touch_expandable feature
962
+ # Currently mapped to C-w 1 (mnemonic for one touch), or C-w o (vim's only)
963
+ # To revert, you have to unexpand
964
+ # Note: basically, i nil the component that we don't want to see
965
+ def expand
966
+ @is_expanding = true # this is required so i don't check for min_width later
967
+ $log.debug " callign expand "
968
+ if @current_component == @first_component
969
+ @saved_component = @second_component
970
+ @second_component = nil
971
+ if @orientation == :VERTICAL_SPLIT
972
+ set_divider_location @width - 1
973
+ else
974
+ set_divider_location @height - 1
975
+ end
976
+ $log.debug " callign expand 2 nil #{@divider_location}, h:#{@height} w: #{@width} "
977
+ else
978
+ @saved_component = @first_component
979
+ @first_component = nil
980
+ set_divider_location 1
981
+ $log.debug " callign expand 1 nil #{@divider_location}, h:#{@height} w: #{@width} "
982
+ end
983
+ @repaint_required = true
984
+ end
985
+ # after expanding one split, revert to original - actually i reset, rather than revert
986
+ # This only works after expand has been done
987
+ def unexpand
988
+ $log.debug " inside unexpand "
989
+ return unless @saved_component
990
+ if @first_component.nil?
991
+ @first_component = @saved_component
992
+ else
993
+ @second_component = @saved_component
994
+ end
995
+ @saved_component = nil
996
+ @repaint_required = true
997
+ reset_to_preferred_sizes
998
+ end
999
+
1000
+ # exchange 2 splits, bound to C-w x
1001
+ def exchange
1002
+ tmp = @first_component
1003
+ @first_component = @second_component
1004
+ @second_component = tmp
1005
+ @repaint_required = true
1006
+ reset_to_preferred_sizes
1007
+ end
1008
+ end # class SplitPane
1009
+ end # module