rbcurse 0.1.3 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/CHANGELOG +126 -0
  2. data/Manifest.txt +53 -20
  3. data/README.markdown +423 -0
  4. data/Rakefile +3 -1
  5. data/examples/keytest.rb +177 -0
  6. data/examples/mpad2.rb +156 -0
  7. data/examples/newtesttabp.rb +121 -0
  8. data/examples/rfe.rb +48 -10
  9. data/examples/rfe_renderer.rb +4 -4
  10. data/examples/rvimsplit.rb +376 -0
  11. data/examples/sqlc.rb +97 -106
  12. data/examples/sqlm.rb +446 -0
  13. data/examples/test1.rb +4 -4
  14. data/examples/test2.rb +12 -12
  15. data/examples/testchars.rb +140 -0
  16. data/examples/testkeypress.rb +9 -4
  17. data/examples/testmulticomp.rb +72 -0
  18. data/examples/testscroller.rb +136 -0
  19. data/examples/testscrolllb.rb +86 -0
  20. data/examples/testscrollp.rb +87 -0
  21. data/examples/testscrollta.rb +80 -0
  22. data/examples/testscrolltable.rb +166 -0
  23. data/examples/testsplit.rb +87 -0
  24. data/examples/testsplit2.rb +123 -0
  25. data/examples/testsplit3.rb +215 -0
  26. data/examples/testsplit3_1.rb +244 -0
  27. data/examples/testsplit3a.rb +215 -0
  28. data/examples/testsplit3b.rb +237 -0
  29. data/examples/testsplitta.rb +148 -0
  30. data/examples/testsplittv.rb +142 -0
  31. data/examples/testsplittvv.rb +144 -0
  32. data/examples/testtable.rb +1 -1
  33. data/examples/testtabp.rb +3 -2
  34. data/examples/testtestw.rb +69 -0
  35. data/examples/testtodo.rb +5 -3
  36. data/examples/testtpane.rb +203 -0
  37. data/examples/testtpane2.rb +145 -0
  38. data/examples/testtpanetable.rb +199 -0
  39. data/examples/viewtodo.rb +5 -3
  40. data/lib/rbcurse.rb +1 -1
  41. data/lib/rbcurse/celleditor.rb +2 -2
  42. data/lib/rbcurse/colormap.rb +5 -5
  43. data/lib/rbcurse/defaultlistselectionmodel.rb +3 -3
  44. data/lib/rbcurse/io.rb +663 -0
  45. data/lib/rbcurse/listeditable.rb +306 -0
  46. data/lib/rbcurse/listkeys.rb +15 -15
  47. data/lib/rbcurse/listscrollable.rb +168 -27
  48. data/lib/rbcurse/mapper.rb +35 -13
  49. data/lib/rbcurse/rchangeevent.rb +28 -0
  50. data/lib/rbcurse/rform.rb +845 -0
  51. data/lib/rbcurse/rlistbox.rb +144 -34
  52. data/lib/rbcurse/rmessagebox.rb +10 -5
  53. data/lib/rbcurse/rmulticontainer.rb +325 -0
  54. data/lib/rbcurse/rmultitextview.rb +306 -0
  55. data/lib/rbcurse/rscrollform.rb +369 -0
  56. data/lib/rbcurse/rscrollpane.rb +511 -0
  57. data/lib/rbcurse/rsplitpane.rb +820 -0
  58. data/lib/rbcurse/rtabbedpane.rb +737 -109
  59. data/lib/rbcurse/rtabbedwindow.rb +326 -0
  60. data/lib/rbcurse/rtable.rb +220 -64
  61. data/lib/rbcurse/rtextarea.rb +340 -181
  62. data/lib/rbcurse/rtextview.rb +237 -101
  63. data/lib/rbcurse/rviewport.rb +203 -0
  64. data/lib/rbcurse/rwidget.rb +919 -95
  65. data/lib/rbcurse/scrollable.rb +7 -7
  66. data/lib/rbcurse/selectable.rb +4 -4
  67. data/lib/rbcurse/table/tablecellrenderer.rb +3 -0
  68. data/lib/rbcurse/undomanager.rb +181 -0
  69. data/lib/rbcurse/vieditable.rb +100 -0
  70. data/lib/ver/window.rb +471 -21
  71. metadata +66 -22
  72. data/README.txt +0 -312
  73. data/examples/testd.db +0 -0
  74. data/examples/todocsv.csv +0 -28
