module Canis::ListScrollable

Attributes

find_offset[R]
find_offset1[R]
search_found_ix[R]
show_caret[RW]

Public Instance Methods

_convert_index_to_printable_row(index=@current_index) click to toggle source

actual position to write on window NOTE can return nil, if user scrolls forward or backward

# File lib/canis/core/include/deprecated/listscrollable.rb, line 623
def _convert_index_to_printable_row index=@current_index
  r,c = rowcol
  pos = _convert_index_to_visible_row(index)
  return nil unless pos
  pos = r + pos
  return pos
end
_convert_index_to_visible_row(index=@current_index) click to toggle source

offset in widget like 0..scrollatrow NOTE can return nil, if user scrolls forward or backward @private

# File lib/canis/core/include/deprecated/listscrollable.rb, line 616
def _convert_index_to_visible_row index=@current_index
  pos = index - @toprow
  return nil if pos < 0 || pos > scrollatrow()
  return pos
end
_find_next(regex=@last_regex, start = @search_found_ix, first_time = false) click to toggle source

find forwards Using this to start a search or continue search

# File lib/canis/core/include/deprecated/listscrollable.rb, line 328
def _find_next regex=@last_regex, start = @search_found_ix, first_time = false
  #raise "No previous search" if regex.nil?
  warn "No previous search" and return if regex.nil?
  #$log.debug " _find_next #{@search_found_ix} : #{@current_index}"
  extra = 1 # first time search on current line, next time skip current line or else we get stuck.
  extra = 0 if first_time
  start ||= 0
  fend = @list.size-1
  if start != fend
    start += extra unless start == fend # used to be +=1 so we don't get stuck in same row
    @last_regex = regex
    @search_start_ix = start
    regex = Regexp.new(regex, Regexp::IGNORECASE) if @search_case
    start.upto(fend) do |ix| 
      row1 = @list[ix].to_s

      # 2011-09-29 crashing on a character F3 in log file
      # 2013-03-20 - 18:25 187compat
      if row1.respond_to? :encode
        row = row1.encode("ASCII-8BIT", :invalid => :replace, :undef => :replace, :replace => "?")
      else
        row = row1
      end

      m=row.match(regex)
      if !m.nil?
        @find_offset = m.offset(0)[0]
        @find_offset1 = m.offset(0)[1]
        ix += (@_header_adjustment || 0)
        @search_found_ix = ix
        return ix 
      end
    end
  end
  fend = start-1
  start = 0
  if @search_wrap
    start.upto(fend) do |ix| 
      row = @list[ix].to_s
      m=row.match(regex)
      if !m.nil?
        @find_offset = m.offset(0)[0]
        @find_offset1 = m.offset(0)[1]
        ix += (@_header_adjustment || 0)
        @search_found_ix = ix
        return ix 
      end
    end
  end
  return nil
end
_find_prev(regex=@last_regex, start = @search_found_ix, first_time = false) click to toggle source

find backwards Using this to start a search or continue search

# File lib/canis/core/include/deprecated/listscrollable.rb, line 412
def _find_prev regex=@last_regex, start = @search_found_ix, first_time = false
  #TODO the firsttime part, see find_next
  #raise "No previous search" if regex.nil?
  warn "No previous search" and return if regex.nil?
  #$log.debug " _find_prev #{@search_found_ix} : #{@current_index}"
  if start != 0
    start -= 1 unless start == 0
    @last_regex = regex
    @search_start_ix = start
    regex = Regexp.new(regex, Regexp::IGNORECASE) if @search_case
    start.downto(0) do |ix| 
      row = @list[ix].to_s
      m=row.match(regex)
      if !m.nil?
        @find_offset = m.offset(0)[0]
        @find_offset1 = m.offset(0)[1]
        ix += (@_header_adjustment || 0)
        @search_found_ix = ix
        return ix 
      end
    end
  end
  fend = start-1
  start = @list.size-1
  if @search_wrap
    start.downto(fend) do |ix| 
      row = @list[ix].to_s
      m=row.match(regex)
      if !m.nil?
        @find_offset = m.offset(0)[0]
        @find_offset1 = m.offset(0)[1]
        ix += (@_header_adjustment || 0)
        @search_found_ix = ix
        return ix 
      end
    end
  end
  return nil
