class Prawn::Table::Cells
Represents a selection of cells to be styled. Operations on a CellProxy can be chained, and cell properties can be set one-for-all on the proxy.
To set vertical borders only:
table.cells.borders = [:left, :right]
To highlight a rectangular area of the table:
table.rows(1..3).columns(2..4).background_color = 'ff0000'
Public Instance Methods
Retrieves a cell based on its 0-based row and column. Returns an individual Cell
, not a Cells
collection.
table.cells[0, 0].content # => "First cell content"
# File lib/prawn/table/cells.rb, line 109 def [](row, col) return nil if empty? index_cells unless defined?(@indexed) && @indexed row_array, col_array = @rows[@first_row + row] || [], @columns[@first_column + col] || [] if row_array.length < col_array.length row_array.find { |c| c.column == @first_column + col } else col_array.find { |c| c.row == @first_row + row } end end
Returns the number of columns in the list.
# File lib/prawn/table/cells.rb, line 90 def column_count index_cells unless defined?(@indexed) && @indexed @column_count end
Limits selection to the given column or columns. col_spec
can be anything that responds to the === operator selecting a set of 0-based column numbers; most commonly a number or a range.
table.column(0) # selects first column table.columns(3..4) # selects columns four and five
# File lib/prawn/table/cells.rb, line 79 def columns(col_spec) index_cells unless defined?(@indexed) && @indexed col_spec = transform_spec(col_spec, @first_column, @column_count) Cells.new(@columns[col_spec] ||= select { |c| col_spec.respond_to?(:include?) ? col_spec.include?(c.column) : col_spec === c.column }) end
Allows you to filter the given cells by arbitrary properties.
table.column(4).filter { |cell| cell.content =~ /Yes/ }. background_color = '00ff00'
# File lib/prawn/table/cells.rb, line 100 def filter(&block) Cells.new(select(&block)) end
# File lib/prawn/table/cells.rb, line 40 def fits_on_current_page?(offset, ref_bounds) # an empty row array means it definitely fits return true if self.empty? height_with_span < (self[0,0].y + offset) - ref_bounds.absolute_bottom end
Returns the total height of all rows in the selected set.
# File lib/prawn/table/cells.rb, line 180 def height aggregate_cell_values(:row, :height_ignoring_span, :max) end
Returns the total height of all rows in the selected set including spanned cells if the cell is the master cell
# File lib/prawn/table/cells.rb, line 187 def height_with_span aggregate_cell_values(:row, :height, :max) end
Returns maximum width that can contain cells in the set.
# File lib/prawn/table/cells.rb, line 174 def max_width aggregate_cell_values(:column, :max_width_ignoring_span, :max) end
Supports setting arbitrary properties on a group of cells.
table.cells.row(3..6).background_color = 'cc0000'
# File lib/prawn/table/cells.rb, line 195 def method_missing(id, *args, &block) if id.to_s =~ /=\z/ each { |c| c.send(id, *args, &block) if c.respond_to?(id) } else super end end
Returns minimum width required to contain cells in the set.
# File lib/prawn/table/cells.rb, line 168 def min_width aggregate_cell_values(:column, :avg_spanned_min_width, :max) end
Returns the number of rows in the list.
# File lib/prawn/table/cells.rb, line 67 def row_count index_cells unless defined?(@indexed) && @indexed @row_count end
Limits selection to the given row or rows. row_spec
can be anything that responds to the === operator selecting a set of 0-based row numbers; most commonly a number or a range.
table.row(0) # selects first row table.rows(3..4) # selects rows four and five
# File lib/prawn/table/cells.rb, line 56 def rows(row_spec) index_cells unless defined?(@indexed) && @indexed row_spec = transform_spec(row_spec, @first_row, @row_count) Cells.new(@rows[row_spec] ||= select { |c| row_spec.respond_to?(:include?) ? row_spec.include?(c.row) : row_spec === c.row }) end
Supports setting multiple properties at once.
table.cells.style(:padding => 0, :border_width => 2)
is the same as:
table.cells.padding = 0 table.cells.border_width = 2
You can also pass a block, which will be called for each cell in turn. This allows you to set more complicated properties:
table.cells.style { |cell| cell.border_width += 12 }
# File lib/prawn/table/cells.rb, line 153 def style(options={}, &block) each do |cell| next if cell.is_a?(Cell::SpanDummy) cell.style(options, &block) end end
Returns the total width of all columns in the selected set.
# File lib/prawn/table/cells.rb, line 162 def width ColumnWidthCalculator.new(self).natural_widths.inject(0, &:+) end
Protected Instance Methods
Sum up a min/max value over rows or columns in the cells selected. Takes the min/max (per aggregate
) of the result of sending meth
to each cell, grouped by row_or_column
.
# File lib/prawn/table/cells.rb, line 236 def aggregate_cell_values(row_or_column, meth, aggregate) ColumnWidthCalculator.new(self).aggregate_cell_values(row_or_column, meth, aggregate) end
Defers indexing until rows() or columns() is actually called on the Cells
object. Without this, we would needlessly index the leaf nodes of the object graph, the ones that are only there to be iterated over.
Make sure to call this before using @rows or @columns.
# File lib/prawn/table/cells.rb, line 211 def index_cells @rows = {} @columns = {} each do |cell| @rows[cell.row] ||= [] @rows[cell.row] << cell @columns[cell.column] ||= [] @columns[cell.column] << cell end @first_row = @rows.keys.min @first_column = @columns.keys.min @row_count = @rows.size @column_count = @columns.size @indexed = true end
Transforms spec
, a column / row specification, into an object that can be compared against a row or column number using ===. Normalizes negative indices to be positive, given a total size of total
. The first row/column is indicated by first
; this value is considered row or column 0.
# File lib/prawn/table/cells.rb, line 246 def transform_spec(spec, first, total) case spec when Range transform_spec(spec.begin, first, total) .. transform_spec(spec.end, first, total) when Integer spec < 0 ? (first + total + spec) : first + spec when Enumerable spec.map { |x| first + x } else # pass through raise "Don't understand spec #{spec.inspect}" end end