@@ -0,0 +1,326 @@
1
+ =begin
2
+ * Name: tabbed pane: can have multiple forms overlapping.
3
+ * Description: This is the old program that uses multiple windows.
4
+ * This cannot be embedded inside a form, but can be used as a popup.
5
+ * Avoid using this, move to the widget TabbedPane which can be embedded inside a form.
6
+ * Author: rkumar
7
+
8
+
9
+ *** rtabbedpane renamed to rtabbedwindow 2009-11-02 13:04
10
+
11
+ --------
12
+ * Date: 2008-12-13 13:06
13
+ * License:
14
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
15
+
16
+ =end
17
+ require 'rubygems'
18
+ require 'ncurses'
19
+ require 'logger'
20
+ require 'rbcurse'
21
+
22
+ include Ncurses
23
+ include RubyCurses
24
+ module RubyCurses
25
+ extend self
26
+
27
+ # TODO : insert_tab, remove_tab, disable/hide tab
28
+ # Hotkeys should be defined with ampersand, too.
29
+ #
30
+ # Multiple independent overlapping forms using the tabbed metaphor.
31
+ class TabbedButton < RubyCurses::RadioButton
32
+ def getvalue_for_paint
33
+ @text
34
+ end
35
+ ##
36
+ # highlight abd selected colors and attribs should perhaps be in a
37
+ # structure, so user can override easily
38
+ def repaint # tabbedbutton
39
+ # $log.debug("BUTTon repaint : #{self.class()} r:#{@row} c:#{@col} #{getvalue_for_paint}" )
40
+ r,c = rowcol
41
+ attribs = @attrs
42
+ @highlight_foreground ||= $reversecolor
43
+ @highlight_background ||= 0
44
+ _state = @state
45
+ _state = :SELECTED if @variable.value == @value
46
+ case _state
47
+ when :HIGHLIGHTED
48
+ bgcolor = @highlight_background
49
+ color = @highlight_foreground
50
+ bgcolor = @bgcolor
51
+ color = @color
52
+ attribs = Ncurses::A_BOLD
53
+ when :SELECTED
54
+ bgcolor = @bgcolor
55
+ color = @color
56
+ attribs = Ncurses::A_REVERSE
57
+ else
58
+ bgcolor = @bgcolor
59
+ color = @color
60
+ end
61
+ #bgcolor = @state==:HIGHLIGHTED ? @highlight_background : @bgcolor
62
+ #color = @state==:HIGHLIGHTED ? @highlight_foreground : @color
63
+ if bgcolor.is_a? String and color.is_a? String
64
+ color = ColorMap.get_color(color, bgcolor)
65
+ end
66
+ value = getvalue_for_paint
67
+ # $log.debug("button repaint : r:#{r} c:#{c} col:#{color} bg #{bgcolor} v: #{value} ")
68
+ len = @display_length || value.length
69
+ @form.window.printstring r, c, "%-*s" % [len, value], color, attribs
70
+ # @form.window.mvchgat(y=r, x=c, max=len, Ncurses::A_NORMAL, bgcolor, nil)
71
+ if @underline != nil
72
+ # changed +1 to +0 on 2008-12-15 21:23 pls check.
73
+ @form.window.mvchgat(y=r, x=c+@underline+0, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, color, nil)
74
+ end
75
+ end
76
+ end
77
+ class TabbedWindow
78
+ include DSL
79
+ include EventHandler
80
+ dsl_accessor :row, :col
81
+ dsl_accessor :height, :width
82
+ dsl_accessor :button_type # ok, ok_cancel, yes_no
83
+ dsl_accessor :buttons # used if type :custom
84
+ attr_reader :selected_index
85
+ def initialize win, aconfig={}, &block
86
+ @parent = win
87
+ @tabs ||= []
88
+ @forms ||= []
89
+ @bgcolor ||= "black" # 0
90
+ @color ||= "white" # $datacolor
91
+ @attr = nil
92
+ @current_form = nil
93
+ @current_tab = nil
94
+ @config = aconfig
95
+ @config.each_pair { |k,v| variable_set(k,v) }
96
+ instance_eval &block if block_given?
97
+ end
98
+ ##
99
+ # when adding tabs, you may use ampersand in text to create hotkey
100
+ def add_tab text, aconfig={}, &block
101
+ #create a button here and block is taken care of in button's instance
102
+ #or push this for later creation.
103
+ @tabs << Tab.new(text, aconfig, &block)
104
+ tab = @tabs.last
105
+ @forms << create_tab_form(tab)
106
+ tab.form = @forms.last
107
+ return tab
108
+ end
109
+ # private
110
+ def variable_set var, val
111
+ var = "@#{var}"
112
+ instance_variable_set(var, val)
113
+ end
114
+ # private
115
+ def configure(*val , &block)
116
+ case val.size
117
+ when 1
118
+ return @config[val[0]]
119
+ when 2
120
+ @config[val[0]] = val[1]
121
+ variable_set(val[0], val[1])
122
+ end
123
+ instance_eval &block if block_given?
124
+ end
125
+ def repaint
126
+ @window || create_window
127
+ @window.show
128
+ end
129
+ def show
130
+ repaint
131
+ end
132
+ def create_window
133
+ # first create the main top window with the tab buttons on it.
134
+ @layout = { :height => @height, :width => @width, :top => @row, :left => @col }
135
+ @window = VER::Window.new(@layout)
136
+ @form = RubyCurses::Form.new @window
137
+ @form.navigation_policy = :NON_CYCLICAL
138
+ @current_form = @form
139
+ @window.bkgd(Ncurses.COLOR_PAIR($datacolor));
140
+ @window.box( 0, 0);
141
+ @window.wrefresh
142
+ Ncurses::Panel.update_panels
143
+ col = 1
144
+ @buttons = []
145
+ ## create a button for each tab
146
+ $tabradio = Variable.new
147
+ @tabs.each do |tab|
148
+ text = tab.text
149
+ @buttons << RubyCurses::TabbedButton.new(@form) do
150
+ variable $tabradio
151
+ text text
152
+ name text
153
+ value text
154
+ row 1
155
+ col col
156
+ end
157
+ col += text.length+4
158
+ # @forms << create_tab_form(tab)
159
+ # form = @forms.last
160
+ form = tab.form
161
+ form.window = @window if form.window.nil? ## XXX
162
+ panel = form.window.panel
163
+ @buttons.last.command { Ncurses::Panel.top_panel(panel)
164
+ Ncurses::Panel.update_panels();
165
+ Ncurses.doupdate();
166
+ form.repaint
167
+ @current_form = form
168
+ @current_tab = form
169
+ }
170
+
171
+ end
172
+ create_buttons
173
+ @form.repaint
174
+ end
175
+ def display_form form
176
+ panel = form.window.panel
177
+ Ncurses::Panel.top_panel(panel)
178
+ Ncurses::Panel.update_panels();
179
+ Ncurses.doupdate();
180
+ form.repaint
181
+ end
182
+ def create_tab_form tab
183
+ layout = { :height => @height-2, :width => @width, :top => @row+2, :left => @col }
184
+ window = VER::Window.new(layout)
185
+ form = RubyCurses::Form.new window
186
+ form.navigation_policy = :NON_CYCLICAL
187
+ window.bkgd(Ncurses.COLOR_PAIR($datacolor));
188
+ window.box( 0, 0);
189
+ window.mvprintw(1,1, tab.text.tr('&', ''))
190
+ ##window.wrefresh
191
+ ##Ncurses::Panel.update_panels
192
+ return form
193
+ end
194
+ def handle_keys
195
+ begin
196
+ while (( ch=@window.getchar()) != 999)
197
+ if ch == ?\C-q.getbyte(0)
198
+ @selected_index = -1 # this signifies cancel by ?C-q
199
+ @stop = true
200
+ return
201
+ end
202
+ return if @stop
203
+ @current_form ||= @form
204
+ ret = @current_form.handle_key(ch)
205
+ case ret
206
+ when :NO_NEXT_FIELD
207
+ if @current_form != @form
208
+ @current_form = @form
209
+ #@current_form.select_field -1
210
+ @current_form.req_first_field
211
+ #ret = @current_form.handle_key(ch)
212
+ else
213
+ if !@current_tab.nil?
214
+ @current_form = @current_tab
215
+ display_form @current_form
216
+ @current_form.req_first_field
217
+ #@current_form.select_field -1
218
+ #ret = @current_form.handle_key(ch)
219
+ end
220
+ end
221
+ when :NO_PREV_FIELD
222
+ if @current_form != @form
223
+ $log.debug " 1 no prev field - going to button "
224
+ @current_form = @form
225
+ @current_form.req_last_field
226
+ else
227
+ if !@current_tab.nil?
228
+ @current_form = @current_tab
229
+ display_form @current_form
230
+ @current_form.req_last_field
231
+ end
232
+ end
233
+ when :UNHANDLED
234
+ $log.debug " unhandled in tabbed pane #{ch}"
235
+ ret = @form.process_key ch, self # field
236
+ @form.repaint
237
+ #return :UNHANDLED if ret == :UNHANDLED
238
+ end
239
+ return if @stop
240
+ @current_form.window.wrefresh
241
+ @window.refresh
242
+ end
243
+ ensure
244
+ destroy
245
+ end
246
+ end
247
+ def destroy
248
+ @window.destroy
249
+ @forms.each { |f| w = f.window; w.destroy unless w.nil? }
250
+ end
251
+ def create_buttons
252
+ case @button_type.to_s.downcase
253
+ when "ok"
254
+ make_buttons ["&OK"]
255
+ when "ok_cancel" #, "input", "list", "field_list"
256
+ make_buttons %w[&OK &Cancel]
257
+ when "yes_no"
258
+ make_buttons %w[&Yes &No]
259
+ when "yes_no_cancel"
260
+ make_buttons ["&Yes", "&No", "&Cancel"]
261
+ when "custom"
262
+ raise "Blank list of buttons passed to custom" if @buttons.nil? or @buttons.size == 0
263
+ make_buttons @buttons
264
+ else
265
+ $log.debug "No buttontype passed for creating tabbedpane. Using default (OK)"
266
+ make_buttons ["&OK"]
267
+ end
268
+ end
269
+ def make_buttons names
270
+ total = names.inject(0) {|total, item| total + item.length + 4}
271
+ bcol = center_column total
272
+
273
+ brow = @layout[:height]-2
274
+ button_ct=0
275
+ names.each_with_index do |bname, ix|
276
+ text = bname
277
+ #underline = @underlines[ix] if !@underlines.nil?
278
+
279
+ button = Button.new @form do
280
+ text text
281
+ name bname
282
+ row brow
283
+ col bcol
284
+ #underline underline
285
+ highlight_background $reversecolor
286
+ color $datacolor
287
+ bgcolor $datacolor
288
+ end
289
+ index = button_ct
290
+ button.command { |form| @selected_index = index; @stop = true; $log.debug "Pressed Button #{bname}";}
291
+ button_ct += 1
292
+ bcol += text.length+6
293
+ end
294
+ end
295
+ def center_column textlen
296
+ width = @layout[:width]
297
+ return (width-textlen)/2
298
+ end
299
+
300
+ ##
301
+ # nested class tab
302
+ class Tab
303
+ attr_reader :text
304
+ attr_reader :config
305
+ attr_accessor :form
306
+ def initialize text, aconfig={}, &block
307
+ @text = text
308
+ @config = aconfig
309
+ @config.each_pair { |k,v| variable_set(k,v) }
310
+ instance_eval &block if block_given?
311
+ end
312
+ # private
313
+ def variable_set var, val
314
+ var = "@#{var}"
315
+ instance_variable_set(var, val)
316
+ end
317
+ def repaint
318
+
319
+
320
+ end
321
+ end
322
+
323
+ end # class TabbedWindow
324
+
325
+
326
+ end # module
@@ -1,12 +1,23 @@
1
1
  =begin