end
backward_word() click to toggle source

go to beginning of previous word somewhat similar to vim's 'b' movement. Introduced on 2013-03-25 - 00:49 and has some errors but mostly quite helpful - i think i've fixed the error of getting stuck on a line

# File lib/canis/core/include/deprecated/listscrollable.rb, line 494
def backward_word
  $multiplier = 1 if !$multiplier || $multiplier == 0
  line = @current_index
  buff = @list[line].to_s
  return unless buff
  pos = @curpos || 0 # list does not have curpos
  $multiplier.times {
    #found = buff.index(/[[:punct:][:space:]]+/, pos)
    # 2013-03-04 - 17:35 modified so it skips spaces and puncts
    # ouch pos becomes -2 and remains in same line !

    spos = pos -2
    spos = 0 if spos < 0
    found = buff.rindex(/[[:punct:][:space:]]\w/, spos)
    if !found || found == 0
      # if not found, we've lost a counter/multiplier
      if pos > 0
        pos = 0
      elsif line > 0
        line -= 1
        buff = @list[line].to_s
        pos = buff.size - 1
      else
        return
      end
    else
      pos = found + 1
    end
    $log.debug "BBB backward_word: pos #{pos} line #{line} buff: #{buff}, found #{found}"
  }
  @current_index = line
  @curpos = pos
  @buffer = @list[@current_index].to_s
  set_form_row
  set_form_col pos
  @repaint_required = true
end
bounds_check() click to toggle source

please set oldrow before calling this. Store current_index as oldrow before changing. NOTE

# File lib/canis/core/include/deprecated/listscrollable.rb, line 83
def bounds_check
  h = scrollatrow()
  rc = row_count
  @old_toprow = @toprow

  @_header_adjustment ||= 0
  @current_index = 0 if @current_index < 0  # not lt 0
  @current_index = rc-1 if @current_index >= rc && rc>0 # not gt rowcount
  @toprow = rc-h-1 if rc > h && @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
    # sometimes current row gets hidden below header line
    @toprow = @current_index - (@_header_adjustment ||0)
    # prev line can make top row -1, however, if we are going back, lets
    # put it at start of page, so first or second row is not hidden
    @toprow = 0 if @toprow < h
  end

  @row_changed = false
  if @oldrow != @current_index
    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
    set_form_row
    @row_changed = true
  end
  #set_form_row # 2011-10-13

  if @old_toprow != @toprow # only if scrolling has happened should we repaint
    @repaint_required = true #if @old_toprow != @toprow # only if scrolling has happened should we repaint
    @widget_scrolled = true
  end
end
down(num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier))
Alias for: next_row
find_more() click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 319
def find_more
  if @search_direction_prev 
    find_prev
  else
    find_next
  end
end
find_next() click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 379
def find_next
  unless @last_regex
    alert("No previous search. Search first.")
    return
  end
  ix = _find_next
  regex = @last_regex 
  if ix.nil?
    alert("No more matching data for: #{regex}")
  else
    set_focus_on(ix) 
    set_form_col @find_offset1
    @cell_editor.component.curpos = (@find_offset||0) if @cell_editing_allowed
  end
end
find_prev() click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 394
def find_prev
  unless @last_regex
    alert("No previous search. Search first.")
    return
  end
  ix = _find_prev
  regex = @last_regex 
  if ix.nil?
    alert("No previous matching data for: #{regex}")
  else
    set_focus_on(ix)
    set_form_col @find_offset
    @cell_editor.component.curpos = (@find_offset||0) if @cell_editing_allowed
  end
end
focussed_index() click to toggle source

not that saving content_rows is buggy since we add rows.

caution, this now uses winrow not prow

for user to know which row is being focussed on
# File lib/canis/core/include/deprecated/listscrollable.rb, line 203
def focussed_index
  @current_index # 2009-01-07 14:35
end
Also aliased as: selected_index
forward_char(char=nil) click to toggle source

goes to next occurence of <char> (or nth occurence) Actually, we can club this with forward_word so no duplication Or call one from the other

