Class: RubyCurses::Table

Inherits:
Widget show all
Includes:
ListKeys, ListSelectable
Defined in:
lib/rbcurse/rtable.rb

Overview

—— NOTE —————— # Table contains a TableModel Table contains a TableColumnModel (which contains TableColumn instances) TableColumn contains 2 TableCellRenderer: column and header ———————— #

Due to not having method overloading, after usig new, use set_data or set_model

This is a widget that displays tabular data. We will get into editing after this works out. This uses the MVC architecture and is WIP as of 2009-01-04 18:37 TODO cellrenderers should be able to get parents bgcolor and color (Jtables) if none defined for them.

Constant Summary

Constants included from Io

Io::ERROR_COLOR_PAIR, Io::FOOTER_COLOR_PAIR, Io::LINEONE, Io::MAIN_WINDOW_COLOR_PAIR

Instance Attribute Summary collapse

Attributes included from ListSelectable

#column_selection_allowed, #row_selection_allowed

Attributes inherited from Widget

#_object_created, #col_offset, #cols_panned, #config, #curpos, #focussed, #form, #id, #parent_component, #row_offset, #rows_panned, #state

Instance Method Summary collapse

Methods included from ListKeys

#install_list_keys

Methods included from ListSelectable

#add_row_selection_interval, #clear_selection, #create_default_list_selection_model, #do_next_selection, #do_prev_selection, #is_selected?, #list_selection_model, #remove_row_selection_interval, #selected_row, #selected_row_count, #selected_rows, #selected_value, #selected_values, #toggle_row_selection

Methods inherited from Widget

#changed, #click, #destroy, #enter, #event_list, #focus, #get_preferred_size, #getvalue, #getvalue_for_paint, #height, #height=, #hide, #leave, #modified?, #move, #override_graphic, #process_key, #remove, #repaint_all, #repaint_required, #rowcol, #set_buffer_modified, #set_buffering, #set_form, #set_modified, #setformrowcol, #setrowcol, #show, #text_variable, #unbind_key, #width, #width=

Methods included from Io

#askchoice, #askyesno, #askyesnocancel, #clear_error, #clear_this, #get_string, #newaskyesno, #old_print_header, #old_print_top_right, #print_action, #print_error, #print_footer_help, #print_headers, #print_help, #print_help_page, #print_in_middle, #print_key_labels, #print_key_labels_row, #print_screen_labels, #print_status, #print_this, #print_top_right, #rbgetstr, #warn

Methods included from Utils

#_process_key, #bind_key, #clean_string!, #get_color, #keycode_tos, #repeatm, #view, #wrap_text

Methods included from ConfigSetup

#cget, #config_setup, #configure, #variable_set

Methods included from EventHandler

#bind, #fire_handler, #fire_property_change

Constructor Details

#initialize(form = nil, config = {}, &block) ⇒ Table

Returns a new instance of Table.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/rbcurse/rtable.rb', line 77

def initialize form = nil, config={}, &block
  _data = config.delete :data
  _columns = config.delete :columns
  @_column_widths = config.delete :column_widths
  # if user leaves width blank but gives us col widths, that means calculate total width
  if @_column_widths && config[:width].nil?
    total = @_column_widths.inject(0) { |total, w| total+=w }
    @width = total+2
  end
  @suppress_borders = false
  @col_offset = @row_offset = 1

  super
  # added LIST event since bombing when selecting a row in table 2011-09-8 FFI
  @_events.push(*[:TABLE_TRAVERSAL_EVENT,:TABLE_EDITING_EVENT, :LIST_SELECTION_EVENT])
  init_vars
  install_list_keys
  install_keys_bindings
  if _data && _columns
    set_data _data, _columns
  end
end

Instance Attribute Details

#current_indexObject

the row index universally



63
64
65
# File 'lib/rbcurse/rtable.rb', line 63

def current_index
  @current_index
end

#editing_colObject (readonly)

attr_accessor :current_column # index of column (usually in current row ) a changed event of an editor component can utitlize this if it wishes to know the row or col that was exited.



67
68
69
# File 'lib/rbcurse/rtable.rb', line 67

def editing_col
  @editing_col
end

#editing_rowObject (readonly)

attr_accessor :current_column # index of column (usually in current row ) a changed event of an editor component can utitlize this if it wishes to know the row or col that was exited.



67
68
69
# File 'lib/rbcurse/rtable.rb', line 67

def editing_row
  @editing_row
end

#is_editingObject

boolean is only true if cell_editing_allowed



68
69
70
# File 'lib/rbcurse/rtable.rb', line 68

def is_editing
  @is_editing
end

#toprowObject

top visible



1071
1072
1073
# File 'lib/rbcurse/rtable.rb', line 1071

def toprow
  @toprow
end

Instance Method Details

#_print_more_columns_marker(tf) ⇒ Object



1015
1016
1017
1018
1019
1020
1021
# File 'lib/rbcurse/rtable.rb', line 1015

def _print_more_columns_marker tf
  marker = tf ?  Ncurses::ACS_CKBOARD : Ncurses::ACS_HLINE
  @graphic.mvwaddch @row+@height-1, @col+@width-2, marker
  # show if columns to left or not
  marker = @_first_column_print > 0 ?  Ncurses::ACS_CKBOARD : Ncurses::ACS_HLINE
  @graphic.mvwaddch @row+@height-1, @col+@_first_column_print+1, marker
end

#_print_more_data_marker(tf) ⇒ Object

private



1009
1010
1011
1012
1013
1014
# File 'lib/rbcurse/rtable.rb', line 1009

def _print_more_data_marker tf
  marker = tf ?  Ncurses::ACS_CKBOARD : Ncurses::ACS_VLINE
  @graphic.mvwaddch @row+@height-2, @col+@width-1, marker
  marker = @toprow > 0 ?  Ncurses::ACS_CKBOARD : Ncurses::ACS_VLINE
  @graphic.mvwaddch @row+1, @col+@width-1, marker
end

#add_column(tc) ⇒ Object



314
315
316
317
# File 'lib/rbcurse/rtable.rb', line 314

def add_column tc
  @table_column_model << tc
  #table_structure_changed # this should be called by tcm TODO with object
end

#add_column_selection_interval(ix0, ix1) ⇒ Object



273
274
275
276
# File 'lib/rbcurse/rtable.rb', line 273

def add_column_selection_interval ix0, ix1
  raise "TODO "
  # if column_selection_allowed
end

#ask_search_backwardObject



1072
1073
1074
1075
1076
1077
1078
1079
1080
# File 'lib/rbcurse/rtable.rb', line 1072

def ask_search_backward
  regex =  get_string("Enter regex to search (backward)")
  ix = @table_model.find_prev regex, @current_index
  if ix.nil?
    alert("No matching data for: #{regex}")
  else
    set_focus_on(ix)
  end
end

#ask_search_forwardObject