2
2
  * Name: table widget
3
3
  * Description:
4
- * Author: rkumar (arunachalesha)
4
+ * Author: rkumar
5
5
 
6
6
 
7
7
  TODO: NOTE:
8
8
  A few higher level methods check for no data but lower level ones do not.
9
+ XXX FIXME if M-tab to exit table then editing_stopped should be called.
10
+ currenty valus is lost if exiting table using Mtab or M-S-tab 2009-10-06 15:10
11
+ FIXME if a field is not printed since it is going out, tab still goes there, and celleditor
12
+ still prints there. - DONE
13
+
14
+ FIXME Increasing a column shoud decrease others till min size but not push off.
15
+ Should we have a method for changing column width online that recomputes others?
16
+ See testtable.rb - TODO a bit later
17
+ FIXME - tabbing in a row, should auto scroll to columns not displayed ?
18
+ currently it moves to next row. (examples/sqlc.rb) - DONE
9
19
 
20
+ * 2010-01-18 19:54 - BUFFERING related changes.
10
21
  --------
11
22
  * Date: 2008-12-27 21:33
12
23
  * License:
@@ -45,7 +56,6 @@ module RubyCurses
45
56
  include RubyCurses::ListSelectable
46
57
  include RubyCurses::ListKeys
47
58
 