# File lib/canis/core/include/deprecated/listscrollable.rb, line 536
def forward_char char=nil
  if char.nil?
    $log.debug " XXX acceptng char"
    ch = @graphic.getchar
    return -1 if ch < 0 or ch > 255 # or 127 ???
    char = ch.chr
  end
  $log.debug " forward_char char:#{char}:"
  $multiplier = 1 if !$multiplier or $multiplier == 0
  line = @current_index
  buff = @list[line].to_s
  pos = @curpos
  $multiplier.times {
    found = false
    while !found
      found = buff.index(char, pos)
      if !found
        line += 1 # unless eof
        buff = @list[line].to_s
        pos = 0
      else
        pos = found + 1
      end
      break if line >= @list.size
      $log.debug " #{found} forward_word: pos #{pos} line #{line} buff: #{buff}"
    end
  }
  @current_index = line
  @curpos = pos
  @buffer = @list[@current_index].to_s
  set_form_row
  set_form_col pos
  @repaint_required = true
end
forward_word() click to toggle source

goes to start of next word (or n words) - vi's w NOTE: will not work if the list has different data from what is displayed Nothing i can do about it. Also does not work as expected if consecutive spaces FIXME Will not scroll list, if reaches end, jist goes on and vanshes FIXME

# File lib/canis/core/include/deprecated/listscrollable.rb, line 458
def forward_word
  $multiplier = 1 if !$multiplier || $multiplier == 0
  line = @current_index
  buff = @list[line].to_s
  return unless buff
  pos = @curpos || 0 # list does not have curpos
  $multiplier.times {
    #found = buff.index(/[[:punct:][:space:]]+/, pos)
    # 2013-03-04 - 17:35 modified so it skips spaces and puncts
    found = buff.index(/[[:punct:][:space:]]\w/, pos)
    if !found
      # if not found, we've lost a counter
      if line+1 < @list.length
        line += 1
      else
        return
      end
      buff = @list[line].to_s
      pos = 0
    else
      pos = found + 1
    end
    $log.debug " forward_word: pos #{pos} line #{line} buff: #{buff}"
  }
  @current_index = line
  @curpos = pos
  @buffer = @list[@current_index].to_s
  set_form_row
  set_form_col pos
  @repaint_required = true
end
goto_bottom() click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 40
def goto_bottom
  @oldrow = @current_index
  rc = row_count
  @current_index = rc -1
  bounds_check
