Class: RubyCurses::Listbox

Inherits:
Widget show all
Extended by:
Forwardable
Includes:
ListScrollable, ListKeys, ListSelectable
Defined in:
lib/rbcurse/rlistbox.rb

Overview

A control for displaying a list of data or values. The list will be editable if @cell_editing_allowed is set to true when creating. By default, multiple selection is allowed, but may be set to :single. TODO: were we not going to force creation of datamodel and listener on startup by putting a blank :list in config, if no list or list_variable or model is there ? Or at end of constructor check, if no listdatamodel then create default. TODO : perhaps when datamodel created, attach listener to it, so we can fire to callers when they want to be informed of changes. As we did with selection listeners.

Direct Known Subclasses

DirectoryList

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 included from ListScrollable

#find_offset, #find_offset1, #search_found_ix, #show_caret

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, #do_next_selection, #do_prev_selection, #is_selected?, #list_selection_model, #remove_row_selection_interval, #selected_row, #selected_row_count, #selected_rows, #selected_value, #toggle_row_selection

Methods included from ListScrollable

#_find_next, #_find_prev, #ask_search, #bounds_check, #find_more, #find_next, #find_prev, #focussed_index, #forward_char, #forward_word, #goto_bottom, #goto_last_position, #goto_top, #install_keys, #next_match, #next_row, #previous_row, #scroll_backward, #scroll_forward, #scroll_left, #scroll_right, #selected_item, #set_focus_on, #set_form_row, #set_selection_for_char, #show_caret_func

Methods inherited from Widget

#changed, #click, #destroy, #enter, #event_list, #focus, #get_preferred_size, #getvalue_for_paint, #height, #height=, #hide, #leave, #modified?, #move, #on_leave, #override_graphic, #printstring, #process_key, #remove, #repaint_all, #repaint_required, #rowcol, #set_buffer_modified, #set_form, #set_form_row, #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_header, #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, config = {}, &block) ⇒ Listbox

Returns a new instance of Listbox.



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
475
476
477
478
479
480
# File 'lib/rbcurse/rlistbox.rb', line 446

def initialize form, config={}, &block
  @focusable = true
  @editable = false
  @sanitization_required = true
  @row = 0
  @col = 0
  # data of listbox this is not an array, its a pointer to the  listdatamodel
  @list = nil 
  # any special attribs such as status to be printed in col1, or color (selection)
  @list_attribs = {}
  @suppress_borders = false
  @row_offset = @col_offset = 1 # for borders
  super
  @_events.push(*[:ENTER_ROW, :LEAVE_ROW, :LIST_SELECTION_EVENT, :PRESS])
  @current_index ||= 0
  @selection_mode ||= :multiple # default is multiple, anything else given becomes single
  @win = @graphic    # 2010-01-04 12:36 BUFFERED  replace form.window with graphic
  # moving down to repaint so that scrollpane can set should_buffered
  # added 2010-02-17 23:05  RFED16 so we don't need a form.
  @win_left = 0
  @win_top = 0

  # next 2 lines carry a redundancy
  select_default_values   
  # when the combo box has a certain row in focus, the popup should have the same row in focus

  install_keys
  init_vars
  install_list_keys
  bind(:PROPERTY_CHANGE){|e| @cell_renderer = nil } # will be recreated if anything changes 2011-09-28 V1.3.1  

  if @list && !@list.selected_index.nil? 
    set_focus_on @list.selected_index # the new version
  end
end

Instance Attribute Details

#current_indexObject

Returns the value of attribute current_index.



421
422
423
# File 'lib/rbcurse/rlistbox.rb', line 421

def current_index
  @current_index
end

#one_key_selectionObject

will pressing a single key select or not



440
441
442
# File 'lib/rbcurse/rlistbox.rb', line 440

def one_key_selection
  @one_key_selection
end

#toprowObject (readonly)

dsl_accessor :list # the array of data to be sent by user



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

def toprow
  @toprow
end

Instance Method Details

#[](off0) ⇒ Object

get element at

Parameters:

  • index (Fixnum)

    for element

Returns:

Since:

  • 1.2.0 2010-09-06 14:33 making life easier for others.



637
638
639
# File 'lib/rbcurse/rlistbox.rb', line 637