1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
# File 'lib/rbcurse/rtable.rb', line 1090

def ask_search_forward
  regex =  get_string("Enter regex to search (forward)")
  #ix = @table_model.find_next regex, @current_index
  ix = @table_model.find_match regex, @current_index
  if ix.nil?
    alert("No matching data for: #{regex}")
  else
    set_focus_on(ix)
  end
end

#bounds_checkObject



777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
# File 'lib/rbcurse/rtable.rb', line 777

def bounds_check
  h = scrollatrow()
  rc = row_count

  @current_index = 0 if @current_index < 0  # not lt 0
  @current_index = rc-1 if @current_index >= rc # not gt rowcount
  @toprow = rc-h-1 if rc > h and @toprow > rc - h - 1 # toprow shows full page if possible
  # curr has gone below table,  move toprow forward
  if @current_index - @toprow > h
    @toprow = @current_index - h
  elsif @current_index < @toprow
    # curr has gone above table,  move toprow up
    @toprow = @current_index
  end

  if @oldrow != @current_index
    #$log.debug "going to call on leave and on enter"
    on_leave_row @oldrow #if respond_to? :on_leave_row     # to be defined by widget that has included this
    on_enter_row @current_index   #if respond_to? :on_enter_row  # to be defined by widget that has included this
  end
  set_form_row
  @oldrow = @current_index 
  @repaint_required = true
end

#cancel_editorObject

Its too late to call components on_leave here since cursor would have moved elsewhere. Prior to moving out of a field, the on_leave should be called and exceptions caught FIXME



497
498
499
500
501
502
503
# File 'lib/rbcurse/rtable.rb', line 497

def cancel_editor
  # not really required, the refresh was required. Ok, now i call components on_leave inside
  #@cell_editor.cancel_editor
  @editing_row, @editing_col = nil, nil
  @is_editing = false
  @repaint_required = true
end

#column(ix) ⇒ Object

returns col by col ix added on 2009-01-16 23:45



328
329
330
# File 'lib/rbcurse/rtable.rb', line 328

def column ix
  @table_column_model.column(ix)
end

#column_property_changed(evt) ⇒ Object



378
379
380
381
382
# File 'lib/rbcurse/rtable.rb', line 378

def column_property_changed evt
  $log.debug "JT def column_property_changed #{evt} "
  @table_changed = true
  @repaint_required = true
end

#create_default_table_column_modelObject



259
260
261
# File 'lib/rbcurse/rtable.rb', line 259

def create_default_table_column_model
  table_column_model DefaultTableColumnModel.new
end

#create_table_headerObject



262
263
264
# File 'lib/rbcurse/rtable.rb', line 262

def create_table_header
  @table_header = TableHeader.new @table_column_model
end

#current_column(*val) ⇒ Object

getter and setter for current_column index



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/rbcurse/rtable.rb', line 295

def current_column(*val)
  if val.empty?
    @current_column || 0
  else
    @oldcol = @current_column
    v = val[0]
    v = 0 if v < 0
    v = @table_column_model.column_count-1 if v > @table_column_model.column_count-1
    @current_column = v 
    if @current_column != @oldcol
      on_leave_column @oldcol
      on_enter_column @current_column
    end
    set_form_col
    @oldcol = @current_column # added on 2009-01-16 19:40 for next_col
  end
end

#edit_cell_at(row, col) ⇒ Object



434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'lib/rbcurse/rtable.rb', line 434

def edit_cell_at row, col
  acolumn = column(col)
  if acolumn.editable == false or (acolumn.editable.nil? and @cell_editing_allowed!=true)
    $log.debug " editing not allowed in #{col}"
    @is_editing = false
    return nil
  end
  return nil if row >= row_count
  value = get_value_at row, col
  editor = get_cell_editor row, col
  @old_cell_value = value # for event
  if editor.nil?
    
    cls = value.nil? ? get_value_at(0,col).class.to_s : value.class.to_s
    if value.nil?
      case cls
      when 'String'
        value = value.to_s
      when 'Fixnum'
        value = value.to_i
      when 'Float'
        value = value.to_f
      else
        value = value.to_s
      end
    end
    editor = get_default_cell_editor_for_class cls
    #$log.debug "EDIT_CELL_AT:1 #{cls}  #{editor.component.display_length} = #{@table_column_model.column(col).width}i maxlen #{editor.component.maxlen}"
    editor.component.display_length = @table_column_model.column(col).width
    # maxlen won't be nil ! This used to work earlier
    #editor.component.maxlen = editor.component.display_length if editor.component.respond_to? :maxlen and editor.component.maxlen.nil? # 2009-01-18 00:59  XXX don't overwrite if user has set
    if editor.component.respond_to? :maxlen 
      editor.component.maxlen = @table_column_model.column(col).edit_length || editor.component.display_length 
    end
    #$log.debug "EDIT_CELL_AT: #{cls}  #{editor.component.display_length} = #{@table_column_model.column(col).width}i maxlen #{editor.component.maxlen}"
  end
  #$log.debug " got an EDITOR #{editor} ::  #{editor.component} "
  # by now we should have something to edit with. We just need to prepare the widgey.
  prepare_editor editor, row, col, value

end

#editing_canceledObject



609
610
611
612
613
# File 'lib/rbcurse/rtable.rb', line 609

def editing_canceled
  return unless @cell_editing_allowed
  @is_editing = false if @is_editing
  cancel_editor
end

#editing_startedObject



623
624
625
626
627
628
629
630
631
632
633
# File 'lib/rbcurse/rtable.rb', line 623

def editing_started
  return if !@cell_editing_allowed or row_count < 1
  @is_editing = true # 2009-01-16 16:14 
  $log.debug " turning on editing cell at #{focussed_row}, #{focussed_col}"
  # on deleting last row, we need to go back 2009-01-19 18:31 
  if focussed_row >= row_count
    bounds_check
  end
  @editing_row, @editing_col = focussed_row(), focussed_col()
  edit_cell_at focussed_row(), focussed_col()
end

#editing_stopped(row = focussed_row(), col = focussed_col()) ⇒ Object

EDST the defualt values are useful when user is ON the field and pressed ENTER when leaving a cell, this should have oldrow and oldcol, not default values this throws an exception if validation on field fails NOTE



638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
# File 'lib/rbcurse/rtable.rb', line 638

def editing_stopped row=focussed_row(), col=focussed_col()
  return unless @cell_editing_allowed or @is_editing == false or column(col).editable == false
  return if row_count < 1
  $log.debug "editing_stopped set_value_at(#{row}, #{col}: #{@cell_editor.getvalue}"
  # next line should be in on_leave_cell but that's not being called FIXME from everywhere
  @cell_editor.on_leave row,col # added here since this is called whenever a cell is exited

  value = @cell_editor.getvalue
  if value != @old_cell_value
    set_value_at(row, col, @cell_editor.getvalue) #.dup 2009-01-10 21:42 boolean can't duplicate
    if @table_editing_event.nil? 
      @table_editing_event ||= TableEditingEvent.new row, col, self, @old_cell_value, value, :EDITING_STOPPED
    else
      @table_editing_event.set row, col, self, @old_cell_value, value, :EDITING_STOPPED
    end
    fire_handler :TABLE_EDITING_EVENT, @table_editing_event
  end
  cancel_editor