end
Also aliased as: goto_end
goto_end()
Alias for: goto_bottom
goto_last_position() click to toggle source
returns cursor to last row (if moving columns in same row, won't work)

Useful after a large move such as 12j, 20 C-n etc, Mapped to '' in textview

# File lib/canis/core/include/deprecated/listscrollable.rb, line 194
def goto_last_position
  return unless @oldrow
  @current_index = @oldrow
  bounds_check
end
goto_start()
Alias for: goto_top
goto_top() click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 47
def goto_top
  @oldrow = @current_index
  @current_index = 0
  bounds_check
end
Also aliased as: goto_start
highlight_focussed_row(type, r=nil, c=nil, acolor=nil) click to toggle source

highlights the focussed (current) and unfocussed (oldrow)

NOTE: when multiselecting ... it will remove selection
so be careful when calling.
# File lib/canis/core/include/deprecated/listscrollable.rb, line 634
def highlight_focussed_row type, r=nil, c=nil, acolor=nil
  return unless @should_show_focus
  case type
  when :FOCUSSED
    ix = @current_index
    return if is_row_selected ix
    r = _convert_index_to_printable_row() unless r
    return unless r # row is not longer visible 2013-04-10 - 16:37
    attrib = @focussed_attrib || 'bold'

  when :UNFOCUSSED
    return if @oldrow.nil? || @oldrow == @current_index
    ix = @oldrow
    return if is_row_selected ix
    r = _convert_index_to_printable_row(@oldrow) unless r
    return unless r # row is not longer visible
    attrib = @attr
  end
  unless c
    _r, c = rowcol
  end
  # this optimization now overrides any coloring that listbox may have done per row XXX
  acolor ||= get_color $datacolor
  att = get_attrib(attrib) #if @focussed_attrib
  @graphic.mvchgat(y=r, x=c, @width-@internal_width, att , acolor , nil)
end
install_keys() click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 264
    def install_keys
=begin
      @KEY_ASK_FIND_FORWARD ||= ?\M-f.getbyte(0)
      @KEY_ASK_FIND_BACKWARD ||= ?\M-F.getbyte(0)
      @KEY_FIND_NEXT ||= ?\M-g.getbyte(0)
      @KEY_FIND_PREV ||= ?\M-G.getbyte(0)
=end
      @KEY_ASK_FIND ||= ?\M-f.getbyte(0)
      @KEY_FIND_MORE ||= ?\M-g.getbyte(0)
    end
is_visible?(index) click to toggle source

Is the given index in the visible area UNTESTED XXX

# File lib/canis/core/include/deprecated/listscrollable.rb, line 608
def is_visible? index
  #(0..scrollatrow()).include? index - @toprow
  j = index - @toprow
  j >= 0 && j <= scrollatrow()
end
next_match(char) click to toggle source

finds the next match for the char pressed returning the index If we are only checking first char, then why chomp ? Please note that this is used now by tree, and list can have non-strings, so use to_s

# File lib/canis/core/include/deprecated/listscrollable.rb, line 218
def next_match char
  data = get_content
  row = focussed_index + 1
  row.upto(data.length-1) do |ix|
    #val = data[ix].chomp rescue return  # 2010-01-05 15:28 crashed on trueclass
    val = data[ix].to_s rescue return  # 2010-01-05 15:28 crashed on trueclass
    #if val[0,1] == char #and val != currval
    if val[0,1].casecmp(char) == 0 #AND VAL != CURRval
      return ix
    end
  end
  row = focussed_index - 1
  0.upto(row) do |ix|
    #val = data[ix].chomp
    val = data[ix].to_s
    #if val[0,1] == char #and val != currval
    if val[0,1].casecmp(char) == 0 #and val != currval
      return ix
    end
  end
  return -1
end
next_row(num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)) click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 27
def next_row num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
  rc = row_count
  # returning unhandled was clever .. when user hits down arrow on last row the focus goes to
  # next field. however, in long lists when user scrolls the sudden jumping to next is very annoying.
  # In combos, if focus was on last row, the combo closed which is not accceptable.
  #return :UNHANDLED if @current_index == rc-1 # EVIL !!!
  return :NO_NEXT_ROW if @current_index == rc-1  # changed 2011-10-5 so process can do something
  @oldrow = @current_index
  @current_index += 1*num if @current_index < rc
  bounds_check
  $multiplier = 0
end
Also aliased as: down
previous_row(num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)) click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 14
def previous_row num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
  #return :UNHANDLED if @current_index == 0 # EVIL
  return :NO_PREVIOUS_ROW if @current_index == 0 
  @oldrow = @current_index
  # NOTE that putting a multiplier inside, prevents an event from being triggered for each row's
  # on leave and on enter
  num.times { 
    @current_index -= 1 if @current_index > 0
  }
  bounds_check
  $multiplier = 0
end
Also aliased as: up
scroll_backward() click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 53
def scroll_backward
  @oldrow = @current_index
  h = scrollatrow()
  m = $multiplier == 0? 1 : $multiplier
  @current_index -= h * m
  bounds_check
  $multiplier = 0
end
scroll_forward() click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 61
def scroll_forward
  @oldrow = @current_index
  h = scrollatrow()
  rc = row_count
  m = $multiplier == 0? 1 : $multiplier
  # more rows than box
  if h * m < rc
    # next 2 lines were preventing widget_scrolled from being set to true,
    # so i've modified it slightly as per scroll_down 2011-11-1
    #@toprow += h+1 #if @current_index+h < rc
    #@current_index = @toprow
    @current_index += h+1
  else
    # fewer rows than box
    @current_index = rc -1
  end
  #@current_index += h+1 #if @current_index+h < rc
  bounds_check
end
scroll_left() click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 186
def scroll_left
  hscrollcols = $multiplier > 0 ? $multiplier : @width/2
  @pcol -= hscrollcols if @pcol > 0
  @pcol = 0 if @pcol < 0
  @repaint_required = true