def [](off0)
  @list[off0]
end

#ask_search_backwardObject

gets string to search and calls data models find prev



839
840
841
842
843
844
845
846
847
848
# File 'lib/rbcurse/rlistbox.rb', line 839

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

#ask_search_forwardObject



829
830
831
832
833
834
835
836
837
# File 'lib/rbcurse/rlistbox.rb', line 829

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

#ask_selection_for_charObject

get a keystroke from user and go to first item starting with that key



822
823
824
825
826
827
828
# File 'lib/rbcurse/rlistbox.rb', line 822

def ask_selection_for_char
  ch = @graphic.getch
  if ch < 0 || ch > 255
    return :UNHANDLED
  end
  ret = set_selection_for_char ch.chr
end

#cancel_blockObject

added on 2009-02-19 22:37



1118
1119
1120
1121
# File 'lib/rbcurse/rlistbox.rb', line 1118

def cancel_block
  @first_index = @last_index = nil
  @inside_block = false
end

#cell_editor(*val) ⇒ Object

getter and setter for cell_editor



930
931
932
933
934
935
936
# File 'lib/rbcurse/rlistbox.rb', line 930

def cell_editor(*val)
  if val.empty?
    @cell_editor ||= create_default_cell_editor
  else
    @cell_editor = val[0] 
  end
end

#cell_renderer(*val) ⇒ Object

getter and setter for cell_renderer



942
943
944
945
946
947
948
# File 'lib/rbcurse/rlistbox.rb', line 942

def cell_renderer(*val)
  if val.empty?
    @cell_renderer ||= create_default_cell_renderer
  else
    @cell_renderer = val[0] 
  end
end

#convert_value_to_text(value, crow) ⇒ Object

the idea here is to allow users who subclass Listbox to easily override parts of the cumbersome repaint method. This assumes your List has some data, but you print a lot more. Now you don’t need to change the data in the renderer, or keep formatted data in the list itself. e.g. @list contains file names, or File objects, and this converts to a long listing. If the renderer did that, the truncation would be on wrong data.

Since:

  • 1.2.0



1028
1029
1030
1031
1032
1033
1034
1035
# File 'lib/rbcurse/rlistbox.rb', line 1028

def convert_value_to_text value, crow
  case value
  when TrueClass, FalseClass
    value
  else
    value.to_s if value
  end
end

#create_default_cell_editorObject



937
938
939
# File 'lib/rbcurse/rlistbox.rb', line 937

def create_default_cell_editor
  return RubyCurses::CellEditor.new RubyCurses::Field.new nil, {"focusable"=>false, "visible"=>false, "display_length"=> @width-@internal_width-@left_margin}
end

#create_default_cell_rendererObject



949
950
951
# File 'lib/rbcurse/rlistbox.rb', line 949

def create_default_cell_renderer
  return RubyCurses::ListCellRenderer.new "", {"color"=>@color, "bgcolor"=>@bgcolor, "parent" => self, "display_length"=> @width-@internal_width-@left_margin}
end

#create_default_list_selection_modelObject

create a default list selection model and set it NOTE: I am now checking if one is not already created, since a second creation would wipe out any listeners on it.



626
627
628
629
630
# File 'lib/rbcurse/rlistbox.rb', line 626

def create_default_list_selection_model
  if @list_selection_model.nil?
    list_selection_model DefaultListSelectionModel.new(self)
  end
end

#current_valueObject Also known as: current_row, text

return object under cursor Note: this should not be confused with selected row/s. User may not have selected this. This is only useful since in some demos we like to change a status bar as a user scrolls down

Since:

  • 1.2.0 2010-09-06 14:33 making life easier for others.



644
645
646
# File 'lib/rbcurse/rlistbox.rb', line 644

def current_value
  @list[@current_index]
end

#edit_row_at(arow) ⇒ Object



873
874
875
876
877
878
879
# File 'lib/rbcurse/rlistbox.rb', line 873

def edit_row_at arow
  if @cell_editing_allowed
    #$log.debug " cell editor on enter #{arow} val of list[row]: #{@list[arow]}"
    editor = cell_editor
    prepare_editor editor, arow
  end
end

#editing_canceled(arow = @current_index) ⇒ Object



922
923
924
925
926
# File 'lib/rbcurse/rlistbox.rb', line 922