48
- dsl_accessor :height
49
59
  dsl_accessor :title
50
60
  dsl_accessor :title_attrib
51
61
  dsl_accessor :selected_color, :selected_bgcolor, :selected_attr
@@ -61,11 +71,12 @@ module RubyCurses
61
71
  # In addition, A column to be editable must either have editable as nil or true
62
72
  dsl_accessor :cell_editing_allowed # 2009-01-16 22:55
63
73
 
64
- def initialize form, config={}, &block
74
+ def initialize form = nil, config={}, &block
65
75
  super
66
76
  init_vars
67
77
  install_list_keys
68
78
  install_keys_bindings
79
+ ## create_buffer needs to move to repaint. widget needs values to use when i creates buffer in repaint.
69
80
  end
70
81
 
71
82
  def init_vars
@@ -121,7 +132,8 @@ module RubyCurses
121
132
  end
122
133
  # added 2009-01-07 13:05 so new scrollable can use
123
134
  def scrollatrow
124
- @height -3
135
+ #@height -3
136
+ @height -4 # we forgot to remove 1 from height in border.
125
137
  end
126
138
 
127
139
  #
@@ -151,17 +163,17 @@ module RubyCurses
151
163
  create_table_header
152
164
  end
153
165
  def set_model tm, tcm=nil, lsm=nil
154
- table_model tm
155
- if tcm.nil?
156
- create_default_table_column_model
157
- else
158
- table_column_model tcm
159
- end
160
- if lsm.nil?
161
- create_default_list_selection_model
162
- else
163
- list_selection_model lsm
164
- end
166
+ table_model tm
167
+ if tcm.nil?
168
+ create_default_table_column_model
169
+ else
170
+ table_column_model tcm
171
+ end
172
+ if lsm.nil?
173
+ create_default_list_selection_model
174
+ else
175
+ list_selection_model lsm
176
+ end
165
177
  create_table_header
166
178
  end
167
179
 
@@ -428,6 +440,12 @@ module RubyCurses
428
440
  end
429
441
  @cell_editor = editor
430
442
  @repaint_required = true
443
+ # copied from rlistbox, so that editors write on parent's graphic, otherwise
444
+ # their screen updates get overwritten by parent. 2010-01-19 20:17
445
+ if @should_create_buffer
446
+ $log.debug "LB #{@name} overriding editors comp with GRAPHIC #{@graphic} "
447
+ editor.component.override_graphic(@graphic) # 2010-01-05 00:36 TRYING OUT BUFFERED
448
+ end
431
449
  set_form_col
432
450
  end
433
451
  ## Its too late to call components on_leave here
@@ -449,15 +467,15 @@ module RubyCurses
449
467
  case cname
450
468
  when 'String'
451
469
  # I do not know cell width here, you will have toset display_length NOTE
452
- ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 8}
470
+ ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 8, :name => "tb_field_str"}
453
471
  @ceh['String'] = ce
454
472
  return ce
455
473
  when 'Fixnum'
456
- ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 5}
474
+ ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 5, :name => "tb_field_num"}
457
475
  @ceh[cname] = ce
458
476
  return ce
459
477
  when 'Float'
460
- ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 5}
478
+ ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 5, :name => "tb_field_flt"}
461
479
  @ceh[cname] = ce
462
480
  return ce
463
481
  when "Boolean" #'TrueClass', 'FalseClass'
@@ -466,7 +484,7 @@ module RubyCurses
466
484
  return ce
467
485
  else
468
486
  $log.debug " get_default_cell_editor_for_class UNKNOWN #{cname}"
469
- ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 6}
487
+ ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 6, :name => "tb_field_unk"}
470
488
  @ceh[cname] = ce
471
489
  return ce
472
490
  end
@@ -493,6 +511,7 @@ module RubyCurses
493
511
  ret = @cell_editor.component.handle_key(ch)
494
512
  @repaint_required = true
495
513
  $log.debug "RET #{ret} got from to cell editor"
514
+ #set_form_col if ret != :UNHANDLED # added 2010-01-30 20:17 CURSOR POS TABBEDPANE
496
515
  return if ret != :UNHANDLED
497
516
  end
498
517
  case ch
@@ -502,21 +521,21 @@ module RubyCurses
502
521
  when KEY_DOWN # show previous value
503
522
  editing_stopped if @is_editing # 2009-01-16 16:06