end

#estimate_column_widths(columns, datatypes = nil) ⇒ Object

Makes an estimate of columns sizes, returning a hash, and storing it as @column_widths based on checking first 20 rows of data. This does not try to fit all columns into table, but gives best width, so you can scroll right to see other columns. using the command: @columns, *rows = @db.execute2(command)

Parameters:

  • -

    datatypes is an array returned by following command to DB



1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
# File 'lib/rbcurse/rtable.rb', line 1139

def estimate_column_widths columns, datatypes=nil
  tablewidth = @width-3
  colwidths = {}
  unless datatypes
    datatypes = []
    row = columns[0]
    $log.debug " XXX row: #{row} "

    row.each do |c| 
      $log.debug " XXX c: #{c} "
      case c
      when Fixnum, Integer
        datatypes << "int"
      when Date, Time
        datatypes << "date"
      else
        datatypes << "varchar"
      end
    end
  end
  min_column_width = (tablewidth/columns.length) -1
  $log.debug("min: #{min_column_width}, #{tablewidth}")
  0.upto(20) do |rowix|
    break if rowix >= row_count
  #@content.each_with_index do |row, cix|
  #  break if cix >= 20
    @table_column_model.each_with_index do |acolumn, ix|
      col = get_value_at(rowix, ix)
      colwidths[ix] ||= 0
      colwidths[ix] = [colwidths[ix], col.to_s.length].max
    end
  end
  total = 0
  # crashing in 1.9.2 due to hash key no insert in iteration 2010-08-22 20:09 
  #colwidths.each_pair do |k,v|
  tkeys = colwidths.keys
  tkeys.each do |k|
    name = columns[k.to_i]
    v = colwidths[k]
    colwidths[name] = v
    total += v
  end
  colwidths["__TOTAL__"] = total
  column_widths = colwidths
  @max_data_widths = column_widths.dup

  $log.debug "XXXX datatypes #{datatypes} "
  columns.each_with_index do | col, i|
   break if datatypes[i].nil?
  if datatypes[i].match(/(real|int)/) != nil
    wid = column_widths[i]
    #   cw = [column_widths[i], [8,min_column_width].min].max
    $log.debug("XXX #{wid}. #{columns[i].length}")
    cw = [wid, columns[i].length].max
    $log.debug("int #{col} #{column_widths[i]}, #{cw}")
  elsif datatypes[i].match(/(date)/) != nil
    cw = [column_widths[i], [12,min_column_width].min].max
    #cw = [12,min_column_width].min
    $log.debug("date #{col}  #{column_widths[i]}, #{cw}")
  else
    cw = [column_widths[i], min_column_width].max
    if column_widths[i] <= col.length and col.length <= min_column_width
      cw = col.length
    end
    $log.debug("else #{col} #{column_widths[i]}, #{col.length} #{cw}")
  end
  column_widths[i] = cw
  total += cw
  end
  column_widths["__TOTAL__"] = total
  $log.debug("Estimated col widths: #{column_widths.inspect}")
  @column_widths = column_widths
  return column_widths
end

#find_nextObject

table find_next



1101
1102
1103
1104
1105
1106
1107
1108
1109
# File 'lib/rbcurse/rtable.rb', line 1101

def find_next 
  ix = @table_model.find_next
  regex = @table_model.last_regex 
  if ix.nil?
    alert("No more matching data for: #{regex}")
  else
    set_focus_on(ix)
  end
end

#find_prevObject



1081
1082
1083
1084
1085
1086
1087
1088
1089
# File 'lib/rbcurse/rtable.rb', line 1081

def find_prev 
  ix = @table_model.find_prev
  regex = @table_model.last_regex 
  if ix.nil?
    alert("No previous matching data for: #{regex}")
  else
    set_focus_on(ix)
  end
end

#focussed_colObject



151
152
153
154
155
# File 'lib/rbcurse/rtable.rb', line 151

def focussed_col
  return nil if row_count < 1
  #raise "No data in table" if row_count < 1
  @current_column
end

#focussed_rowObject



145
146
147
148
149
150
# File 'lib/rbcurse/rtable.rb', line 145

def focussed_row
  #raise "No data in table" if row_count < 1
  return nil if row_count < 1
  return @current_index if @current_index < row_count
  @current_index = row_count-1
end

#get_cell_editor(row, col) ⇒ Object

——- editing methods———- #



427
428
429
430
431
432
433
# File 'lib/rbcurse/rtable.rb', line 427

def get_cell_editor row, col
$log.debug " def get_cell_editor #{row}, #{col}"
  column = @table_column_model.column(col)
  return nil if column.editable == false or (column.editable.nil? and @cell_editing_allowed!=true)
  editor = column.cell_editor
  return editor # can be nil
end

#get_cell_renderer(row, col) ⇒ Object

override for cell or row behaviour



419
420
421
422
423
424
# File 'lib/rbcurse/rtable.rb', line 419

def get_cell_renderer row, col
  # get columns renderer else class default
  column = @table_column_model.column(col)
  rend = column.cell_renderer
  return rend # can be nil
end

#get_column(identifier) ⇒ Object

table_structure_changed # this should be called by tcm TODO with object



322
323
324
325
# File 'lib/rbcurse/rtable.rb', line 322

def get_column identifier
  ix = @table_column_model.column_index identifier
  return @table_column_model.column ix
end

#get_column_name(ix) ⇒ Object



331
332
333
# File 'lib/rbcurse/rtable.rb', line 331

def get_column_name ix
  @table_column_model.column(ix).identifier
end

#get_column_offset(columnid = @current_column) ⇒ Object

protected



875
876
877
878
# File 'lib/rbcurse/rtable.rb', line 875

def get_column_offset columnid=@current_column
  return 0 if @table_column_model.nil?
  return @table_column_model.column(columnid).column_offset || 0
end

#get_default_cell_editor_for_class(cname) ⇒ Object



504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
# File 'lib/rbcurse/rtable.rb', line 504