def editing_canceled arow=@current_index
  return unless @cell_editing_allowed
  prepare_editor @cell_editor, arow
  @repaint_required = true
end

#editing_completed(arow) ⇒ Object



910
911
912
913
914
915
916
917
918
919
920
921
# File 'lib/rbcurse/rlistbox.rb', line 910

def editing_completed arow
  if @cell_editing_allowed
    if !@cell_editor.nil?
  #    $log.debug " cell editor (leave) setting value row: #{arow} val: #{@cell_editor.getvalue}"
      $log.debug " cell editor #{@cell_editor.component.form.window} (leave) setting value row: #{arow} val: #{@cell_editor.getvalue}"
      @list[arow] = @cell_editor.getvalue #.dup 2009-01-10 21:42 boolean can't duplicate
    else
      $log.debug "CELL EDITOR WAS NIL, #{arow} "
    end
  end
  @repaint_required = true
end

#end_blockObject

sets marker for end of block added on 2009-02-19 22:37



1130
1131
1132
1133
1134
1135
1136
1137
# File 'lib/rbcurse/rlistbox.rb', line 1130

def end_block #selection
  @last_index = current_index
  lower = [@first_index, @last_index].min
  higher = [@first_index, @last_index].max
  #lower.upto(higher) do |i| @list.toggle_row_selection i; end
  add_row_selection_interval(lower, higher)
  @repaint_required = true
end

#fire_action_eventObject

fire handler when user presses ENTER/RETURN listbox now traps ENTER key and fires action event to trap please bind :PRESS

Since:

  • 1.2.0



815
816
817
818
819
820
# File 'lib/rbcurse/rlistbox.rb', line 815

def fire_action_event
  # this does not select the row ???? FIXME ??
  require 'rbcurse/ractionevent'
  # should have been callled :ACTION_EVENT !!!
  fire_handler :PRESS, ActionEvent.new(self, :PRESS, text)
end

#get_contentObject

START FOR scrollable ###



685
686
687
688
# File 'lib/rbcurse/rlistbox.rb', line 685

def get_content
  #@list 2008-12-01 23:13 
  @list_variable && @list_variable.value || @list 
end

#get_selected_indicesObject Also known as: selected_indices

trying to simplify usage. The Java way has made listboxes very difficult to use Returns selected indices Indices are often required since the renderer may modify the values displayed



1168
1169
1170
# File 'lib/rbcurse/rlistbox.rb', line 1168

def get_selected_indices
  @list_selection_model.get_selected_indices
end

#get_selected_valuesObject Also known as: selected_values

Returns selected values



1174
1175
1176
1177
1178
# File 'lib/rbcurse/rlistbox.rb', line 1174

def get_selected_values
  selected = []
  @list_selection_model.get_selected_indices.each { |i| selected << list_data_model[i] }
  return selected
end

#get_windowObject



689
690
691
# File 'lib/rbcurse/rlistbox.rb', line 689

def get_window
  @graphic # 2010-01-04 12:37 BUFFERED
end

#getvalueObject

END FOR scrollable ### override widgets text returns indices of selected rows



695
696
697
# File 'lib/rbcurse/rlistbox.rb', line 695

def getvalue
  selected_rows
end

#handle_key(ch) ⇒ Object

Listbox



699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
# File 'lib/rbcurse/rlistbox.rb', line 699