504
523
  next_row
505
- when 27, ?\C-c:
524
+ when 27, ?\C-c
506
525
  editing_canceled
507
- when KEY_ENTER, 10, 13:
526
+ when KEY_ENTER, 10, 13
508
527
  # actually it should fall through to the else
509
528
  return :UNHANDLED unless @cell_editing_allowed
510
529
  toggle_cell_editing
511
530
 
512
- when @KEY_ROW_SELECTOR # ?\C-x #32:
531
+ when @KEY_ROW_SELECTOR # ?\C-x #32
513
532
  #add_row_selection_interval @current_index, @current_index
514
533
  toggle_row_selection @current_index #, @current_index
515
534
  @repaint_required = true
516
- when ?\C-n:
535
+ when ?\C-n.getbyte(0)
517
536
  editing_stopped if @is_editing # 2009-01-16 16:06
518
537
  scroll_forward
519
- when ?\C-p:
538
+ when ?\C-p.getbyte(0)
520
539
  editing_stopped if @is_editing # 2009-01-16 16:06
521
540
  scroll_backward
522
541
  when 48, @KEY_GOTO_TOP
@@ -537,6 +556,7 @@ module RubyCurses
537
556
  ret = process_key ch, self
538
557
  return :UNHANDLED if ret == :UNHANDLED
539
558
  end
559
+ return 0 # added 2010-03-14 13:27
540
560
  end
541
561
  def editing_canceled
542
562
  return unless @cell_editing_allowed
@@ -601,37 +621,63 @@ module RubyCurses
601
621
  bounds_check
602
622
  end
603
623
  end
624
+ # move focus to next column
625
+ # 2009-10-07 12:47 behavior change. earlier this would move to next row
626
+ # if focus was on last visible field. Now it scrolls so that first invisible
627
+ # field becomes the first column.
604
628
  def next_column
605
629
  v = @current_column+1
606
- if v < @table_column_model.column_count and v <= @_last_column_print
607
- $log.debug " if v < #{@table_column_model.column_count} "
608
- current_column v
630
+ # normal situation, there is a next column go to
631
+ if v < @table_column_model.column_count
632
+ if v <= @_last_column_print
633
+ $log.debug " if v < #{@table_column_model.column_count} nd lastcolprint "
634
+ current_column v
635
+ else
636
+ # there is a col but its not visible
637
+ # XXX inefficient but i scroll completely to next column (putting it at start)
638
+ # otherwise sometimes it was still not visible if last column
639
+ (v-@_first_column_print).times(){scroll_right}
640
+ current_column v
641
+ set_form_col
642
+ end
643
+
609
644
  else
610
645
  if @current_index < row_count()-1
611
646
  $log.debug " GOING TO NEXT ROW FROM NEXT COL : #{@current_index} : #{row_count}"
612
647
  @current_column = 0
613
- @current_column = @_first_column_print # added 2009-02-17 00:01
648
+ #@current_column = @_first_column_print # added 2009-02-17 00:01
649
+ @_first_column_print = 0 # added 2009-10-07 11:25
614
650
  next_row
615
651
  set_form_col
652
+ @repaint_required = true
653
+ @table_changed = true # so columns are modified by print_header
616
654
  else
617
655
  return :UNHANDLED
618
656
  end
619
657
  end
620
658
  end
659
+ # move focus to previous column
660
+ # if you are on first column, check if scrolling required, else move up to
661
+ # last *visible* column of prev row
621
662
  def previous_column
622
663
  v = @current_column-1
623
664
  # returning unhandled so focus can go to prev field auto
624
665
  if v < @_first_column_print and @current_index <= 0
625
666
  return :UNHANDLED
626
667
  end
627
- if v < @_first_column_print and @current_index > 0
628
- @current_column = @table_column_model.column_count-1
629
- @current_column = @_last_column_print # added 2009-02-17 00:01
630
- $log.debug " XXXXXX prev col #{@current_column}, las #{@_last_column_print}, fi: #{@_first_column_print}"
631
- set_form_col
632
- previous_row
668
+ if v < @_first_column_print
669
+ if v > 0
670
+ scroll_left
671
+ current_column v
672
+ elsif @current_index > 0
673
+ @current_column = @table_column_model.column_count-1
674
+ @current_column = @_last_column_print # added 2009-02-17 00:01
675
+ $log.debug " XXXXXX prev col #{@current_column}, las #{@_last_column_print}, fi: #{@_first_column_print}"
676
+ set_form_col
677
+ previous_row
678
+ end
633
679
  else
634
- current_column @current_column-1
680
+ current_column v
635
681
  end
636
682
  end
637
683
  def goto_bottom
@@ -745,14 +791,24 @@ module RubyCurses
745
791
  end
746
792
  def set_form_row
747
793
  r,c = rowcol
794
+ @rows_panned ||= 0 # RFED16 2010-02-19 10:00
795
+ win_row = 0
796
+ #win_row=@form.window.top # 2010-01-18 20:28 added
748
797
  # +1 is due to header
749
- @form.row = r + (@current_index-@toprow) + 1
798
+ #@form.row = r + (@current_index-@toprow) + 1
799
+ frow = r + (@current_index-@toprow) + 1 + win_row + @rows_panned
800
+ setrowcol(frow, nil) # 2010-01-18 20:04
750
801
  end
751
802
  # set cursor on correct column, widget
752
803
  def set_form_col col=@curpos
753
804
  @curpos = col
805
+ @cols_panned ||= 0 # RFED16 2010-02-19 10:00
754
806
  @current_column_offset = get_column_offset