end
scroll_right() click to toggle source
# File lib/canis/core/include/deprecated/listscrollable.rb, line 170
def scroll_right
  $log.debug " inside scroll_right "
  hscrollcols = $multiplier > 0 ? $multiplier : @width/2
  #hscrollcols = $multiplier > 0 ? $multiplier : 1 # for testing out
  $log.debug " scroll_right  mult:#{$multiplier} , hscrollcols  #{hscrollcols}, pcol #{@pcol} w: #{@width} ll:#{@longest_line} "
  #blen = @buffer.rstrip.length
  blen = @longest_line
  if @pcol + @width < blen 
    @pcol += hscrollcols if @pcol + @width < blen 
  else
    # due to some change somewhere, sometimes width = longest which is not true
    hscrollcols = $multiplier > 0 ? $multiplier : 1
    @pcol += hscrollcols
  end
  @repaint_required = true
end
selected_index()

alias :current_index :focussed_index

Alias for: focussed_index
selected_item() click to toggle source

only to be used in single selection cases as focussed item FIXME. best not to use, as can be implementation dep, use current_index

# File lib/canis/core/include/deprecated/listscrollable.rb, line 208
def selected_item
  get_content()[focussed_index()]
end
set_focus_on(arow) click to toggle source

ensures that the given row is focussed new version of older one that was not perfect. 2009-01-17 13:25

# File lib/canis/core/include/deprecated/listscrollable.rb, line 256
def set_focus_on arow
  @oldrow = @current_index
  # the next line fixed cursor positioning, but when wraparound then it messed up
  # matching line would get hidden
  @current_index = arow
  bounds_check if @oldrow != @current_index
end
set_form_row() click to toggle source

the cursor should be appropriately positioned

# File lib/canis/core/include/deprecated/listscrollable.rb, line 119
def set_form_row
  r,c = rowcol
  @rows_panned ||= 0

  # when the toprow is set externally then cursor can be mispositioned since
  # bounds_check has not been called
  if @current_index < @toprow
    # cursor is outside table
    @current_index = @toprow # ??? only if toprow 2010-10-19 12:56
  end

  row = r + (@current_index-@toprow) + @rows_panned 
  # row should not be < r or greater than r+height TODO FIXME

  setrowcol row, nil

end
set_selection_for_char(char) click to toggle source
2008-12-18 18:03

sets the selection to the next row starting with char

# File lib/canis/core/include/deprecated/listscrollable.rb, line 242
def set_selection_for_char char
  @oldrow = @current_index
  @last_regex = "^#{char}"
  ix = next_match char
  @current_index = ix if ix && ix != -1
  @search_found_ix = @current_index
  bounds_check
  return ix
end
show_caret_func() click to toggle source
paint the cursor ourselves on the widget, rather than rely on getting to the top window with
the correct coordinates. I do need to erase cursor too. Can be dicey, but is worth the attempt.
This works perfectly, except for when placed in a Tabbedpane since that prints the form with a row offset

+ of 2 and the widget does not know of the offset. cursor gets it correct since the form has an add_row.

# File lib/canis/core/include/deprecated/listscrollable.rb, line 146
def show_caret_func
  return unless @show_caret
  # trying highlighting cursor 2010-01-23 19:07 TABBEDPANE TRYING
  # TODO take into account rows_panned etc ? I don't think so.
  @rows_panned ||= 0
  r,c = rowcol
  yy = r + @current_index - @toprow - @win_top
  #xx = @form.col # how do we know what value has been set earlier ?
  yy = r + @current_index - @toprow #- @win_top
  yy = @row_offset + @current_index - @toprow #- @win_top
  xx = @col_offset + @curpos || 0
  #yy = @row_offset if yy < @row_offset # sometimes r is 0, we are missing something in tabbedpane+scroll
  #xx = @col_offset if xx < @col_offset
  #xx = 0 if xx < 0

  $log.debug " #{@name} printing CARET at #{yy},#{xx}: fwt:- #{@win_top} r:#{@row} tr:-#{@toprow}+ci:#{@current_index},+r #{r}  "
  if !@oldcursorrow.nil?
    @graphic.mvchgat(y=@oldcursorrow, x=@oldcursorcol, 1, Ncurses::A_NORMAL, $datacolor, NIL)
  end
  @oldcursorrow = yy
  @oldcursorcol = xx
  @graphic.mvchgat(y=yy, x=xx, 1, Ncurses::A_NORMAL, $reversecolor, nil)
  @buffer_modified = true
end
up(num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier))
Alias for: previous_row