def handle_key(ch)
  map_keys unless @keys_mapped
  @current_index ||= 0
  @toprow ||= 0
  h = scrollatrow()
  rc = row_count
  $log.debug " listbox got ch #{ch}"
  #$log.debug " when kps #{@KEY_PREV_SELECTION}  "
  case ch
  when 10,13, KEY_ENTER
    # this means you cannot just bind_key 10 or 13 like we once did
    fire_action_event # trying out REMOVE 2011-09-16 FFI
    $log.debug " 333 listbox catching 10,13 fire_action_event "
    return 0
  when KEY_UP  # show previous value
    return previous_row
  when KEY_DOWN  # show previous value
    return next_row
  when @KEY_ROW_SELECTOR # 32
    return if is_popup && @selection_mode != :multiple # not allowing select this way since there will be a difference 
    toggle_row_selection @current_index #, @current_index
    @repaint_required = true
  when @KEY_SCROLL_FORWARD # ?\C-n
    scroll_forward
  when @KEY_SCROLL_BACKWARD #  ?\C-p
    scroll_backward
  when @KEY_GOTO_TOP # 48, ?\C-[
    # please note that C-[ gives 27, same as esc so will respond after ages
    goto_top
  when @KEY_GOTO_BOTTOM # ?\C-]
    goto_bottom
  when @KEY_NEXT_SELECTION # ?'
    $log.debug "insdie next selection"
    @oldrow = @current_index
    do_next_selection 
    bounds_check
  when @KEY_PREV_SELECTION # ?"
    @oldrow = @current_index
    $log.debug "insdie prev selection"
    do_prev_selection 
    bounds_check
  when @KEY_CLEAR_SELECTION
    clear_selection 
    @repaint_required = true
  when 27, ?\C-c.getbyte(0), ?\C-g.getbyte(0)
    editing_canceled @current_index if @cell_editing_allowed
    cancel_block # block
    $multiplier = 0
  when @KEY_ASK_FIND_FORWARD
  # ask_search_forward
  when @KEY_ASK_FIND_BACKWARD
  # ask_search_backward
  when @KEY_FIND_NEXT
  # find_next
  when @KEY_FIND_PREV
  # find_prev
  when @KEY_ASK_FIND
    ask_search
  when @KEY_FIND_MORE
    find_more
  when @KEY_BLOCK_SELECTOR
    mark_block #selection
  #when ?\C-u.getbyte(0)
    # multiplier. Series is 4 16 64
    # TESTING @multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
  #  return 0
  when ?\C-c.getbyte(0)
    @multiplier = 0
    return 0
  else
    # this has to be fixed, if compo does not handle key it has to continue into next part FIXME
    ret = :UNHANDLED # changed on 2009-01-27 13:14 not going into unhandled, tab not released
    if @cell_editing_allowed
      @repaint_required = true
      # hack - on_enter_row should fire when this widget gets focus. first row that is DONE
      begin
        ret = @cell_editor.component.handle_key(ch)
      rescue
        on_enter_row @current_index
        ret = @cell_editor.component.handle_key(ch)
      end
    end
    if ret == :UNHANDLED
      # beware one-key eats up numbers. we'll be wondering why
      if @one_key_selection
        case ch
        #when ?A.getbyte(0)..?Z.getbyte(0), ?a.getbyte(0)..?z.getbyte(0), ?0.getbyte(0)..?9.getbyte(0)
        when ?A.getbyte(0)..?Z.getbyte(0), ?a.getbyte(0)..?z.getbyte(0)
          # simple motion, key press defines motion
          ret = set_selection_for_char ch.chr
        else
          ret = process_key ch, self
  $log.debug "111 listbox #{@current_index} "
          @multiplier = 0
          return :UNHANDLED if ret == :UNHANDLED
        end
      else
        # no motion on single key, we can freak out like in vim, pref f <char> for set_selection
        case ch
        when ?0.getbyte(0)..?9.getbyte(0)
          $multiplier *= 10 ; $multiplier += (ch-48)
          #$log.debug " setting mult to #{$multiplier} in list "
          return 0
        end
        ret = process_key ch, self
        return :UNHANDLED if ret == :UNHANDLED
      end
    end
  end
  $multiplier = 0
end

#init_varsObject

this is called several times, from constructor and when list data changed, so only put relevant resets here. why can’t current_index be set to 0 here



484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
# File 'lib/rbcurse/rlistbox.rb', line 484

def init_vars
  @repaint_required = true
  @toprow = @pcol = 0

  @row_offset = @col_offset = 0 if @suppress_borders
  if @show_selector
    @row_selected_symbol ||= '>'
    @row_unselected_symbol ||= ' '
    @left_margin ||= @row_selected_symbol.length
  end
  @left_margin ||= 0
  @one_key_selection = true if @one_key_selection.nil?
  # we reduce internal_width from width while printing
  @internal_width = 2 # taking into account borders accounting for 2 cols
  @internal_width = 0 if @suppress_borders # should it be 0 ???

end

#list(*val) ⇒ ListDataModel

provide data to List in the form of an Array or Variable or ListDataModel. This will create a default ListSelectionModel.

