Parent

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

[](row, col) click to toggle source

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 101
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
column(col_spec) click to toggle source
Alias for: columns
column_count() click to toggle source

Returns the number of columns in the list.

# File lib/prawn/table/cells.rb, line 82
def column_count
  index_cells unless defined?(@indexed) && @indexed
  @column_count
end
columns(col_spec) click to toggle source

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 71
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
Also aliased as: column
filter(&block) click to toggle source

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 92
def filter(&block)
  Cells.new(select(&block))
end
height() click to toggle source

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
max_width() click to toggle source

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
method_missing(id, *args, &block) click to toggle source

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
min_width() click to toggle source

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
row(row_spec) click to toggle source
Alias for: rows
row_count() click to toggle source

Returns the number of rows in the list.

# File lib/prawn/table/cells.rb, line 59
def row_count
  index_cells unless defined?(@indexed) && @indexed
  @row_count
end
rows(row_spec) click to toggle source

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 48
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
Also aliased as: row
style(options={}, &block) click to toggle source

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 145
def style(options={}, &block)
  each do |cell|
    next if cell.is_a?(Cell::SpanDummy)
    cell.style(options, &block)
  end
end
width() click to toggle source

Returns the total width of all columns in the selected set.

# File lib/prawn/table/cells.rb, line 154
def width
  widths = {}
  each do |cell|
    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

Protected Instance Methods

aggregate_cell_values(row_or_column, meth, aggregate) click to toggle source

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 = {}

  #calculate values for all cells that do not span accross multiple cells
  #this ensures that we don't have a problem if the first line includes
  #a cell that spans across multiple cells
  each do |cell|
    #don't take spanned cells
    if cell.colspan == 1 and cell.class != Prawn::Table::Cell::SpanDummy
      index = cell.send(row_or_column)
      values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
    end
  end

  #if there are only colspanned or rowspanned cells in a table
  spanned_width_needs_fixing = true

  each do |cell|
    index = cell.send(row_or_column)
    if cell.colspan > 1
      #calculate current (old) return value before we do anything
      old_sum = 0
      cell.colspan.times { |i|
        old_sum += values[index+i] unless values[index+i].nil?
      }

      #calculate future return value
      new_sum = cell.send(meth) * cell.colspan

      #due to float rounding errors we need to ignore a small difference in the new 
      #and the old sum the same had to be done in
      #the column_width_calculator#natural_width
      spanned_width_needs_fixing = ((new_sum - old_sum) > Prawn::FLOAT_PRECISION)

      if spanned_width_needs_fixing
        #not entirely sure why we need this line, but with it the tests pass
        values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
        #overwrite the old values with the new ones, but only if all entries existed
        entries_exist = true
        cell.colspan.times { |i| entries_exist = false if values[index+i].nil? }
        cell.colspan.times { |i|
          values[index+i] = cell.send(meth) if entries_exist
        }
      end
    else
      if spanned_width_needs_fixing && cell.class == Prawn::Table::Cell::SpanDummy
        values[index] = [values[index], cell.send(meth)].compact.send(aggregate)
      end
    end
  end
  values.values.inject(0, &:+)
end
index_cells() click to toggle source

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
transform_spec(spec, first, total) click to toggle source

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 288
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

[Validate]

Generated with the Darkfish Rdoc Generator 2.