def get_default_cell_editor_for_class cname
  @ceh ||= {}
  cname = 'Boolean' if cname == 'TrueClass' or cname == 'FalseClass'
  if @ceh.include? cname
    return @ceh[cname]
  else
    case cname
    when 'String'
      # I do not know cell width here, you will have toset display_length NOTE
      ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 8, :name => "tb_field_str"}
      @ceh['String'] = ce
      return ce
    when 'Fixnum'
      ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 5, :name => "tb_field_num"}
      @ceh[cname] = ce
      return ce
    when 'Float'
      ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 5, :name => "tb_field_flt"}
      @ceh[cname] = ce
      return ce
    when "Boolean" #'TrueClass', 'FalseClass'
      ce = RubyCurses::CellEditor.new(RubyCurses::CheckBox.new nil, {"display_length"=> 0})
      @ceh[cname] = ce
      return ce
    else
      $log.debug " get_default_cell_editor_for_class UNKNOWN #{cname}"
      ce = RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> 6, :name => "tb_field_unk"}
      @ceh[cname] = ce
      return ce
    end
  end
end

#get_default_cell_renderer_for_class(cname) ⇒ Object

this is vry temporary and will change as we begin to use models - i need to pick columns renderer



410
411
412
413
# File 'lib/rbcurse/rtable.rb', line 410

def get_default_cell_renderer_for_class cname
  @crh || prepare_renderers
  @crh[cname] || @crh['String']
end

#get_table_column_modelObject

@deprecated, avoid usage



254
255
256
257
# File 'lib/rbcurse/rtable.rb', line 254

def get_table_column_model
  $log.warn " DEPRECATED. Pls use table_column_model()"
  @table_column_model 
end

#get_value_at(row, col) ⇒ Object

— row and column methods of Table —# must not give wrong results when columns switched!



341
342
343
344
345
# File 'lib/rbcurse/rtable.rb', line 341

def get_value_at row, col
  return nil if row.nil? || col.nil? # 2011-09-29 
  model_index = @table_column_model.column(col).model_index
  @table_model.get_value_at row, model_index
end

#goto_bottomObject



744
745
746
747
748
749
# File 'lib/rbcurse/rtable.rb', line 744

def goto_bottom
  @oldrow = @current_index
  rc = row_count
  @current_index = rc -1
  bounds_check
end

#goto_topObject



750
751
752
753
754
# File 'lib/rbcurse/rtable.rb', line 750

def goto_top
  @oldrow = @current_index
  @current_index = 0
  bounds_check
end

#handle_key(ch) ⇒ Object

key handling make separate methods so callable programmatically



546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
# File 'lib/rbcurse/rtable.rb', line 546

def handle_key(ch)
  return :UNHANDLED if @table_model.nil?
  @current_index ||= 0
  @toprow ||= 0
  h = scrollatrow()
  rc = @table_model.row_count
  if @is_editing and (ch != 27 and ch != ?\C-c and ch != 13)
    $log.debug " sending ch #{ch} to cell editor"
    ret = @cell_editor.component.handle_key(ch)
    @repaint_required = true
    $log.debug "RET #{ret} got from to cell editor"
    #set_form_col if ret != :UNHANDLED # added 2010-01-30 20:17 CURSOR POS TABBEDPANE
    return if ret != :UNHANDLED
  end
  case ch
  when KEY_UP  # show previous value
    editing_stopped if @is_editing # 2009-01-16 16:06 
    previous_row
  when KEY_DOWN  # show previous value
    editing_stopped if @is_editing # 2009-01-16 16:06 
    next_row
  when 27, ?\C-c
    editing_canceled
  when KEY_ENTER, 10, 13
    # actually it should fall through to the else
    return :UNHANDLED unless @cell_editing_allowed
    toggle_cell_editing

  when @KEY_ROW_SELECTOR # ?\C-x #32
    #add_row_selection_interval @current_index, @current_index
    toggle_row_selection @current_index #, @current_index
    @repaint_required = true
  when ?\C-n.getbyte(0)
    editing_stopped if @is_editing # 2009-01-16 16:06 
    scroll_forward
  when ?\C-p.getbyte(0)
    editing_stopped if @is_editing # 2009-01-16 16:06 
    scroll_backward
  when @KEY_GOTO_TOP # removed 48 (0) from here so we can trap numbers
    # please note that C-[ gives 27, same as esc so will respond after ages
    editing_stopped if @is_editing # 2009-01-16 16:06 
    goto_top
  when @KEY_GOTO_BOTTOM
    editing_stopped if @is_editing # 2009-01-16 16:06 
    goto_bottom
  when @KEY_SCROLL_RIGHT
    editing_stopped if @is_editing # dts 2009-02-17 00:35 
    scroll_right
  when @KEY_SCROLL_LEFT
    editing_stopped if @is_editing # dts 2009-02-17 00:35 
    scroll_left
  when ?0.getbyte(0)..?9.getbyte(0)
    $multiplier *= 10 ; $multiplier += (ch-48)
    #$log.debug " setting mult to #{$multiplier} in list "
    return 0
  else
    # there could be a case of editing here too!
    ret = process_key ch, self
    $multiplier = 0 
    return :UNHANDLED if ret == :UNHANDLED
  end
  return 0 # added 2010-03-14 13:27 
end

#init_varsObject



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/rbcurse/rtable.rb', line 100

def init_vars
  @focusable= true
  @current_index = 0
  @current_column = 0
  @oldrow = @oldcol = 0
  @current_column_offset ||= 0 # added 2009-01-12 19:06 current_column's offset
  @toprow = 0
  @show_grid ||= 1
  @_first_column_print = 0 # intro for horiz scrolling 2009-02-14 16:20 
  @_last_column_print = 0 # 2009-02-16 23:57 so we don't tab further etc. 
  # table needs to know what columns are being printed.
  @curpos = 0
  @inter_column_spacing = 1
  # @selected_color ||= 'yellow'
  # @selected_bgcolor ||= 'black'
  @col_offset = @row_offset = 0 if @suppress_borders
  @table_changed = true
  @repaint_required = true
end

#install_keys_bindingsObject



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/rbcurse/rtable.rb', line 119

def install_keys_bindings

  # alt-tab next column
  # alt-shift-tab prev column
  #bind_key(?\M-\C-i) { next_column }
  #bind_key(481) { previous_column }
  bind_key(KEY_TAB) { next_column }
  bind_key(KEY_BTAB) { previous_column }
  bind_key(KEY_RIGHT) { next_column }
  bind_key(KEY_LEFT) { previous_column }
  bind_key(@KEY_ASK_FIND_FORWARD) { ask_search_forward }
  bind_key(@KEY_ASK_FIND_BACKWARD) { ask_search_backward }
  bind_key(@KEY_FIND_NEXT) { find_next }
  bind_key(@KEY_FIND_PREV) { find_prev }
  # added 2010-05-12 21:41 for vim keys, will work if cell editing allowed is false
  # user should be able to switch to editable and off so he can use keys TODO
  # TODO vim_editable mode: C dd etc . to repeat change, how about range commands like vim
  # TODO use numeric to widen, so we can distribute spacing
  bind_key(?j){ next_row() }
  bind_key(?k){ previous_row() }
  bind_key(?G){ goto_bottom() }
  bind_key([?g,?g]){ goto_top() }
  bind_key(?l) { next_column }
  bind_key(?h) { previous_column }