CHANGE as on 2010-09-21 12:53: If explicit nil passed then dummy datamodel and selection model created From now on, constructor will call this, so this can always happen.

NOTE: sometimes this can be added much after its painted. Do not expect this to be called from constructor, although that is the usual case. it can be dependent on some other list or tree.

Parameters:

Returns:



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
# File 'lib/rbcurse/rlistbox.rb', line 563

def list *val
  return @list if val.empty?
  clear_selection if @list # clear previous selections if any
  @default_values = nil if @list # clear previous selections if any
  alist = val[0]
  case alist
  when Array
    if @list
      @list.remove_all
      @list.insert 0, *alist
      @current_index = 0
    else
      @list = RubyCurses::ListDataModel.new(alist)
    end
  when NilClass
    if @list
      @list.remove_all
    else
      @list = RubyCurses::ListDataModel.new(alist)
    end
  when Variable
    @list = RubyCurses::ListDataModel.new(alist.value)
  when RubyCurses::ListDataModel
    @list = alist
  else
    raise ArgumentError, "Listbox list(): do not know how to handle #{alist.class} " 
  end
  # added on 2009-01-13 23:19 since updates are not automatic now
  @list.bind(:LIST_DATA_EVENT) { |e| list_data_changed() }
  create_default_list_selection_model
  @list_selection_model.selection_mode = @tmp_selection_mode if @tmp_selection_mode
  @repaint_required = true
  @list
end

#list_data_changedObject



1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
# File 'lib/rbcurse/rlistbox.rb', line 1069

def list_data_changed
  if row_count == 0 # added on 2009-02-02 17:13 so cursor not hanging on last row which could be empty
    init_vars
    @current_index = 0
    # I had placed this at some time to get cursor correct. But if this listbox is updated
    # during entry in another field, then this steals the row. e.g. test1.rb 5
    #set_form_row
  end
  @repaint_required = true
end

#list_data_model(ldm = nil) ⇒ Object

populate using a custom data model NOTE: This explicilty overwrites any existing datamodel such as the default one. You may lose any events you have bound to the listbox prior to this call.



613
614
615
616
617
618
619
620
# File 'lib/rbcurse/rlistbox.rb', line 613

def list_data_model ldm=nil
  return @list if ldm.nil?
  raise "Expecting list_data_model" unless ldm.is_a? RubyCurses::ListDataModel
  @list = ldm
  # added on 2009-01-13 23:19 since updates are not automatic now
  @list.bind(:LIST_DATA_EVENT) { |e| list_data_changed() }
  create_default_list_selection_model
end

#list_variable(alist = nil) ⇒ Object

populate using a Variable which should contain a list NOTE: This explicilty overwrites any existing datamodel such as the default one. You may lose any events you have bound to the listbox prior to this call.



601
602
603
604
605
606
607
# File 'lib/rbcurse/rlistbox.rb', line 601

def list_variable alist=nil
  return @list if alist.nil?
  @list = RubyCurses::ListDataModel.new(alist.value)
  # added on 2009-01-13 23:19 since updates are not automatic now
  @list.bind(:LIST_DATA_EVENT) { |e| list_data_changed() }
  create_default_list_selection_model
end

#map_keysObject



501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
# File 'lib/rbcurse/rlistbox.rb', line 501

def map_keys
  return if @keys_mapped
  bind_key(?f){ ask_selection_for_char() }
  bind_key(?\M-v){ @one_key_selection = false }
  bind_key(?j){ next_row() }
  bind_key(?k){ previous_row() }
  bind_key(?G){ goto_bottom() }
  bind_key([?g,?g]){ goto_top() }
  bind_key(?/){ ask_search() }
  bind_key(?n){ find_more() }
  bind_key(32){ toggle_row_selection() }
  bind_key(10){ fire_action_event }
  bind_key(13){ fire_action_event }
  @keys_mapped = true
end

#mark_blockObject

end experimental selection of multiple rows via block specify a block start and then a block end usage: bind mark_selection to a key. It works as a toggle. C-c will cancel any selection that has begun. added on 2009-02-19 22:37



1108
1109
1110
1111
1112
1113
1114
1115
1116
# File 'lib/rbcurse/rlistbox.rb', line 1108

