Skip to content

Commit

Permalink
Allow custom cell_fill_mode in tables
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucas-C committed Feb 20, 2024
1 parent 1bd4548 commit 7265cd1
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',

## [2.7.9] - Not released yet
### Added
* allow to define custom `cell_fill_mode` logic for tables: [_Set cells background_ - documentation section](https://py-pdf.github.io/fpdf2/Tables.html#set-cells-background)

### Fixed

Expand Down Expand Up @@ -47,7 +48,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
* outer table borders are now drawn continuously for nonzero `gutter_width`/`gutter_height`, with spacing applied inside the border similar to HTML tables - thanks to @mjasperse - cf. [#1071](https://github.com/py-pdf/fpdf2/issues/1071)
* removed the requirement that all rows in a `Table` have the same number of columns - thanks to @mjasperse
### Deprecated
- font aliases (`Arial``Helvetica`, `CourierNew``Courer`, `TimesNewRoman``Times`). They will be removed in a later release.
- font aliases (`Arial``Helvetica`, `CourierNew``Courier`, `TimesNewRoman``Times`). They will be removed in a later release.

## [2.7.7] - 2023-12-10
### Added
Expand Down
12 changes: 12 additions & 0 deletions docs/Tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,18 @@ The cell color is set following those settings, ordered by priority:
4. The table setting `cell_fill_color`, if `cell_fill_mode` indicates to fill a cell
5. The document `.fill_color` set before rendering the table

Finally, it is possible to define your own cell-filling logic:

```python
class EvenOddCellFillMode():
def should_fill_cell(self, i, j):
return i % 2 and j % 2

...
with pdf.table(cell_fill_color=lightblue, cell_fill_mode=EvenOddCellFillMode()) as table:
...
```


## Set borders layout

Expand Down
9 changes: 8 additions & 1 deletion fpdf/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def coerce(cls, value):

raise ValueError(f"{value} is not a valid {cls.__name__}")

raise TypeError(f"{value} cannot convert to a {cls.__name__}")
raise TypeError(f"{value} cannot be converted to a {cls.__name__}")


class CoerciveIntEnum(IntEnum):
Expand Down Expand Up @@ -314,6 +314,13 @@ class TableCellFillMode(CoerciveEnum):
COLUMNS = intern("COLUMNS")
"Fill only table cells in odd columns"

@classmethod
def coerce(cls, value):
"Any class that has a .should_fill_cell() method is considered a valid 'TableCellFillMode' (duck-typing)"
if callable(getattr(value, "should_fill_cell", None)):
return value
return super().coerce(value)

def should_fill_cell(self, i, j):
if self is self.NONE:
return False
Expand Down
Binary file added test/table/table_with_cell_fill_custom_class.pdf
Binary file not shown.
18 changes: 18 additions & 0 deletions test/table/test_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,24 @@ def test_table_with_cell_fill(tmp_path):
assert_pdf_equal(pdf, HERE / "table_with_cell_fill.pdf", tmp_path)


class EvenOddCellFillMode():
def should_fill_cell(self, i, j):
return i % 2 and j % 2


def test_table_with_cell_fill_custom_class(tmp_path):
pdf = FPDF()
pdf.add_page()
pdf.set_font("Times", size=16)
lightblue = (173, 216, 230)
with pdf.table(cell_fill_color=lightblue, cell_fill_mode=EvenOddCellFillMode()) as table:
for data_row in TABLE_DATA:
row = table.row()
for datum in data_row:
row.cell(datum)
assert_pdf_equal(pdf, HERE / "table_with_cell_fill_custom_class.pdf", tmp_path, generate=True)


def test_table_with_internal_layout(tmp_path):
pdf = FPDF()
pdf.add_page()
Expand Down

0 comments on commit 7265cd1

Please sign in to comment.