Class: HexaPDF::Layout::TableBox::Cells
- Inherits:
-
Object
- Object
- HexaPDF::Layout::TableBox::Cells
- Defined in:
- lib/hexapdf/layout/table_box.rb
Overview
Represents the cells of a TableBox.
This class is a wrapper around an array of arrays and provides some utility methods for managing and styling the cells.
Table data transformation into correct form
One of the main purposes of this class is to transform the cell data provided on initialization into the representation a TableBox instance can work with.
The data
argument for ::new is an array of arrays representing the rows of the table. Each row array may contain one of the following items:
-
A single Box instance defining the content of the cell.
-
An array of Box instances defining the content of the cell.
-
A hash which defines the content of the cell as well as, optionally, additional information through the following keys:
:content
-
The content for the cell. This may be a single Box or an array of Box instances.
:row_span
-
An integer specifying the number of rows this cell should span.
:col_span
-
An integer specifying the number of columsn this cell should span.
:properties
-
A hash of properties (see Box#properties) to be set on the cell itself.
All other key-value pairs are taken to be cell styling information (like
:background_color
) and assigned to the cell style.
Additionally, the first item in the data
argument is treated specially if it is not an array:
-
If it is a hash, it is assumed to be style properties to be set on all created cell instances.
-
If it is a callable object, it needs to accept a cell as argument and is called for all created cell instances.
Any properties or styling information retrieved from the respective item in data
takes precedence over the above globally specified information.
Here is an example input data array:
data = [[box1, {col_span: 2, content: box2}, box3],
[box4, box5, {col_span: 2, row_span: 2, content: [box6.1, box6.2]}],
[box7, box8]]
And this is what the table will look like:
| box1 | box2 | box 3 |
| box4 | box5 | box6.1 box6.2 |
| box7 | box8 | |
Instance Method Summary collapse
-
#[](row, column) ⇒ Object
Returns the cell (a Cell instance) in the given row and column.
-
#draw_rows(start_row, end_row, canvas, x, y) ⇒ Object
Draws the rows from
start_row
toend_row
on the givencanvas
, with the top-left corner of the resulting table being at (x
,y
). -
#each_row(&block) ⇒ Object
Iterates over each row.
-
#fit_rows(start_row, available_height, column_info, frame) ⇒ Object
Fits all rows starting from
start_row
into an area with the givenavailable_height
, using the column information incolumn_info
. -
#initialize(data, cell_style: nil) ⇒ Cells
constructor
Creates a new Cells instance with the given
data
which cannot be changed afterwards. -
#number_of_columns ⇒ Object
Returns the number of columns.
-
#number_of_rows ⇒ Object
Returns the number of rows.
-
#style(**properties, &block) ⇒ Object
Applies the given style properties to all cells and optionally yields all cells for more complex customization.
Constructor Details
#initialize(data, cell_style: nil) ⇒ Cells
Creates a new Cells instance with the given data
which cannot be changed afterwards.
The optional cell_style
argument can either be a hash of style properties to be assigned to every cell or a block accepting a cell for more control over e.g. style assignment. If the data
has such a cell style as its first item, the cell_style
argument is not used.
See the class documentation for details on the data
argument.
332 333 334 335 336 |
# File 'lib/hexapdf/layout/table_box.rb', line 332 def initialize(data, cell_style: nil) @cells = [] @number_of_columns = 0 assign_data(data, cell_style) end |
Instance Method Details
#[](row, column) ⇒ Object
Returns the cell (a Cell instance) in the given row and column.
Note that the same cell instance may be returned for different (row, column) arguments if the cell spans more than one row and/or column.
342 343 344 |
# File 'lib/hexapdf/layout/table_box.rb', line 342 def [](row, column) @cells[row]&.[](column) end |
#draw_rows(start_row, end_row, canvas, x, y) ⇒ Object
Draws the rows from start_row
to end_row
on the given canvas
, with the top-left corner of the resulting table being at (x
, y
).
425 426 427 428 429 430 431 432 |
# File 'lib/hexapdf/layout/table_box.rb', line 425 def draw_rows(start_row, end_row, canvas, x, y) @cells[start_row..end_row].each.with_index(start_row) do |columns, row_index| columns.each_with_index do |cell, col_index| next if cell.row != row_index || cell.column != col_index cell.draw(canvas, x + cell.left, y - cell.top - cell.height) end end end |
#each_row(&block) ⇒ Object
Iterates over each row.
357 358 359 |
# File 'lib/hexapdf/layout/table_box.rb', line 357 def each_row(&block) @cells.each(&block) end |
#fit_rows(start_row, available_height, column_info, frame) ⇒ Object
Fits all rows starting from start_row
into an area with the given available_height
, using the column information in column_info
. Returns the used height as well as the row index of the last row that fit (which may be -1 if no row fits).
The column_info
argument needs to be an array of arrays of the form [x_pos, width] containing the horizontal positions and widths of each column.
The frame
argument is further handed down to the Cell instances for fitting.
The fitting of a cell is done through the Cell#fit method which stores the result in the cell itself. Furthermore, Cell#left and Cell#top are also assigned correctly.
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 |
# File 'lib/hexapdf/layout/table_box.rb', line 383 def fit_rows(start_row, available_height, column_info, frame) height = available_height last_fitted_row_index = -1 @cells[start_row..-1].each.with_index(start_row) do |columns, row_index| row_fit = true row_height = 0 columns.each_with_index do |cell, col_index| next if cell.row != row_index || cell.column != col_index available_cell_width = if cell.col_span > 1 column_info[cell.column, cell.col_span].map(&:last).sum else column_info[cell.column].last end unless cell.fit(available_cell_width, available_height, frame) row_fit = false break end cell.left = column_info[cell.column].first cell.top = height - available_height row_height = cell.preferred_height if row_height < cell.preferred_height end if row_fit seen = {} columns.each do |cell| next if seen[cell] cell.update_height(cell.row == row_index ? row_height : cell.height + row_height) seen[cell] = true end last_fitted_row_index = row_index available_height -= row_height else last_fitted_row_index = columns.min_by(&:row).row - 1 if height != available_height break end end [height - available_height, last_fitted_row_index] end |
#number_of_columns ⇒ Object
Returns the number of columns.
352 353 354 |
# File 'lib/hexapdf/layout/table_box.rb', line 352 def number_of_columns @number_of_columns end |
#number_of_rows ⇒ Object
Returns the number of rows.
347 348 349 |
# File 'lib/hexapdf/layout/table_box.rb', line 347 def number_of_rows @cells.size end |
#style(**properties, &block) ⇒ Object
Applies the given style properties to all cells and optionally yields all cells for more complex customization.
363 364 365 366 367 368 369 370 |
# File 'lib/hexapdf/layout/table_box.rb', line 363 def style(**properties, &block) @cells.each do |columns| columns.each do |cell| cell.style.update(**properties) block&.call(cell) end end end |