def mark_block #selection
  if @inside_block
    @inside_block = false
    end_block #selection
  else
    @inside_block = true
    start_block #selection
  end
end

#on_enterBoolean

please check for error before proceeding

Returns:

  • (Boolean)

    false if no data



851
852
853
854
855
856
857
858
859
860
861
862
863
864
# File 'lib/rbcurse/rlistbox.rb', line 851

def on_enter
  if @list.nil? || @list.size == 0
    #Ncurses.beep
    get_window.ungetch($current_key) # 2011-10-4 push key back so form can go next
    return :UNHANDLED
  end
  on_enter_row @current_index
  set_form_row # added 2009-01-11 23:41 
  #$log.debug " ONE ENTER LIST #{@current_index}, #{@form.row}"
  @repaint_required = true
  super
  #fire_handler :ENTER, self
  true
end

#on_enter_row(arow) ⇒ Object



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

def on_enter_row arow
  #$log.debug " Listbox #{self} ENTER_ROW with curr #{@current_index}. row: #{arow} H: #{@handler.keys}"
  #fire_handler :ENTER_ROW, arow
  fire_handler :ENTER_ROW, self
  @list.on_enter_row self  ## XXX WHY THIS ???
  edit_row_at arow
  @repaint_required = true
end

#on_leave_row(arow) ⇒ Object

set original value so we can cancel set row and col, set value and other things, color and bgcolor



903
904
905
906
907
908
909
# File 'lib/rbcurse/rlistbox.rb', line 903

def on_leave_row arow
  #$log.debug " Listbox #{self} leave with (cr: #{@current_index}) #{arow}: list[row]:#{@list[arow]}"
  #$log.debug " Listbox #{self} leave with (cr: #{@current_index}) #{arow}: "
  #fire_handler :LEAVE_ROW, arow
  fire_handler :LEAVE_ROW, self
  editing_completed arow
end

#prepare_editor(editor, row) ⇒ Object

private



882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
# File 'lib/rbcurse/rlistbox.rb', line 882

def prepare_editor editor, row
  r,c = rowcol
  value =  @list[row] # .chomp
  value = value.dup rescue value # so we can cancel
  row = r + (row - @toprow) #  @form.row
  col = c+@left_margin # @form.col
  # unfortunately 2009-01-11 19:47 combo boxes editable allows changing value
  editor.prepare_editor self, row, col, value
  editor.component.curpos = 0 # reset it after search, if user scrols down
  #editor.component.graphic = @graphic #  2010-01-05 00:36 TRYING OUT BUFFERED
  ## override is required if the listbox uses a buffer
  #if @should_create_buffer # removed on 2011-09-29 
    #$log.debug " overriding editors comp with GRAPHIC #{@graphic} "
    #editor.component.override_graphic(@graphic) #  2010-01-05 00:36 TRYING OUT BUFFERED
  #end
  set_form_col 0 #@left_margin

  # set original value so we can cancel
  # set row and col,
  # set value and other things, color and bgcolor
end


659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
# File 'lib/rbcurse/rlistbox.rb', line 659

def print_borders
  width = @width
  height = @height-1 # 2010-01-04 15:30 BUFFERED HEIGHT
  window = @graphic  # 2010-01-04 12:37 BUFFERED
  startcol = @col 
  startrow = @row 
  @color_pair = get_color($datacolor)
#      bordercolor = @border_color || $datacolor # changed 2011 dts  
  bordercolor = @border_color || @color_pair
  borderatt = @border_attrib || Ncurses::A_NORMAL

  #$log.debug "rlistb #{name}: window.print_border #{startrow}, #{startcol} , h:#{height}, w:#{width} , @color_pair, @attr "
  window.print_border startrow, startcol, height, width, bordercolor, borderatt
  print_title
end


674
675
676
677
678
679
680
681
682
683
# File 'lib/rbcurse/rlistbox.rb', line 674

def print_title
  @color_pair ||= get_color($datacolor)
  # check title.length and truncate if exceeds width
  return unless @title
  _title = @title
  if @title.length > @width - 2
    _title = @title[0..@width-2]
  end
  @graphic.printstring( @row, @col+(@width-_title.length)/2, _title, @color_pair, @title_attrib) unless @title.nil?
end

#repaintObject

