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'
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 100 def [](row, col) return nil if empty? index_cells unless @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 81 def column_count index_cells unless @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 70 def columns(col_spec) index_cells unless @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 91 def filter(&block) Cells.new(select(&block)) 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 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, :min) 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 188 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 58 def row_count index_cells unless @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 47 def rows(row_spec) index_cells unless @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 144 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 153 def width widths = {} each do |cell| index = cell.column per_cell_width = cell.width_ignoring_span.to_f / cell.colspan cell.colspan.times do |n| widths[cell.column+n] = [widths[cell.column+n], per_cell_width]. compact.max end end widths.values.inject(0, &:+) end
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 229 def aggregate_cell_values(row_or_column, meth, aggregate) values = {} each do |cell| index = cell.send(row_or_column) values[index] = [values[index], cell.send(meth)].compact.send(aggregate) end values.values.inject(0, &:+) 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 204 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 244 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