Class: Prawn::Table::ColumnWidthCalculator
- Inherits:
-
Object
- Object
- Prawn::Table::ColumnWidthCalculator
- Defined in:
- lib/prawn/table/column_width_calculator.rb
Instance Method Summary collapse
-
#aggregate_cell_values(row_or_column, meth, aggregate) ⇒ Object
get column widths (either min or max depending on meth) used in cells.rb.
-
#fill_values_if_needed(values, cell, index, meth) ⇒ Object
helper method column widths are stored in the values array a cell may span cells whose value is only partly given this function handles this special case.
-
#has_a_span_dummy?(row) ⇒ Boolean
does this row include a Cell:SpanDummy?.
-
#initialize(cells) ⇒ ColumnWidthCalculator
constructor
A new instance of ColumnWidthCalculator.
- #natural_widths ⇒ Object
Constructor Details
#initialize(cells) ⇒ ColumnWidthCalculator
Returns a new instance of ColumnWidthCalculator.
7 8 9 10 11 12 13 14 15 16 17 |
# File 'lib/prawn/table/column_width_calculator.rb', line 7 def initialize(cells) @cells = cells @widths_by_column = Hash.new(0) @rows_with_a_span_dummy = Hash.new(false) #calculate for each row if it includes a Cell:SpanDummy @cells.each do |cell| @rows_with_a_span_dummy[cell.row] = true if cell.is_a?(Cell::SpanDummy) end end |
Instance Method Details
#aggregate_cell_values(row_or_column, meth, aggregate) ⇒ Object
get column widths (either min or max depending on meth) used in cells.rb
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/prawn/table/column_width_calculator.rb', line 123 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 @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 @cells.each do |cell| index = cell.send(row_or_column) if cell.colspan > 1 #special treatment if some but not all spanned indices in the values array have been calculated #only applies to rows values = fill_values_if_needed(values, cell, index, meth) if row_or_column == :column #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 return values.values.inject(0, &:+) end |
#fill_values_if_needed(values, cell, index, meth) ⇒ Object
helper method column widths are stored in the values array a cell may span cells whose value is only partly given this function handles this special case
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/prawn/table/column_width_calculator.rb', line 37 def fill_values_if_needed(values, cell, index, meth) #have all spanned indices been filled with a value? #e.g. values[0], values[1] and values[2] don't return nil given a index of 0 and a colspan of 3 number_of_nil_values = 0 cell.colspan.times do |i| number_of_nil_values += 1 if values[index+i].nil? end #nothing to do? because #a) all values are filled return values if number_of_nil_values == 0 #b) no values are filled return values if number_of_nil_values == cell.colspan #c) I am not sure why this line is needed FIXXME #some test cases manage to this line even though there is no dummy cell in the row #I'm not sure if this is a sign for a further underlying bug. return values unless has_a_span_dummy?(cell.row) #fill up the values array #calculate the new sum new_sum = cell.send(meth) * cell.colspan #substract any calculated values cell.colspan.times do |i| new_sum -= values[index+i] unless values[index+i].nil? end #calculate value for the remaining - not yet filled - cells. new_value = new_sum.to_f / number_of_nil_values #fill the not yet filled cells cell.colspan.times do |i| values[index+i] = new_value if values[index+i].nil? end return values end |
#has_a_span_dummy?(row) ⇒ Boolean
does this row include a Cell:SpanDummy?
23 24 25 |
# File 'lib/prawn/table/column_width_calculator.rb', line 23 def has_a_span_dummy?(row) @rows_with_a_span_dummy[row] end |
#natural_widths ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/prawn/table/column_width_calculator.rb', line 72 def natural_widths #calculate natural column width for all rows that do not include a span dummy @cells.each do |cell| unless has_a_span_dummy?(cell.row) @widths_by_column[cell.column] = [@widths_by_column[cell.column], cell.width.to_f].max end end #integrate natural column widths for all rows that do include a span dummy @cells.each do |cell| next unless has_a_span_dummy?(cell.row) #the width of a SpanDummy cell will be calculated by the "mother" cell next if cell.is_a?(Cell::SpanDummy) if cell.colspan == 1 @widths_by_column[cell.column] = [@widths_by_column[cell.column], cell.width.to_f].max else #calculate the current with of all cells that will be spanned by the current cell current_width_of_spanned_cells = @widths_by_column.to_a[cell.column..(cell.column + cell.colspan - 1)] .collect{|key, value| value}.inject(0, :+) #update the Hash only if the new with is at least equal to the old one #due to arithmetic errors we need to ignore a small difference in the new and the old sum #the same had to be done in the column_widht_calculator#natural_width update_hash = ((cell.width.to_f - current_width_of_spanned_cells) > Prawn::FLOAT_PRECISION) if update_hash # Split the width of colspanned cells evenly by columns width_per_column = cell.width.to_f / cell.colspan # Update the Hash cell.colspan.times do |i| @widths_by_column[cell.column + i] = width_per_column end end end end @widths_by_column.sort_by { |col, _| col }.map { |_, w| w } end |