this method chops the data to length before giving it to the renderer, this can cause problems if the renderer does some processing. also, it pans the data horizontally giving the renderer a section of it.



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
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
# File 'lib/rbcurse/rlistbox.rb', line 957

def repaint
  return unless @repaint_required
  # not sure where to put this, once for all or repeat 2010-02-17 23:07 RFED16
  my_win = @form ? @form.window : @target_window
  @graphic = my_win unless @graphic
  raise " #{@name} neither form, nor target window given LB paint " unless my_win
  raise " #{@name} NO GRAPHIC set as yet                 LB paint " unless @graphic
  @win_left = my_win.left
  @win_top = my_win.top

  #$log.debug "rlistbox repaint  #{@name} r,c, #{@row} #{@col} , width: #{@width}  "
  print_borders unless @suppress_borders # do this once only, unless everything changes
  #maxlen = @maxlen || @width-@internal_width
  renderer = cell_renderer()
  renderer.display_length(@width-@internal_width-@left_margin) # just in case resizing of listbox
  tm = list()
  rc = row_count
  @longest_line = @width
  $log.debug " rlistbox #{row_count} "
  if rc > 0     # just added in case no data passed
    tr = @toprow
    acolor = get_color $datacolor # should be set once, if color or bgcolor changs TODO FIXME
    h = scrollatrow()
    r,c = rowcol
    0.upto(h) do |hh|
      crow = tr+hh
      if crow < rc
        _focussed = @current_index == crow ? true : false  # row focussed ?
        focus_type = _focussed 
        # added 2010-09-02 14:39 so inactive fields don't show a bright focussed line
        #focussed = false if focussed && !@focussed
        focus_type = :SOFT_FOCUS if _focussed && !@focussed
        selected = is_row_selected crow
        content = tm[crow]   # 2009-01-17 18:37 chomp giving error in some cases says frozen
        content = convert_value_to_text content, crow # 2010-09-23 20:12 
        # by now it has to be a String
        if content.is_a? String
          content = content.dup
          sanitize content if @sanitization_required
          truncate content
        end
        ## set the selector symbol if requested
        selection_symbol = ''
        if @show_selector
          if selected
            selection_symbol = @row_selected_symbol
          else
            selection_symbol =  @row_unselected_symbol
          end
          @graphic.printstring r+hh, c, selection_symbol, acolor,@attr
        end
        #renderer = get_default_cell_renderer_for_class content.class.to_s
        renderer.repaint @graphic, r+hh, c+@left_margin, crow, content, focus_type, selected
      else
        # clear rows
        @graphic.printstring r+hh, c, " " * (@width-@internal_width), acolor,@attr
      end
    end
    if @cell_editing_allowed
      @cell_editor.component.repaint unless @cell_editor.nil? or @cell_editor.component.form.nil?
    end
  end # rc == 0
  #@table_changed = false
  @repaint_required = false
end

#row_countObject



537
538
539
540
# File 'lib/rbcurse/rlistbox.rb', line 537

def row_count
  return 0 if @list.nil?
  @list.length
end

#sanitize(content) ⇒ Object

takes a block, this way anyone extending this class can just pass a block to do his job This modifies the string



1038
1039
1040
1041
1042
1043
1044
1045
1046
# File 'lib/rbcurse/rlistbox.rb', line 1038

def sanitize content
  if content.is_a? String
    content.chomp!
    content.gsub!(/\t/, '  ') # don't display tab
    content.gsub!(/[^[:print:]]/, '')  # don't display non print characters
  else
    content
  end
end

#scrollatrowObject

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



542
543
544
545
546
547
548
# File 'lib/rbcurse/rlistbox.rb', line 542

def scrollatrow
  if @suppress_borders
    return @height - 1
  else
    return @height - 3
  end
end

#select_default_valuesObject

XXX can this not be done at repaint



652
653
654
655
656
657
658
# File 'lib/rbcurse/rlistbox.rb', line 652

def select_default_values
  return if @default_values.nil?
  @default_values.each do |val|
    row = @list.index val
    add_row_selection_interval row, row unless row.nil?
  end
end

#selection_mode(*val) ⇒ Object

getter and setter for selection_mode Must be called after creating model, so no duplicate. Since one may set in model directly.



