rbcurse 0.1.3 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. data/CHANGELOG +126 -0
  2. data/Manifest.txt +53 -20
  3. data/README.markdown +423 -0
  4. data/Rakefile +3 -1
  5. data/examples/keytest.rb +177 -0
  6. data/examples/mpad2.rb +156 -0
  7. data/examples/newtesttabp.rb +121 -0
  8. data/examples/rfe.rb +48 -10
  9. data/examples/rfe_renderer.rb +4 -4
  10. data/examples/rvimsplit.rb +376 -0
  11. data/examples/sqlc.rb +97 -106
  12. data/examples/sqlm.rb +446 -0
  13. data/examples/test1.rb +4 -4
  14. data/examples/test2.rb +12 -12
  15. data/examples/testchars.rb +140 -0
  16. data/examples/testkeypress.rb +9 -4
  17. data/examples/testmulticomp.rb +72 -0
  18. data/examples/testscroller.rb +136 -0
  19. data/examples/testscrolllb.rb +86 -0
  20. data/examples/testscrollp.rb +87 -0
  21. data/examples/testscrollta.rb +80 -0
  22. data/examples/testscrolltable.rb +166 -0
  23. data/examples/testsplit.rb +87 -0
  24. data/examples/testsplit2.rb +123 -0
  25. data/examples/testsplit3.rb +215 -0
  26. data/examples/testsplit3_1.rb +244 -0
  27. data/examples/testsplit3a.rb +215 -0
  28. data/examples/testsplit3b.rb +237 -0
  29. data/examples/testsplitta.rb +148 -0
  30. data/examples/testsplittv.rb +142 -0
  31. data/examples/testsplittvv.rb +144 -0
  32. data/examples/testtable.rb +1 -1
  33. data/examples/testtabp.rb +3 -2
  34. data/examples/testtestw.rb +69 -0
  35. data/examples/testtodo.rb +5 -3
  36. data/examples/testtpane.rb +203 -0
  37. data/examples/testtpane2.rb +145 -0
  38. data/examples/testtpanetable.rb +199 -0
  39. data/examples/viewtodo.rb +5 -3
  40. data/lib/rbcurse.rb +1 -1
  41. data/lib/rbcurse/celleditor.rb +2 -2
  42. data/lib/rbcurse/colormap.rb +5 -5
  43. data/lib/rbcurse/defaultlistselectionmodel.rb +3 -3
  44. data/lib/rbcurse/io.rb +663 -0
  45. data/lib/rbcurse/listeditable.rb +306 -0
  46. data/lib/rbcurse/listkeys.rb +15 -15
  47. data/lib/rbcurse/listscrollable.rb +168 -27
  48. data/lib/rbcurse/mapper.rb +35 -13
  49. data/lib/rbcurse/rchangeevent.rb +28 -0
  50. data/lib/rbcurse/rform.rb +845 -0
  51. data/lib/rbcurse/rlistbox.rb +144 -34
  52. data/lib/rbcurse/rmessagebox.rb +10 -5
  53. data/lib/rbcurse/rmulticontainer.rb +325 -0
  54. data/lib/rbcurse/rmultitextview.rb +306 -0
  55. data/lib/rbcurse/rscrollform.rb +369 -0
  56. data/lib/rbcurse/rscrollpane.rb +511 -0
  57. data/lib/rbcurse/rsplitpane.rb +820 -0
  58. data/lib/rbcurse/rtabbedpane.rb +737 -109
  59. data/lib/rbcurse/rtabbedwindow.rb +326 -0
  60. data/lib/rbcurse/rtable.rb +220 -64
  61. data/lib/rbcurse/rtextarea.rb +340 -181
  62. data/lib/rbcurse/rtextview.rb +237 -101
  63. data/lib/rbcurse/rviewport.rb +203 -0
  64. data/lib/rbcurse/rwidget.rb +919 -95
  65. data/lib/rbcurse/scrollable.rb +7 -7
  66. data/lib/rbcurse/selectable.rb +4 -4
  67. data/lib/rbcurse/table/tablecellrenderer.rb +3 -0
  68. data/lib/rbcurse/undomanager.rb +181 -0
  69. data/lib/rbcurse/vieditable.rb +100 -0
  70. data/lib/ver/window.rb +471 -21
  71. metadata +66 -22
  72. data/README.txt +0 -312
  73. data/examples/testd.db +0 -0
  74. data/examples/todocsv.csv +0 -28
@@ -0,0 +1,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