755
- @form.col = @col + @col_offset + @curpos + @current_column_offset
807
+ #@form.col = @col + @col_offset + @curpos + @current_column_offset
808
+ #win_col=@form.window.left
809
+ win_col = 0 # RFED16 2010-02-19 10:00
810
+ fcol = @col + @col_offset + @curpos + @current_column_offset + @cols_panned + win_col
811
+ setrowcol(nil, fcol) # 2010-01-18 20:04
756
812
  end
757
813
  # protected
758
814
  def get_column_offset columnid=@current_column
@@ -762,8 +818,17 @@ module RubyCurses
762
818
 
763
819
 
764
820
  def repaint
821
+ safe_create_buffer # moved here 2010-02-19 09:53 RFED16
765
822
  return unless @repaint_required
766
- print_border @form.window if @to_print_borders == 1 # do this once only, unless everything changes
823
+ my_win = @form ? @form.window : @target_window
824
+ @graphic = my_win unless @graphic
825
+ #$log.warn "neither form not target window given!!! TV paint 368" unless my_win
826
+ raise " #{@name} neither form, nor target window given TV paint " unless my_win
827
+ raise " #{@name} NO GRAPHIC set as yet TV paint " unless @graphic
828
+ @win_left = my_win.left # unused remove TODO
829
+ @win_top = my_win.top
830
+
831
+ print_border @graphic if @to_print_borders == 1 # do this once only, unless everything changes
767
832
  return if @table_model.nil? # added 2009-02-17 12:45
768
833
  @_first_column_print ||= 0
769
834
  cc = @table_model.column_count
@@ -797,45 +862,50 @@ module RubyCurses
797
862
  #acolumn = tcm.column(colix)
798
863
  #model_index = acolumn.model_index
799
864
  content = get_value_at(crow, colix) # tables
800
- #renderer = get_default_cell_renderer_for_class content.class.to_s
801
865
  renderer = get_cell_renderer(crow, colix)
802
866
  if renderer.nil?
803
867
  renderer = get_default_cell_renderer_for_class(content.class.to_s) if renderer.nil?
804
868
  renderer.display_length acolumn.width unless acolumn.nil?
805
869
  end
806
870
  width = renderer.display_length + @inter_column_spacing
807
- #renderer.repaint @form.window, r+hh, c+(colix*11), content, focussed, selected
808
871
  acolumn.column_offset = offset
809
872
  # trying to ensure that no overprinting
810
- # $log.debug " c+offset+width > @col+@width #{c+offset+width} > #{@col}+#{@width}"
811
- # $log.debug " #{c}+#{offset}+#{width} > @col+@width #{c+offset+width} > #{@col}+#{@width}"
812
873
  if c+offset+width > @col+@width
813
874
  _column_scrolling = true
814
875
  @_last_column_print = colix
815
- #$log.debug " TABLE BREAKING SINCE "
816
- #$log.debug " if c+offset+width > @col+@width #{c+offset+width} > #{@col}+#{@width}"
817
- #$log.debug " if #{c}+#{offset}+#{width} > @col+@width #{c+offset+width} > #{@col}+#{@width}"
818
876
  # experimental to print subset of last
819
877
  space_left = (@width-3)-(offset) # 3 due to boundaries
820
878
  space_left = 0 if space_left < 0
821
- if content.length > space_left
879
+ # length bombed for trueclass 2009-10-05 19:34
880
+ contentlen = content.length rescue content.to_s.length
881
+ #if content.length > space_left
882
+ if contentlen > space_left
822
883
  clen = space_left
823
884
  renderer.display_length clen
824
885
  else
825
886
  clen = -1
826
887
  renderer.display_length space_left # content.length
827
888
  end
889
+ # added 2009-10-05 20:29 since non strings were bombing
890
+ # in other cases should be just pass the content as-is. XXX
891
+ contenttrim = content[0..clen] rescue content # .to_s[0..clen]
828
892
  # print the inter cell padding just in case things mess up while scrolling
829
- @form.window.mvprintw r+hh, c+offset-@inter_column_spacing, inter_column_padding
830
- renderer.repaint @form.window, r+hh, c+offset, crow, content[0..clen], focussed, selected
893
+ @graphic.mvprintw r+hh, c+offset-@inter_column_spacing, inter_column_padding
894
+ #renderer.repaint @graphic, r+hh, c+offset, crow, content[0..clen], focussed, selected
895
+ #renderer.repaint @graphic, r+hh, c+offset, crow, contenttrim, focussed, selected
896
+ # 2009-10-05 20:35 XXX passing self so we check it doesn't print outside
897
+ renderer.repaint self, r+hh, c+offset, crow, contenttrim, focussed, selected
831
898
  break
832
899
  end
833
900
  # added crow on 2009-02-11 22:46
834
- renderer.repaint @form.window, r+hh, c+(offset), crow, content, focussed, selected
901
+ #renderer.repaint @graphic, r+hh, c+(offset), crow, content, focussed, selected
902
+ # 2009-10-05 20:35 XXX
903
+ renderer.repaint self, r+hh, c+(offset), crow, content, focussed, selected
835
904
  offset += width
836
905
  end
837
906
  else
838
- @form.window.printstring r+hh, c, " " * (@width-2), acolor,@attr
907
+ #@graphic.printstring r+hh, c, " " * (@width-2), acolor,@attr
908
+ printstring r+hh, c, " " * (@width-2), acolor,@attr
839
909
  # clear rows
840
910
  end
841
911
  end