end

#is_cell_selected(row, col) ⇒ Object



270
271
272
# File 'lib/rbcurse/rtable.rb', line 270

def is_cell_selected row, col
  raise "TODO "
end

#is_column_selected(col) ⇒ Object

— selection methods —#



267
268
269
# File 'lib/rbcurse/rtable.rb', line 267

def is_column_selected col
  raise "TODO "
end

#move_column(ix, newix) ⇒ Object



334
335
336
337
# File 'lib/rbcurse/rtable.rb', line 334

def move_column ix, newix
  @table_column_model.move_column ix, newix
  #table_structure_changed # this should be called by tcm TODO with object
end

#next_column(num = (($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)) ⇒ Object

move focus to next column

2009-10-07 12:47 behavior change. earlier this would move to next row
if focus was on last visible field. Now it scrolls so that first invisible
field becomes the first column. 
# 2010-05-13 12:42 added multiplier

def next_column



686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
# File 'lib/rbcurse/rtable.rb', line 686

def next_column num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
  $multiplier = 0 # so not used again in next row
  #v =  @current_column+1 
  v =  @current_column + num
  # normal situation, there is a next column go to
  if v < @table_column_model.column_count 
    if v <= @_last_column_print
      $log.debug " if v < #{@table_column_model.column_count} nd lastcolprint "
      current_column v
    else
      # there is a col but its not visible
      # XXX inefficient but i scroll completely to next column (putting it at start)
      # otherwise sometimes it was still not visible if last column
      (v-@_first_column_print).times(){scroll_right}
      current_column v
      set_form_col 
    end

  else
    if @current_index < row_count()-1 
      $log.debug " GOING TO NEXT ROW FROM NEXT COL : #{@current_index} : #{row_count}"
      @current_column = 0
      #@current_column = @_first_column_print # added 2009-02-17 00:01 
      @_first_column_print = 0 # added 2009-10-07 11:25 
      next_row 1
      set_form_col
      @repaint_required = true
      @table_changed = true    # so columns are modified by print_header
    else
      return :UNHANDLED
    end
  end
end

#next_row(num = (($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)) ⇒ Object

goto next row added multipler 2010-05-12 20:51



670
671
672
673
674
675
676
677
678
679
# File 'lib/rbcurse/rtable.rb', line 670

def next_row num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
  rc = row_count
  @oldrow = @current_index
  # don't go on if rc 2009-01-16 19:55  XXX
  if @current_index < rc
    @current_index += 1*num if @current_index < rc
    bounds_check
  end
  $multiplier = 0
end

#on_enterObject

on enter of widget the cursor should be appropriately positioned



842
843
844
845
846
847
# File 'lib/rbcurse/rtable.rb', line 842

def on_enter
  super
  set_form_row
  set_form_col # 2009-01-17 01:35 
  on_enter_cell focussed_row(), focussed_col() unless focussed_row().nil? or focussed_col().nil?
end

#on_enter_cell(arow, acol) ⇒ Object

OECE



828
829
830
831
832
833
834
835
836
837
838
839
# File 'lib/rbcurse/rtable.rb', line 828

def on_enter_cell arow, acol
  $log.debug " def on_enter_cell #{arow}, #{acol}"
  if @table_traversal_event.nil? 
    @table_traversal_event ||= TableTraversalEvent.new @oldrow, @oldcol, arow, acol, self
  else
    @table_traversal_event.set(@oldrow, @oldcol, arow, acol, self)
  end
  fire_handler :TABLE_TRAVERSAL_EVENT, @table_traversal_event
  if @editing_policy == :EDITING_AUTO
    editing_started
  end
end

#on_enter_column(acol) ⇒ Object



815
816
817
818
# File 'lib/rbcurse/rtable.rb', line 815

def on_enter_column acol
  #$log.debug " def on_enter_column #{acol}"
  on_enter_cell @current_index, acol
end

#on_enter_row(arow) ⇒ Object



811
812
813
814
# File 'lib/rbcurse/rtable.rb', line 811

def on_enter_row arow
  #$log.debug " def on_enter_row #{arow}"
  on_enter_cell arow, @current_column
end

#on_leaveObject



848
849
850
851
852
# File 'lib/rbcurse/rtable.rb', line 848

def on_leave
  super
  $log.debug " on leave of table 2009-01-16 21:58 "
  editing_stopped if @is_editing #  2009-01-16 21:58 
end

#on_leave_cell(arow, acol) ⇒ Object

OLCE



820
821
822
823
824
825
826
# File 'lib/rbcurse/rtable.rb', line 820

def on_leave_cell arow, acol
  $log.debug " def on_leave_cell #{arow}, #{acol}"
  #if @editing_policy == :EDITING_AUTO  # actually this should happen in all cases
  if @is_editing # 2009-01-17 00:49 
    editing_stopped arow, acol
  end
end

#on_leave_column(acol) ⇒ Object



806
807
808
809
810
# File 'lib/rbcurse/rtable.rb', line 806

def on_leave_column acol
  #$log.debug " def on_leave_column #{acol}"
  #on_leave_cell @current_index, acol
  on_leave_cell @oldrow, acol
end

#on_leave_row(arow) ⇒ Object



801
802
803
804
805
# File 'lib/rbcurse/rtable.rb', line 801

def on_leave_row arow
  #$log.debug " def on_leave_row #{arow}"
  #on_leave_cell arow, @current_column
  on_leave_cell arow, @oldcol # 2009-01-16 19:41 XXX trying outt
end

#prepare_editor(editor, row, col, value) ⇒ Object



475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
# File 'lib/rbcurse/rtable.rb', line 475

def prepare_editor editor, row, col, value
  r,c = rowcol
  row = r + (row - @toprow) +1  #  @form.row , 1 added for header row!
  col = c+get_column_offset()
  editor.prepare_editor self, row, col, value
  # added on 2009-02-16 23:49 
  # if data is longer than can be displayed then update editors disp len too
  if (col+editor.component.display_length)>= @col+@width
    editor.component.display_length = @width-1-col
    $log.debug "DDDXXX #{editor.component.display_length} = @width-1-col"
  else
  $log.debug "EEE if (#{col+editor.component.display_length})> #{@col+@width}"
  end
  @cell_editor = editor
  @repaint_required = true
  # copied from rlistbox, so that editors write on parent's graphic, otherwise
  # their screen updates get overwritten by parent. 2010-01-19 20:17 
  set_form_col 
end

#prepare_renderersObject

to do for TrueClass and FalseClass



396
397
398
399
400
401
402
403
404
405
406
407
# File 'lib/rbcurse/rtable.rb', line 396

