lib/ruco/window.rb in ruco-0.0.40 vs lib/ruco/window.rb in ruco-0.0.41

- old
+ new

@@ -1,35 +1,56 @@ module Ruco class Window OFFSET = 5 - attr_accessor :position, :lines, :columns, :top, :left - attr_reader :cursor + attr_accessor :lines, :columns, :left + attr_reader :cursor, :top - def initialize(lines, columns) + def initialize(lines, columns, options={}) + @options = options + + @options[:line_scroll_threshold] ||= 1 + @options[:line_scroll_offset] ||= 1 + @options[:column_scroll_threshold] ||= 1 + @options[:column_scroll_offset] ||= 5 + @lines = lines @columns = columns @top = 0 @left = 0 @cursor = Position.new(0,0) end - def crop(content) - lines = content[visible_lines] || [] - lines[@lines-1] ||= nil - lines.map do |line| + def position=(x) + set_position(x) + end + + def set_position(position, options={}) + scroll_line_into_view position.line, (options[:max_lines] || 9999) + scroll_column_into_view position.column + @cursor = Position.new(position.line - @top, position.column - @left) + end + + def crop(lines) + lines_to_display = lines[visible_lines] || [] + lines_to_display[@lines-1] ||= nil + lines_to_display.map do |line| line ||= '' line[visible_columns] || '' end end - def position=(pos) - self.top = pos.line - line_offset unless visible_lines.include?(pos.line) - self.left = pos.column - column_offset unless visible_columns.include?(pos.column) - @cursor = Position.new(pos.line - @top, pos.column - @left) + def scroll_line_into_view(line, total_lines) + result = adjustment(line, visible_lines, @options[:line_scroll_threshold], @options[:line_scroll_offset]) + set_top result, total_lines if result end + def scroll_column_into_view(column) + result = adjustment(column, visible_columns, @options[:column_scroll_threshold], @options[:column_scroll_offset]) + self.left = result if result + end + def color_mask(selection) mask = Array.new(lines) return mask unless selection mask.map_with_index do |_,line| @@ -44,33 +65,35 @@ [last[1]-left, Curses::A_NORMAL] ] end end - def top=(x) - @top = [x,0].max - end - def left=(x) @left = [x,0].max end + def set_top(line, total_lines) + max_top = total_lines - lines + 1 + @options[:line_scroll_offset] + @top = [[line, max_top].min, 0].max + end + private + def adjustment(current, allowed, threshold, offset) + if current < (allowed.first + threshold) + current - offset + elsif current > (allowed.last - threshold) + size = allowed.last - allowed.first + 1 + current - size + 1 + offset + end + end + def visible_area(line) line += @top start_of_line = [line, @left] last_visible_column = @left + @columns end_of_line = [line, last_visible_column] start_of_line..end_of_line - end - - def line_offset - @lines / 2 - end - - def column_offset - @columns / 2 end def visible_lines @top..(@top+@lines-1) end \ No newline at end of file