Class: HexaPDF::Layout::TableBox
- Defined in:
- lib/hexapdf/layout/table_box.rb
Overview
A TableBox allows placing boxes in a table.
A table box instance can be fit into a rectangular area. The widths of the columns is determined by the #column_widths definition. This means that there is no auto-sizing supported.
If some rows don’t fit into the provided area, the table is split. The style of the original table is also applied to the split box.
Table Cell
Each table cell is a Box instance and can have an associated style, e.g. for creating borders around the cell contents. It is also possible to create cells that span more than one row or column. By default a cell has a solid, black, 1pt border and a padding of 5pt on all sides.
It is important to note that the drawing of cell borders (just the drawing, size calculations are done as usual) are handled differently from standard box borders. While standard box borders are drawn inside the box, cell borders are drawn on the bounds of the box. This means that, visually, the borders of adjoining cells overlap, with the borders of cells to the right and bottom being on top.
To make sure that the cell borders are not outside of the table’s bounds, the left and top border widths of the top-left cell and the right and bottom border widths of the bottom-right cell are taken into account when calculating the available space.
Examples
Let’s start with a basic table:
#>pdf-composer
cells = [[layout.text('A'), layout.text('B')],
[layout.text('C'), layout.text('D')]]
composer.table(cells)
The HexaPDF::Document::Layout#table_box method accepts the cells as positional argument instead of as keyword argument but all other arguments of ::new work the same.
While the table box itself only allows box instances as cell contents, the layout helper method also allows text which it transforms to text boxes. So this is the same as the above:
#>pdf-composer
composer.table([['A', 'B'], ['C', 'D']])
Each cell can hold zero or more boxes:
#>pdf-composer
cells = [[[layout.text('A'), layout.image(machu_picchu, height: 40)], layout.text('B')],
[nil, layout.text('D')]]
composer.table(cells)
The style of the cells can be customized, e.g. to avoid drawing borders:
#>pdf-composer
cells = [[layout.text('A'), layout.text('B')],
[layout.text('C'), layout.text('D')]]
composer.table(cells, cell_style: {border: {width: 0}})
If the table doesn’t fit completely, it is automatically split (in this case, the last row gets moved to the second column):
#>pdf-composer
cells = [[layout.text('A'), layout.text('B')],
[layout.text('C'), layout.text('D')],
[layout.text('E'), layout.text('F')]]
composer.column(height: 50) {|col| col.table(cells) }
It is also possible to use row and column spans:
#>pdf-composer
cells = [[{content: layout.text('A'), col_span: 2}, {content: layout.text("B\nB\nB"), row_span: 2}],
[{content: layout.text('C'), col_span: 2, row_span: 2}],
[layout.text('D')]]
composer.table(cells)
Each table can have header rows and footer rows which are shown for all split parts:
#>pdf-composer
header = lambda {|tb| [[{content: layout.text('Header', text_align: :center), col_span: 2}]] }
= lambda {|tb| [[layout.text('left'), layout.text('right', text_align: :right)]] }
cells = [[layout.text('A'), layout.text('B')],
[layout.text('C'), layout.text('D')],
[layout.text('E'), layout.text('F')]]
composer.column(height: 90) {|col| col.table(cells, header: header, footer: ) }
The cells can be styled using a callable object for more complex styling:
#>pdf-composer
cells = [[layout.text('A'), layout.text('B')],
[layout.text('C'), layout.text('D')]]
block = lambda do |cell|
cell.style.background_color =
(cell.row == 0 && cell.column == 0 ? 'ffffaa' : 'ffffee')
end
composer.table(cells, cell_style: block)
Defined Under Namespace
Constant Summary
Constants included from Utils
Instance Attribute Summary collapse
-
#cells ⇒ Object
readonly
The Cells instance containing the data of the table.
-
#column_widths ⇒ Object
readonly
The column widths definition.
-
#footer_cells ⇒ Object
readonly
The Cells instance containing the footer cells of the table.
-
#header_cells ⇒ Object
readonly
The Cells instance containing the header cells of the table.
-
#last_fitted_row_index ⇒ Object
readonly
This value is -1 if #fit was not yet called.
-
#start_row_index ⇒ Object
readonly
The row index into the #cells from which this instance starts fitting the rows.
Attributes inherited from Box
#fit_result, #height, #properties, #style, #width
Instance Method Summary collapse
-
#empty? ⇒ Boolean
Returns
true
if not a single row could be fit. -
#initialize(cells:, column_widths: nil, header: nil, footer: nil, cell_style: nil, **kwargs) ⇒ TableBox
constructor
Creates a new TableBox instance.
Methods inherited from Box
#content_height, #content_width, create, #draw, #fit, #split, #split_box?, #supports_position_flow?
Constructor Details
#initialize(cells:, column_widths: nil, header: nil, footer: nil, cell_style: nil, **kwargs) ⇒ TableBox
Creates a new TableBox instance.
cells
-
This needs to be an array of arrays containing the data of the table. See Cells for more information on the allowed contents.
Alternatively, a Cells instance can be used. Note that in this case the
cell_style
argument is not used. column_widths
-
An array defining the width of the columns of the table. If not set, defaults to an empty array.
Each entry in the array may either be a positive or negative number. A positive number sets a fixed width for the respective column.
A negative number specifies that the respective column is auto-sized. Such columns split the remaining width (after substracting the widths of the fixed columns) proportionally among them. For example, if the column width definition is [-1, -2, -2], the first column is a fifth of the width and the other two columns are each two fifth of the width.
If the
cells
definition has more columns than specified bycolumn_widths
, the missing entries are assumed to be -1. header
-
A callable object that needs to accept this TableBox instance as argument and that returns an array of arrays containing the header rows.
The header rows are shown for the table instance and all split boxes.
footer
-
A callable object that needs to accept this TableBox instance as argument and that returns an array of arrays containing the footer rows.
The footer rows are shown for the table instance and all split boxes.
cell_style
-
Contains styling information that should be applied to all header, body and footer cells.
This can either be a hash containing style properties or a callable object accepting a cell as argument.
627 628 629 630 631 632 633 634 635 636 637 638 |
# File 'lib/hexapdf/layout/table_box.rb', line 627 def initialize(cells:, column_widths: nil, header: nil, footer: nil, cell_style: nil, **kwargs) super(**kwargs) @cell_style = cell_style @cells = cells.kind_of?(Cells) ? cells : Cells.new(cells, cell_style: @cell_style) @column_widths = column_widths || [] @start_row_index = 0 @last_fitted_row_index = -1 @header = header @header_cells = Cells.new(header.call(self), cell_style: @cell_style) if header @footer = @footer_cells = Cells.new(.call(self), cell_style: @cell_style) if end |
Instance Attribute Details
#cells ⇒ Object (readonly)
The Cells instance containing the data of the table.
If this is an instance that was split from another one, the cells contain all the rows, not just the ones for this split instance.
Also see #start_row_index.
550 551 552 |
# File 'lib/hexapdf/layout/table_box.rb', line 550 def cells @cells end |
#column_widths ⇒ Object (readonly)
The column widths definition.
See ::new for details.
567 568 569 |
# File 'lib/hexapdf/layout/table_box.rb', line 567 def column_widths @column_widths end |
#footer_cells ⇒ Object (readonly)
The Cells instance containing the footer cells of the table.
If this is a TableBox instance that was split from another one, the footer cells are created again through the use of footer
block supplied to ::new.
562 563 564 |
# File 'lib/hexapdf/layout/table_box.rb', line 562 def @footer_cells end |
#header_cells ⇒ Object (readonly)
The Cells instance containing the header cells of the table.
If this is a TableBox instance that was split from another one, the header cells are created again through the use of header
block supplied to ::new.
556 557 558 |
# File 'lib/hexapdf/layout/table_box.rb', line 556 def header_cells @header_cells end |
#last_fitted_row_index ⇒ Object (readonly)
This value is -1 if #fit was not yet called. Otherwise it contains the row index of the last row that could be fitted.
577 578 579 |
# File 'lib/hexapdf/layout/table_box.rb', line 577 def last_fitted_row_index @last_fitted_row_index end |
#start_row_index ⇒ Object (readonly)
The row index into the #cells from which this instance starts fitting the rows.
This value is 0 if this instance was not split from another one. Otherwise, it contains the correct start index.
573 574 575 |
# File 'lib/hexapdf/layout/table_box.rb', line 573 def start_row_index @start_row_index end |
Instance Method Details
#empty? ⇒ Boolean
Returns true
if not a single row could be fit.
641 642 643 |
# File 'lib/hexapdf/layout/table_box.rb', line 641 def empty? super && (!@last_fitted_row_index || @last_fitted_row_index < 0) end |