def prepare_renderers
  @crh = Hash.new
  @crh['String'] = TableCellRenderer.new "", {"parent" => self }
  @crh['Fixnum'] = TableCellRenderer.new "", { "justify" => :right, "parent" => self}
  @crh['Float'] = TableCellRenderer.new "", {"justify" => :right, "parent" => self}
  @crh['TrueClass'] = CheckBoxCellRenderer.new "", {"parent" => self, "display_length"=>7}
  @crh['FalseClass'] = CheckBoxCellRenderer.new "", {"parent" => self, "display_length"=>7}
  @crh['Time'] = TableDateCellRenderer.new "", {"parent" => self, "display_length"=>16}
  #@crh['String'] = TableCellRenderer.new "", {"bgcolor" => "cyan", "color"=>"white", "parent" => self}
  #@crh['Fixnum'] = TableCellRenderer.new "", {"display_length" => 6, "justify" => :right, "color"=>"blue","bgcolor"=>"cyan" }
  #@crh['Float'] = TableCellRenderer.new "", {"display_length" => 6, "justify" => :right, "color"=>"blue", "bgcolor"=>"cyan" }
end

#previous_column(num = (($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)) ⇒ Object

move focus to previous column if you are on first column, check if scrolling required, else move up to last visible column of prev row def previous_column



723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
# File 'lib/rbcurse/rtable.rb', line 723

def previous_column num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
  v =  @current_column - num # 2010-05-13 12:44 1 to num
  # returning unhandled so focus can go to prev field auto
  if v < @_first_column_print and @current_index <= 0
    return :UNHANDLED
  end
  if v < @_first_column_print
    if v > 0
      scroll_left
      current_column v
    elsif @current_index >  0
      @current_column = @table_column_model.column_count-1
      @current_column = @_last_column_print # added 2009-02-17 00:01 
      $log.debug " XXXXXX prev col #{@current_column}, las #{@_last_column_print}, fi: #{@_first_column_print}"
      set_form_col
      previous_row 1
    end
  else
    current_column v
  end
end

#previous_row(num = (($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)) ⇒ Object

def previous_row



659
660
661
662
663
664
665
666
667
# File 'lib/rbcurse/rtable.rb', line 659

def previous_row num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
  @oldrow = @current_index
#  @current_index -= 1 if @current_index > 0
  num.times { 
    @current_index -= 1 if @current_index > 0
  }
  $multiplier = 0
  bounds_check
end


1000
1001
1002
1003
1004
1005
1006
1007
# File 'lib/rbcurse/rtable.rb', line 1000

def print_border g
  return unless @table_changed
  g.print_border @row, @col, @height-1, @width, $datacolor
  return if @table_model.nil?
  rc = @table_model.row_count
  h = scrollatrow()
  _print_more_data_marker (rc>h)
end

print table header 2011-09-17 added repaint all check so that external components can triger this e.g. multi-container when it changes tables.



1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
# File 'lib/rbcurse/rtable.rb', line 1025

def print_header
  return unless @table_changed || @repaint_all
      $log.debug " TABLE: inside printheader 2009-10-07 11:51  DDD "

  r,c = rowcol
  header_model = @table_header.table_column_model
  tcm = @table_column_model ## could have been overridden, should we use this at all
  offset = 0
  header_model.each_with_index do |tc, colix|
    next if colix < @_first_column_print # added for scrolling rt and left 2009-02-14 17:49 
    acolumn = tcm.column colix
    renderer = tc.cell_renderer
    renderer = @table_header.default_renderer if renderer.nil?
    renderer.display_length acolumn.width unless acolumn.nil?
    width = renderer.display_length + 1
    content = tc.header_value
    if c+offset+width > @col+@width
      #$log.debug " TABLE: experimental code to NOT print if chance of exceeding table width"
      # 2009-02-14 14:24 now printing, but truncating data for last column
          space_left = (@width-3)-(offset)
          space_left = 0 if space_left < 0
          if content.length > space_left
            clen = space_left
            renderer.display_length clen
          else
            clen = -1
            renderer.display_length space_left
          end
          #$log.debug " TABLE BREAKING SINCE sl: #{space_left},#{crow},#{colix}: #{clen} "
    # passing self so can prevent renderer from printing outside 2009-10-05 22:56 
          #renderer.repaint @graphic, r, c+(offset), 0, content[0..clen], false, false
          renderer.repaint self, r, c+(offset), 0, content[0..clen], false, false
      break
    end
    # passing self so can prevent renderer from printing outside 2009-10-05 22:56 
    #renderer.repaint @graphic, r, c+(offset),0, content, false, false
    renderer.repaint self, r, c+(offset),0, content, false, false
    offset += width
  end
end

#printstring(r, c, string, color, att) ⇒ Object

NEW to correct overflow

2009-10-05 21:34 
when resizing columns a renderer can go outside the table bounds
so printing should be done by parent not window


986
987
988
989
990
991
992
993
994
995
996
997
998
999
# File 'lib/rbcurse/rtable.rb', line 986

def printstring(r,c,string, color, att)
  # 3 is table borders
  # if renderer trying to print outside don't let it
  if c > @col+@width-3
    return
  end
  # if date exceeds boundary truncate
  if c+string.length > (@col+@width)-3
    len = string.length-((c+string.length)-(@col+@width-3))
    @graphic.printstring(r,c,string[0..len], color,att)
  else
    @graphic.printstring(r,c,string, color,att)
  end
end

#remove_column(tc) ⇒ Object

table_structure_changed # this should be called by tcm TODO with object



318
319
320
321
# File 'lib/rbcurse/rtable.rb', line 318

def remove_column tc
  @table_column_model.remove_column  tc
  #table_structure_changed # this should be called by tcm TODO with object
end

#remove_column_selection_interval(ix0, ix1) ⇒ Object

if column_selection_allowed



277
278
279
# File 'lib/rbcurse/rtable.rb', line 277

def remove_column_selection_interval ix0, ix1
  raise "TODO "
end

#repaintObject



881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
# File 'lib/rbcurse/rtable.rb', line 881

def repaint
  return unless @repaint_required
  my_win = @form ? @form.window : @target_window
  @graphic = my_win unless @graphic
  #$log.warn "neither form not target window given!!! TV paint 368" unless my_win
  raise " #{@name} neither form, nor target window given TV paint " unless my_win
  raise " #{@name} NO GRAPHIC set as yet                 TV paint " unless @graphic
  @win_left = my_win.left # unused remove TODO
  @win_top = my_win.top

  print_border @graphic if !@suppress_borders  # do this once only, unless everything changes
  return if @table_model.nil? # added 2009-02-17 12:45 
  @_first_column_print ||= 0
  cc = @table_model.column_count
  rc = @table_model.row_count
  inter_column_padding = " " * @inter_column_spacing 
  @_last_column_print = cc-1
  tcm = @table_column_model
  tm = @table_model
  tr = @toprow
  _column_scrolling = false
  acolor = get_color $datacolor
  h = scrollatrow()
  r,c = rowcol
  # each cell should print itself, however there is a width issue. 
  # Then thee
  print_header # do this once, unless columns changed
  # TCM should give modelindex of col which is used to fetch data from TM
  r += 1 # save for header
  0.upto(h) do |hh|
    crow = tr+hh  # crow is the row
    if crow < rc
      offset = 0 # offset of column