@@ -847,10 +917,30 @@ module RubyCurses
847
917
  $log.debug " _print_more_data_marker(#{rc} >= #{tr} + #{h})"
848
918
  @table_changed = false
849
919
  @repaint_required = false
920
+ @buffer_modified = true
921
+ buffer_to_window # RFED16 2010-02-19 09:55
922
+ end
923
+ # NEW to correct overflow
924
+ # 2009-10-05 21:34
925
+ # when resizing columns a renderer can go outside the table bounds
926
+ # so printing should be done by parent not window
927
+ def printstring(r,c,string, color, att)
928
+ # 3 is table borders
929
+ # if renderer trying to print outside don't let it
930
+ if c > @col+@width-3
931
+ return
932
+ end
933
+ # if date exceeds boundary truncate
934
+ if c+string.length > (@col+@width)-3
935
+ len = string.length-((c+string.length)-(@col+@width-3))
936
+ @graphic.printstring(r,c,string[0..len], color,att)
937
+ else
938
+ @graphic.printstring(r,c,string, color,att)
939
+ end
850
940
  end
851
941
  def print_border g
852
942
  return unless @table_changed
853
- g.print_border @row, @col, @height, @width, $datacolor
943
+ g.print_border @row, @col, @height-1, @width, $datacolor
854
944
  return if @table_model.nil?
855
945
  rc = @table_model.row_count
856
946
  h = scrollatrow()
@@ -859,19 +949,21 @@ module RubyCurses
859
949
  # private
860
950
  def _print_more_data_marker tf
861
951
  marker = tf ? Ncurses::ACS_CKBOARD : Ncurses::ACS_VLINE
862
- @form.window.mvwaddch @row+@height-1, @col+@width-1, marker
952
+ @graphic.mvwaddch @row+@height-2, @col+@width-1, marker
863
953
  marker = @toprow > 0 ? Ncurses::ACS_CKBOARD : Ncurses::ACS_VLINE
864
- @form.window.mvwaddch @row+1, @col+@width-1, marker
954
+ @graphic.mvwaddch @row+1, @col+@width-1, marker
865
955
  end
866
956
  def _print_more_columns_marker tf
867
957
  marker = tf ? Ncurses::ACS_CKBOARD : Ncurses::ACS_HLINE
868
- @form.window.mvwaddch @row+@height, @col+@width-2, marker
958
+ @graphic.mvwaddch @row+@height-1, @col+@width-2, marker
869
959
  # show if columns to left or not
870
960
  marker = @_first_column_print > 0 ? Ncurses::ACS_CKBOARD : Ncurses::ACS_HLINE
871
- @form.window.mvwaddch @row+@height, @col+@_first_column_print+1, marker
961
+ @graphic.mvwaddch @row+@height-1, @col+@_first_column_print+1, marker
872
962
  end
873
963
  def print_header
874
964
  return unless @table_changed
965
+ $log.debug " TABLE: inside printheader 2009-10-07 11:51 DDD "
966
+
875
967
  r,c = rowcol
876
968
  header_model = @table_header.table_column_model
877
969
  tcm = @table_column_model ## could have been overridden, should we use this at all
@@ -897,10 +989,14 @@ module RubyCurses
897
989
  renderer.display_length space_left
898
990
  end
899
991
  #$log.debug " TABLE BREAKING SINCE sl: #{space_left},#{crow},#{colix}: #{clen} "
900
- renderer.repaint @form.window, r, c+(offset), 0, content[0..clen], false, false
992
+ # passing self so can prevent renderer from printing outside 2009-10-05 22:56
993
+ #renderer.repaint @graphic, r, c+(offset), 0, content[0..clen], false, false
994
+ renderer.repaint self, r, c+(offset), 0, content[0..clen], false, false
901
995
  break
902
996
  end
903
- renderer.repaint @form.window, r, c+(offset),0, content, false, false
997
+ # passing self so can prevent renderer from printing outside 2009-10-05 22:56
998
+ #renderer.repaint @graphic, r, c+(offset),0, content, false, false
999
+ renderer.repaint self, r, c+(offset),0, content, false, false
904
1000
  offset += width
905
1001
  end
906
1002
  end
@@ -953,6 +1049,7 @@ module RubyCurses
953
1049
  cc = @table_model.column_count
954
1050
  if @_first_column_print < cc-1
955
1051
  @_first_column_print += 1
1052
+ @_last_column_print += 1 if @_last_column_print < cc-1
956
1053
  @current_column = @_first_column_print
957
1054
  set_form_col # FIXME not looking too good till key press
958
1055
  @repaint_required = true
@@ -1039,6 +1136,35 @@ module RubyCurses
1039
1136
  end
1040
1137
  table_structure_changed(nil)
1041
1138
  end
1139
+ def size_columns_to_fit
1140
+ delta = @width - table_column_model().get_total_column_width()
1141
+ tcw = table_column_model().get_total_column_width()
1142
+
1143
+ $log.debug "size_columns_to_fit D #{delta}, W #{@width}, TCW #{tcw}"
1144
+ accomodate_delta(delta) if delta != 0
1145
+ #set_width_from_preferred_widths
1146
+ end
1147
+ private
1148
+ def accomodate_delta delta
1149
+ tcm = @table_column_model
1150
+ cc = tcm.column_count
1151
+ average = (delta/cc).ceil
1152
+ total = 0
1153
+ tcm.each do |col|
1154
+ oldcw = col.width + average
1155
+ next if oldcw < col.min_width or oldcw > col.max_width
1156
+ if delta >0
1157
+ break if total > delta
1158
+ else
1159
+ break if total < delta
1160
+ end
1161
+ col.width oldcw
1162
+ total += average
1163
+ end
1164
+ $log.debug "accomodate_delta: #{average}. #{total}"
1165
+ table_structure_changed(nil)
1166
+ end
1167
+
1042
1168
  # ADD METHODS HERE