520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
# File 'lib/rbcurse/rlistbox.rb', line 520

def selection_mode(*val)
  #raise "ListSelectionModel not yet created!" if @list_selection_model.nil?

  if val.empty?
    if @list_selection_model
      return @list_selection_model.selection_mode
    else
      return @tmp_selection_mode
    end
  else
    if @list_selection_model.nil?
      @tmp_selection_mode = val[0] 
    else
      @list_selection_model.selection_mode = val[0].to_sym
    end
  end
end

#set_buffering(params) ⇒ Object

2010-02-18 11:40 TRYING OUT - canceling editing if resized otherwise drawing errors can occur the earlier painted edited comp in yellow keeps showing until a key is pressed



1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
# File 'lib/rbcurse/rlistbox.rb', line 1142

def set_buffering params
  $log.warn "CALLED set_buffering in LISTBOX listbox " if $log.debug? 
  super # removed from widget 2011-09-29 
  ## Ensuring that changes to top get reflect in editing comp
  #+ otherwise it raises an exception. Still the earlier cell_edit is being
  #+ printed where it was , until a key is moved
  # FIXME - do same for col
  if @cell_editor
    r,c = rowcol
    if @cell_editor.component.row < @row_offset + @buffer_params[:screen_top]
      @cell_editor.component.row = @row_offset +  @buffer_params[:screen_top]
    end
    # TODO next block to be tested by placing a listbox in right split of vertical
    if @cell_editor.component.col < @col_offset + @buffer_params[:screen_left]
      @cell_editor.component.col = @col_offset +  @buffer_params[:screen_left]
    end
    #editing_canceled @current_index if @cell_editing_allowed and @cell_editor
  end
  #set_form_row
  @repaint_required = true
end

#set_form_col(col1 = 0) ⇒ Object

set cursor column position if i set col1 to @curpos, i can move around left right if key mapped



1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
# File 'lib/rbcurse/rlistbox.rb', line 1081

def set_form_col col1=0
  # TODO BUFFERED use setrowcol @form.row, col
  # TODO BUFFERED use cols_panned
  #col1 ||= 0
  @cols_panned ||= 0 # RFED16 2010-02-17 23:40 
  # editable listboxes will involve changing cursor and the form issue
  ## added win_col on 2010-01-04 23:28 for embedded forms BUFFERED TRYING OUT
  #[email protected]
  win_col = 0 # 2010-02-17 23:19 RFED16
  #col = win_col + @orig_col + @col_offset + @curpos + @form.cols_panned
  col2 = win_col + @col + @col_offset + col1 + @cols_panned + @left_margin
  $log.debug " set_form_col in rlistbox #{@col}+ left_margin #{@left_margin} ( #{col2} ) "
  #super col+@left_margin
  #@form.setrowcol @form.row, col2   # added 2009-12-29 18:50 BUFFERED
  setrowcol nil, col2 # 2010-02-17 23:19 RFED16
end

#start_blockObject

sets marker for start of block added on 2009-02-19 22:37



1124
1125
1126
1127
# File 'lib/rbcurse/rlistbox.rb', line 1124

def start_block #selection
  @first_index = @current_index
  @last_index = nil
end

#truncate(content) ⇒ Object

returns only the visible portion of string taking into account display length and horizontal scrolling. MODIFIES STRING if you;ve truncated the data, it could stay truncated even if lb is increased. be careful FIXME if _maxlen becomes 0 then maxlen -1 will print whole string again



1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
# File 'lib/rbcurse/rlistbox.rb', line 1051

def truncate content
  _maxlen = @maxlen || @width-@internal_width
  _maxlen = @width-@internal_width if _maxlen > @width-@internal_width
  #$log.debug "TRUNCATE: listbox maxlen #{@maxlen}, #{_maxlen} width #{@width}: #{content} "
  if !content.nil? 
    if content.length > _maxlen # only show maxlen
      @longest_line = content.length if content.length > @longest_line
      #content = content[@pcol..@pcol+maxlen-1] 
      content.replace content[@pcol..@pcol+_maxlen-1] 
    else
      # can this be avoided if pcol is 0 XXX
      content.replace content[@pcol..-1] if @pcol > 0
    end
  end
  #$log.debug " content: #{content}" 
  content
end