#      0.upto(cc-1) do |colix|
      focussed = @current_index == crow ? true : false 
      selected = is_row_selected crow
      # we loop through column_model and fetch data based on model index
      # FIXED better to call table.get_value_at since we may now 
      # introduce a view - 2009-01-18 18:21 
      tcm.each_with_index do |acolumn, colix|
        next if colix < @_first_column_print
        #acolumn = tcm.column(colix)
        #model_index = acolumn.model_index
        content = get_value_at(crow, colix)  # tables
        renderer = get_cell_renderer(crow, colix)
        if renderer.nil?
          renderer = get_default_cell_renderer_for_class(content.class.to_s) if renderer.nil?
          renderer.display_length acolumn.width unless acolumn.nil?
        end
        width = renderer.display_length + @inter_column_spacing
        acolumn.column_offset = offset
        # trying to ensure that no overprinting
        if c+offset+width > @col+@width
          _column_scrolling = true
          @_last_column_print = colix
          # experimental to print subset of last
          space_left = (@width-3)-(offset) # 3 due to boundaries
          space_left = 0 if space_left < 0
          # length bombed for trueclass 2009-10-05 19:34 
          contentlen = content.length rescue content.to_s.length
          #if content.length > space_left
          if contentlen > space_left
            clen = space_left
            renderer.display_length clen
          else
            clen = -1
            renderer.display_length space_left # content.length
          end
          # added 2009-10-05 20:29 since non strings were bombing
          # in other cases should be just pass the content as-is. XXX
          contenttrim = content[0..clen] rescue content # .to_s[0..clen]
          # print the inter cell padding just in case things mess up while scrolling
          @graphic.mvprintw r+hh, c+offset-@inter_column_spacing, inter_column_padding
          #renderer.repaint @graphic, r+hh, c+offset, crow, content[0..clen], focussed, selected
          #renderer.repaint @graphic, r+hh, c+offset, crow, contenttrim, focussed, selected
          # 2009-10-05 20:35 XXX passing self so we check it doesn't print outside
          renderer.repaint self, r+hh, c+offset, crow, contenttrim, focussed, selected
          break
        end
        # added crow on 2009-02-11 22:46 
        #renderer.repaint @graphic, r+hh, c+(offset), crow, content, focussed, selected
          # 2009-10-05 20:35 XXX
        renderer.repaint self, r+hh, c+(offset), crow, content, focussed, selected
        offset += width
      end
    else
      #@graphic.printstring r+hh, c, " " * (@width-2), acolor,@attr
      printstring r+hh, c, " " * (@width-2), acolor,@attr
      # clear rows
    end
  end
  if @is_editing
    @cell_editor.component.repaint unless @cell_editor.nil? or @cell_editor.component.form.nil?
  end
  _print_more_columns_marker _column_scrolling
  _print_more_data_marker(rc-1 > tr + h)
  $log.debug " _print_more_data_marker(#{rc} >= #{tr} + #{h})"
  @table_changed = false
  @repaint_required = false
  #@buffer_modified = true # 2011-09-30 CLEANUP
end

#row_countObject

added 2009-01-07 13:05 so new scrollable can use



157
158
159
160
# File 'lib/rbcurse/rtable.rb', line 157

def row_count
  return 0 if @table_model.nil?
  @table_model.row_count
end

#scroll_backwardObject



755
756
757
758
759
760
# File 'lib/rbcurse/rtable.rb', line 755

def scroll_backward
  @oldrow = @current_index
  h = scrollatrow()
  @current_index -= h 
  bounds_check
end

#scroll_forwardObject



761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
# File 'lib/rbcurse/rtable.rb', line 761

def scroll_forward
  @oldrow = @current_index
  h = scrollatrow()
  rc = row_count
  # more rows than box
  if h < rc
    @toprow += h+1 #if @current_index+h < rc
    @current_index = @toprow
  else
    # fewer rows than box
    @current_index = rc -1
  end
  #@current_index += h+1 #if @current_index+h < rc
  bounds_check
end

#scroll_leftObject



1121
1122
1123
1124
1125
1126
1127
1128
1129
# File 'lib/rbcurse/rtable.rb', line 1121

def scroll_left
  if @_first_column_print > 0
    @_first_column_print -= 1
    @current_column =  @_first_column_print
      set_form_col
    @repaint_required = true
    @table_changed = true
  end
end

#scroll_rightObject



1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
# File 'lib/rbcurse/rtable.rb', line 1110

def scroll_right
  cc = @table_model.column_count
  if @_first_column_print < cc-1
    @_first_column_print += 1
    @_last_column_print += 1 if @_last_column_print < cc-1
    @current_column =  @_first_column_print
      set_form_col # FIXME not looking too good till key press
    @repaint_required = true
    @table_changed = true    # so columns are modified
  end
end

#scrollatrowObject

added 2009-01-07 13:05 so new scrollable can use



162
163
164
165
166
167
168
# File 'lib/rbcurse/rtable.rb', line 162

def scrollatrow
  if @suppress_borders # NOT TESTED XXX
    @height - 2 # we forgot to remove 1 from height in border.
  else
    @height - 4 # we forgot to remove 1 from height in border.
  end
end

#selected_columnObject



281
282
283
# File 'lib/rbcurse/rtable.rb', line 281

def selected_column
  @table_column_model.selected_columns[0]
end

#selected_column_countObject



287
288
289
# File 'lib/rbcurse/rtable.rb', line 287

def selected_column_count
  @table_column_model.selected_column_count
end

#selected_columnsObject



284
285
286
# File 'lib/rbcurse/rtable.rb', line 284

def selected_columns
  @table_column_model.selected_columns
end

#set_column_widths(cw) ⇒ Object

convenience method sets column widths given an array of ints You may get such an array from estimate_column_widths



1217
1218
1219
1220
1221
1222
1223
1224
# File 'lib/rbcurse/rtable.rb', line 1217

def set_column_widths cw
  raise "Cannot call set_column_widths till table set" unless @table_column_model
  tcm = @table_column_model
  tcm.each_with_index do |col, ix|
    col.width cw[ix]
  end
  table_structure_changed(nil)
end

#set_data(data, colnames_array) ⇒ Object

Sets the data in models Should replace if these are created. TODO FIXME



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/rbcurse/rtable.rb', line 173

