class Rgw::BigList
Constants
- ROW_PADDING
Attributes
@return [Array] The complete data of the list as set by {#data=} or
nil if not.
@return [Array<String>, nil] The heads of the list if set by {#heads=}
or nil if not.
@return [Integer] The number of columns for the list as set by {#num_cols=}
@return [String] The separator to split data strings as set by {#separator=}
Public Class Methods
@param num_cols [Integer, nil] The number of columns the list sould have.
# 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
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
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
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
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
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
# 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
# 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
# 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
# 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
# File lib/rgw/big-list.rb, line 192 def on_scrollbar_change @row = @scroll.value.to_i queue_draw end
# File lib/rgw/big-list.rb, line 158 def queue_draw @area.queue_draw_area 0, 0, @area.allocation.width, @area.allocation.height end
# 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