class Rgw::BigList

Constants

ROW_PADDING

Attributes

data[R]

@return [Array] The complete data of the list as set by {#data=} or

nil if not.
heads[R]

@return [Array<String>, nil] The heads of the list if set by {#heads=}

or nil if not.
numCols[R]

@return [Integer] The number of columns for the list as set by {#num_cols=}

separator[R]

@return [String] The separator to split data strings as set by {#separator=}

Public Class Methods

new(num_cols=1) click to toggle source

@param num_cols [Integer, nil] The number of columns the list sould have.

Calls superclass method
# File lib/rgw/big-list.rb, line 42
def initialize num_cols=1
    super(2, 2, false)
    raise ArgumentError, 'positive integer expected' unless (num_cols.is_a? Integer and num_cols > 0)
    @numCols = num_cols
    # the X poxitions of the column ends
    @colsX = []
    # current displayed top column
    @col = 0
    # current displayed left column
    @row = 0

    @data = nil
    @heads = nil
    @headHeight = 0.0
    @separator = "\t"

    @area = Gtk::DrawingArea.new
    self.attach @area, 0, 1, 0, 2, Gtk::AttachOptions::EXPAND | Gtk::AttachOptions::FILL,
                                   Gtk::AttachOptions::EXPAND | Gtk::AttachOptions::FILL

    # I don't use the integrated double buffering, cause it flickers
    # I can do it better myself
    double_buffered = false
    @backBuffer = nil

    @area.add_events Gdk::Event::Mask::SCROLL_MASK

    @area.signal_connect(:scroll_event) {|object, event| on_scroll event.direction; false}
    @area.signal_connect(:draw)                   {|object, cc| redraw; false}
    @area.signal_connect(:configure_event)        {|object, event| on_configure event; false}

    @scroll = Gtk::Scrollbar.new :vertical
    self.attach @scroll, 1, 2, 1, 2, 0, Gtk::AttachOptions::EXPAND | Gtk::AttachOptions::FILL

    dummy = Gtk::Label.new ' '
    self.attach dummy, 1, 2, 0, 1, 0, 0
end

Public Instance Methods

data=(data) click to toggle source

Set the lists data

@param data [Array] The data for the list. The array has to contain Strings, which will

be split with [separator], or arrays of strings, which will be used directly.
# File lib/rgw/big-list.rb, line 99
def data=(data)
    @data = data
    configure_scrollbar
    queue_draw
end
heads=(heads) click to toggle source

Set the heads of the the list @param heads [Array<String>] The texts which should be displayed as the columns heads.

# File lib/rgw/big-list.rb, line 108
def heads=(heads)
    unless heads.nil?
        raise ArgumentError, "invalid type %s for heads; expect Array of String" % heads.class.to_s unless heads.is_a? Array
        raise ArgumentError, "invalid size of heads" unless @numCols == heads.length
        heads.each {|head| raise ArgumentError, "invalid type %s for head; expect String" % head.class.to_s unless head.is_a? String}
    end
    @heads = heads
    calculate_rows
    configure_scrollbar
end
num_cols=(cols) click to toggle source

Sets the number of columns

@param cols [Integer] The number of columns the list should display @raise [ArgumentError] if cols is not an Integer or less then 1

# File lib/rgw/big-list.rb, line 134
def num_cols=(cols)
    
    raise ArgumentError, 'invalid column number' unless cols.is_a? Integer and cols > 0
    @numCols = cols
    @colsX = []
    width = @width.to_f / @numCols.to_f
    0.upto(@numCols) {|col| @colsX << col.to_f * width}
    queue_draw
end
row_at_pos(x, y) click to toggle source

Get the row data from a given position

@param x [Integer] Ignored for now. @param y [Integer] The vertical position in pixels from the list top position from where

to get the data from

@return [Array<String>] The rows data for the requested position. The data is owend

by the list and should not be modified, because it will change your original data!
# File lib/rgw/big-list.rb, line 152
def row_at_pos x, y
    @data[@row + y.to_f / @rowHeight]
end
separator=(sep) click to toggle source

Set the column separator

@param sep [String] For lists, where the data is provided as an array of strings the

separator will be used to split the input to the text for each column.
# File lib/rgw/big-list.rb, line 124
def separator=(sep)
    @separator = sep
    queue_draw
end

Private Instance Methods

calculate_rows() click to toggle source
# File lib/rgw/big-list.rb, line 210
def calculate_rows
    return if self.window.nil?
    @backBuffer = Cairo::ImageSurface.new Cairo::Format::RGB24, @width, @height
    cc = Cairo::Context.new @backBuffer
    cc.font_size = @ccFontSize
    @rowHeight = cc.text_extents('XgqT)!_').height.to_f + ROW_PADDING.to_f * 2.0
    @headHeight = @heads.nil? ? 0.0 : @rowHeight + 4.0
    @numRows = ((@height.to_f - @headHeight) / @rowHeight).ceil

    if @colsX.length() == 0
        width = @width.to_f / @numCols.to_f
        0.upto(@numCols) {|col| @colsX << col.to_f * width}
    else
        @colsX[-1] = @width.to_f
    end
end
configure_scrollbar() click to toggle source
# File lib/rgw/big-list.rb, line 180
def configure_scrollbar
    return if @data.nil? or @numRows.nil? or @height.nil?
    if @numRows >= @data.length()
        @scroll.hide
    else
        @scroll.show
        @scroll.adjustment = Gtk::Adjustment.new 0, 0, @data.length(), 1, @numRows, @numRows
        @scroll.adjustment.signal_connect(:value_changed) {on_scrollbar_change}
    end
end
on_configure(event) click to toggle source
# File lib/rgw/big-list.rb, line 198
def on_configure event
    @width  = event.width
    @height = event.height
    ctx = self.toplevel.style_context
    fnt = ctx.get_font :normal
    @ccFontSize = Pango.pixels(fnt.size) / 72.0 * self.toplevel.screen.resolution
    @ccFontFamily = fnt.family
    calculate_rows
    configure_scrollbar
end
on_scroll(dir) click to toggle source
# File lib/rgw/big-list.rb, line 163
def on_scroll dir
    return if @data.nil?
    case dir
        when Gdk::EventScroll::Direction::UP
            return if @row == 0
            @row -= 1
            @scroll.adjustment.value = @row
            queue_draw
        when Gdk::EventScroll::Direction::DOWN
            return if @row + @numRows > @data.length
            @row += 1
            @scroll.adjustment.value = @row
            queue_draw
    end
end
on_scrollbar_change() click to toggle source
# File lib/rgw/big-list.rb, line 192
def on_scrollbar_change
    @row = @scroll.value.to_i
    queue_draw
end
queue_draw() click to toggle source
# File lib/rgw/big-list.rb, line 158
def queue_draw
    @area.queue_draw_area 0, 0, @area.allocation.width, @area.allocation.height
end
redraw() click to toggle source
# File lib/rgw/big-list.rb, line 228
def redraw
    return if self.window.nil?
    cc = Cairo::Context.new @backBuffer
    cc.antialias = :none
    cc.set_source_rgb 1.0, 1.0, 1.0
    cc.paint

    # draw the head
    unless @heads.nil?
        cc.set_source_rgb 0.9, 0.9, 0.9
        cc.rectangle 0, 0, @width, @headHeight
        cc.fill.stroke
        cc.antialias = :subpixel
        cc.set_source_rgb 0.0, 0.0, 0.0
        cc.font_size = @ccFontSize
        cc.select_font_face @ccFontFamily, :normal, :bold

        @heads.each_with_index do |head, col|
            cc.move_to @colsX[col] + 4, @rowHeight - 4
            cc.show_text head
            cc.stroke
        end
    end

    # draw the data
    unless @data.nil?
        colClips = []
        cellData = []
        (@row).upto(@row + @numRows - 1) do |row|
            break if row >= @data.length()
            textRow = @data[row]
            if textRow.is_a? Array
                cellData << textRow
            else
                cellData << textRow.split(@separator)
            end
        end

        0.upto(@numCols - 1) do |col|
            cc = Cairo::Context.new @backBuffer
            cc.antialias = :subpixel
            cc.set_source_rgb 0.0, 0.0, 0.0
            cc.font_size = @ccFontSize
            cc.select_font_face @ccFontFamily, :normal, :normal

            cc.rectangle @colsX[col], @headHeight, @colsX[col + 1] - @colsX[col], @height - @headHeight
            cc.clip
            cc.new_path
            0.upto(cellData.length() - 1) do |row|
                tok = cellData[row][col]
                next if tok.nil?
                cc.move_to @colsX[col] + 4, (row + 1) * @rowHeight - 4 + @headHeight
                cc.show_text tok
                cc.stroke
                cc.new_path
            end
        end
    end
    cc = Cairo::Context.new @backBuffer
    cc.antialias = :none
    cc.set_source_rgb 0.0, 0.0, 0.0
    cc.line_width = 1.0
    lg = @data.nil? ? 0 : @data.length()
    lg += 1 unless @heads.nil?

    # draw the vertical lines
    0.upto(@numCols - 1) do |col|
        x = @colsX[col]
        cc.move_to x, 0
        cc.line_to x, @height.min(lg * @rowHeight)
    end
    cc.stroke

    # draw the horizontal lines
    0.upto(@numRows.min(lg - 1)) do |row|
        y = @rowHeight * row + @headHeight
        cc.move_to 0, y
        cc.line_to @width, y
    end
    cc.stroke

    # copy backbuffer to the window
    cb = @area.window.create_cairo_context
    cb.set_source @backBuffer
    cb.paint
    false
end