def set_data data, colnames_array
  # next 2 added in case set_data called again
  @table_changed = true
  @repaint_required = true
  data ||= [[]]
  colnames_array ||= [""]
  if data.is_a? Array
    model = RubyCurses::DefaultTableModel.new data, colnames_array
    table_model model
  elsif data.is_a? RubyCurses::TableModel
    table_model data
  else
    raise "set_data: don't know how to handle data: #{data.class.to_s}"
  end
  if colnames_array.is_a? Array
    model = DefaultTableColumnModel.new colnames_array
    table_column_model model
  elsif colnames_array.is_a? RubyCurses::TableColumnModel
    table_column_model  colnames_array
  else
    raise "set_data: don't know how to handle column data: #{colnames_array.class.to_s}"
  end
  create_default_list_selection_model
  create_table_header
  # added 2010-09-09 19:57 if user provides col widths in hash, or size_to_fit
    $log.debug " XXX @size_to_fit: #{@size_to_fit} "
  if @_column_widths
    $log.debug "XXXX inside set column widths "
    set_column_widths @_column_widths
  elsif @estimate_widths
    $log.debug "XXXX inside estimate column widths "
    cw = estimate_column_widths data
    set_column_widths cw
  elsif @size_to_fit
    $log.debug " XXX inside  @size_to_fit: #{@size_to_fit} "
    size_columns_to_fit
  end
end

#set_default_cell_renderer_for_class(cname, rend) ⇒ Object



414
415
416
417
# File 'lib/rbcurse/rtable.rb', line 414

def set_default_cell_renderer_for_class cname, rend
  @crh ||= {}
  @crh[cname]=rend
end

#set_focus_on(arow) ⇒ Object

2009-01-17 13:25



1066
1067
1068
1069
1070
# File 'lib/rbcurse/rtable.rb', line 1066

def set_focus_on arow
  @oldrow = @current_index
  @current_index = arow
  bounds_check if @oldrow != @current_index  
end

#set_form_col(col = @curpos) ⇒ Object

set cursor on correct column, widget



864
865
866
867
868
869
870
871
872
873
# File 'lib/rbcurse/rtable.rb', line 864

def set_form_col col=@curpos
  @curpos = col
  @cols_panned ||= 0 # RFED16 2010-02-19 10:00 
  @current_column_offset = get_column_offset 
  #@form.col = @col + @col_offset + @curpos + @current_column_offset
  #[email protected]
  win_col = 0 # RFED16 2010-02-19 10:00 
  fcol = @col + @col_offset + @curpos + @current_column_offset + @cols_panned + win_col
  setrowcol(nil, fcol) # 2010-01-18 20:04 
end

#set_form_rowObject



853
854
855
856
857
858
859
860
861
862
# File 'lib/rbcurse/rtable.rb', line 853

def set_form_row
  r,c = rowcol
  @rows_panned ||= 0 # RFED16 2010-02-19 10:00 
  win_row = 0
  #[email protected] # 2010-01-18 20:28 added
  # +1 is due to header
  #@form.row = r + (@current_index-@toprow) + 1
  frow = r + (@current_index-@toprow) + 1 + win_row + @rows_panned
  setrowcol(frow, nil) # 2010-01-18 20:04 
end

#set_model(tm, tcm = nil, lsm = nil) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/rbcurse/rtable.rb', line 211

def set_model tm, tcm=nil, lsm=nil
  table_model tm
  if tcm.nil?
    create_default_table_column_model
  else
    table_column_model tcm
  end
  if lsm.nil?
    create_default_list_selection_model
  else
    list_selection_model lsm
  end
  create_table_header
end

#set_value_at(row, col, value) ⇒ Object

must not give wrong results when columns switched!



347
348
349
350
# File 'lib/rbcurse/rtable.rb', line 347

def set_value_at row, col, value
  model_index = @table_column_model.column(col).model_index
  @table_model.set_value_at row, model_index, value
end

#size_columns_to_fitObject



1225
1226
1227
1228
1229
1230
1231
1232
# File 'lib/rbcurse/rtable.rb', line 1225

def size_columns_to_fit
  delta = @width - table_column_model().get_total_column_width()
  tcw = table_column_model().get_total_column_width()

  $log.debug "size_columns_to_fit D #{delta}, W #{@width}, TCW #{tcw}"
  accomodate_delta(delta) if delta != 0
  #set_width_from_preferred_widths
end

#table_column_model(*val) ⇒ Object

updated this so no param will return the tcm 2009-02-14 12:31



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/rbcurse/rtable.rb', line 238

def table_column_model(*val)
  if val.empty?
    return @table_column_model
  end
  tcm = val[0]
  raise "data error: table_column_model wrong class" if !tcm.is_a? RubyCurses::TableColumnModel
  @table_column_model = tcm
  @table_column_model.bind(:TABLE_COLUMN_MODEL_EVENT) {|e| 
    table_structure_changed e
  }
  @table_column_model.bind(:PROPERTY_CHANGE){|e| column_property_changed(e)}

  #@table_header.column_model(tcm) unless @table_header.nil?
  @table_header.table_column_model=(tcm) unless @table_header.nil?
end

#table_data_changed(tabmodev) ⇒ Object

— event listener support methods (p521) TODO —#



354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/rbcurse/rtable.rb', line 354

def table_data_changed tabmodev
  #$log.debug " def table_data_changed got #{tabmodev}"
  @repaint_required = true
  # next was required otherwise on_enter would bomb if data changed from outside
  if row_count == 0
    init_vars
    set_form_col # added 2009-01-24 14:32 since cursor was still showing on existing col
    return #  added 2009-01-23 15:15 
  end
  # the next block to be only called if user is inside editing. Often data will be refreshed by
  # a search field and this gets called.
  if @is_editing
    @is_editing = false # 2009-01-19 18:18 testing this out XXX
    # we need to refresh the editor if you deleted a row while sitting on it
    # otherwise it shows the old value
    editing_started 
  end
end

#table_model(*val) ⇒ Object

getter and setter for table_model



227
228
229
230
231
232
233
234
235
236
# File 'lib/rbcurse/rtable.rb', line 227

def table_model(*val)
  if val.empty?
    @table_model
  else
    raise "data error" if !val[0].is_a? RubyCurses::TableModel
    @table_model = val[0] 
    ## table registers as a listener, or rather binds to event
    @table_model.bind(:TABLE_MODEL_EVENT){|lde| table_data_changed(lde) }
  end
end

#table_structure_changed(tablecolmodelevent) ⇒ Object



372
373
374
375
376
377
# File 'lib/rbcurse/rtable.rb', line 372

def table_structure_changed tablecolmodelevent
  $log.debug " def table_structure_changed #{tablecolmodelevent}"
  @table_changed = true
  @repaint_required = true
  init_vars
end

#toggle_cell_editingObject



614
615
616
617
618
619
620
621
622
# File 'lib/rbcurse/rtable.rb', line 614

def toggle_cell_editing
  return unless @cell_editing_allowed
  @is_editing = !@is_editing
  if @is_editing 
    editing_started
  else
    editing_stopped
  end
end