1043
1169
  end # class Table
1044
1170
 
@@ -1047,6 +1173,9 @@ module RubyCurses
1047
1173
  # TODO - can't change width beyond min and max if set
1048
1174
  # resizable - user can't resize but programatically can
1049
1175
  # model_index
1176
+ # XXX Seems we are not using min_width and max_width.
1177
+ # min should be used for when resizing,, max should not be used. we are using width which is
1178
+ # updated as changed
1050
1179
  class TableColumn
1051
1180
  include RubyCurses::EventHandler # 2009-01-15 22:49
1052
1181
  attr_reader :identifier
@@ -1056,7 +1185,8 @@ module RubyCurses
1056
1185
  # user may override or set for this column, else headers default will be used
1057
1186
  attr_accessor :header_renderer
1058
1187
  dsl_property :header_value
1059
- dsl_property :width
1188
+ dsl_property :width # XXX don;t let user set width later, should be readonly
1189
+ dsl_property :preferred_width # user should use this when requesting a change
1060
1190
  # some columns may not be editable. e.g in a Finder, file size or time not editable
1061
1191
  # whereas name is.
1062
1192
 
@@ -1069,8 +1199,13 @@ module RubyCurses
1069
1199
  dsl_accessor :edit_length # corresponds to maxlen, if not set, col width will be useda 2009-02-16 21:55
1070
1200
 
1071
1201
 
1202
+ # width is used as initial and preferred width. It has actual value at any time
1203
+ # width must never be directly set, use preferred width later
1072
1204
  def initialize model_index, identifier, header_value, width, config={}, &block
1073
1205
  @width = width
1206
+ @preferred_width = width
1207
+ @min_width = 4
1208
+ @max_width = 1000
1074
1209
  @model_index = model_index
1075
1210
  @identifier = identifier
1076
1211
  @header_value = header_value
@@ -1106,7 +1241,7 @@ module RubyCurses
1106
1241
  nil
1107
1242
  end
1108
1243
  def total_column_width
1109
- 0
1244
+ -1
1110
1245
  end
1111
1246
  def get_selection_model
1112
1247
  nil
@@ -1134,6 +1269,7 @@ module RubyCurses
1134
1269
  # takes a column names array
1135
1270
  def initialize cols=[]
1136
1271
  @columns = []
1272
+ @total_column_width= -1
1137
1273
  ##cols.each_with_index {|c, index| @columns << TableColumn.new(index, c, c, 10) }
1138
1274
  cols.each_with_index {|c, index| add_column(TableColumn.new(index, c, c, 10)) }
1139
1275
  @selected_columns = []
@@ -1162,8 +1298,16 @@ module RubyCurses
1162
1298
  def clear_selection
1163
1299
  @selected_columns = []
1164
1300
  end
1165
- def total_column_width
1166
- 0
1301
+ ##
1302
+ # added 2009-10-07 23:04
1303
+ def get_total_column_width
1304
+ @total_column_width = -1 # XXX
1305
+ if @total_column_width == -1
1306
+ total = 0
1307
+ each { |c| total += c.width ; $log.debug "get_total_column_width: #{c.width}"}
1308
+ @total_column_width = total
1309
+ end
1310
+ return @total_column_width
1167
1311
  end
1168
1312
  def set_selection_model lsm
1169
1313
  @column_selection_model = lsm
@@ -1218,6 +1362,8 @@ module RubyCurses
1218
1362
  end
1219
1363
  def get_value_at row, col
1220
1364
  end
1365
+ def get_total_column_width
1366
+ end
1221
1367
  =begin
1222
1368
  def << obj
1223
1369
  end
@@ -1241,7 +1387,9 @@ module RubyCurses
1241
1387
  @column_identifiers = colnames_array
1242
1388
  end
1243
1389
  def column_count
1244
- @column_identifiers.count
1390
+ # 2010-01-12 19:35 changed count to size since size is supported in 1.8.6 also
1391
+ #@column_identifiers.count
1392
+ @column_identifiers.size
1245
1393
  end
1246
1394
  def row_count
1247
1395
  @data.length
@@ -1412,7 +1560,8 @@ module RubyCurses
1412
1560
  end
1413
1561
  end # class DefaultListSelectionModel
1414
1562
  ##
1415
- #
1563
+ # Class that manages Table's Header
1564
+ # are we not taking events such as column added, removed ?
1416
1565
  class TableHeader
1417
1566
  attr_accessor :default_renderer
1418
1567
  attr_accessor :table_column_model
@@ -1425,7 +1574,14 @@ module RubyCurses
1425
1574
  @default_renderer = TableCellRenderer.new "", {"display_length" => 10, "justify" => :center, "color"=>"white", "bgcolor"=>"blue"}
1426
1575
  end
1427
1576
 
1428
- end
1577
+ # added 2009-10-07 14:03
1578
+ # returns the column being resized
1579
+ # @returns TableColumn
1580
+ # @protected
1581
+ def get_resizing_column
1582
+ end
1583
+
1584
+ end # class TableHeader
1429
1585
  ##
1430
1586
  # When an event is fired by TableModel, contents are changed, then this object will be passed
1431
1587
  # to trigger