# Grid¶

A grid of cells.

Example of grid:

```.. doctest:: grid_demo
```
```>>> from benker.grid import Grid
>>> from benker.cell import Cell
```
```>>> grid = Grid()
>>> grid[1, 1] = Cell("red", height=2)
>>> grid[2, 1] = Cell("pink", width=2)
>>> grid[2, 2] = Cell("blue")
```
```>>> print(grid)
+-----------+-----------------------+
|    red    |   pink                |
|           +-----------+-----------+
|           |   blue    |           |
+-----------+-----------+-----------+
```

You can retrieve the grid cells as follow:

```>>> from benker.grid import Grid
>>> from benker.cell import Cell

>>> grid = Grid()
>>> grid[1, 1] = Cell("red", height=2)
>>> grid[2, 1] = Cell("pink", width=2)
>>> grid[2, 2] = Cell("blue")

>>> grid[1, 1]
<Cell('red', styles={}, nature=None, x=1, y=1, width=1, height=2)>
>>> grid[2, 1]
<Cell('pink', styles={}, nature=None, x=2, y=1, width=2, height=1)>
>>> grid[2, 2]
<Cell('blue', styles={}, nature=None, x=2, y=2, width=1, height=1)>
>>> grid[3, 3]
Traceback (most recent call last):
...
KeyError: Coord(x=3, y=3)
```

A grid has a bounding box, useful to get the grid sizes:

```>>> from benker.grid import Grid
>>> from benker.cell import Cell

>>> grid = Grid()
>>> grid[1, 1] = Cell("red", height=2)
>>> grid[2, 1] = Cell("pink", width=2)
>>> grid[2, 2] = Cell("blue")

>>> grid.bounding_box
Box(min=Coord(x=1, y=1), max=Coord(x=3, y=2))
>>> grid.bounding_box.size
Size(width=3, height=2)
```

You can expand the cell size horizontally or vertically:

```>>> from benker.grid import Grid
>>> from benker.cell import Cell

>>> grid = Grid()
>>> grid[1, 1] = Cell("red", height=2)
>>> grid[2, 1] = Cell("pink", width=2)
>>> grid[2, 2] = Cell("blue")

>>> grid.expand((2, 2), width=1)
<Cell('blue', styles={}, nature=None, x=2, y=2, width=2, height=1)>
>>> print(grid)
+-----------+-----------------------+
|    red    |   pink                |
|           +-----------------------+
|           |   blue                |
+-----------+-----------------------+
```

The content of the merged cells is merged too:

```>>> from benker.grid import Grid
>>> from benker.cell import Cell

>>> grid = Grid()
>>> grid[1, 1] = Cell("red", height=2)
>>> grid[2, 1] = Cell("pink", width=2)
>>> grid[2, 2] = Cell("blue", width=2)

>>> grid.merge((2, 1), (3, 2), content_appender=lambda a, b: "/".join([a, b]))
<Cell('pink/blue', styles={}, nature=None, x=2, y=1, width=2, height=2)>
>>> print(grid)
+-----------+-----------------------+
|    red    | pink/blue             |
|           |                       |
|           |                       |
+-----------+-----------------------+
```
class benker.grid.Grid(cells=None)

Collection of `Cell` objects ordered in a grid of rows and columns.

property bounding_box

Bounding box of the grid (`None` if the grid is empty).

expand(coord, width=0, height=0, content_appender=None)

Expand (or shrink) the width and/or height of a cell, using the content_appender to append cell contents.

See also the method `merge()` to merge a group of cells contained in a bounding box.

Parameters
• coord – Coordinates of the cell to expand (or shrink).

• width – Number of columns to add to the cell width.

• height – Number of rows to add to the cell height.

• content_appender – Function to use to append the cell contents. The function must have the following signature: `f(a, b) -> c`, where a, b anc c must be of the same type than the cell content. If not provided, the default function is `operator.__add__()`.

Returns

The merged cell.

Raises

ValueError – If the group of cells is empty or if cells cannot be merged.

iter_rows()

Iterate the cells grouped by rows.

merge(start, end, content_appender=None)

Merge a group of cells contained in a bounding box, using the content_appender to append cell contents.

The coordinates start and end delimit a group of cells to merge.

Warning

All the cells of the group must be included in the group bounding box, no intersection is allowed. If not, `ValueError` is raised.

See also the method `expand()` to expand (or shrink) the width and/or height of a cell.

Parameters
• start (Coord or tuple[int, int]) – Top-left coordinates of the group of cells to merge.

• end – Bottom-right coordinates of the group of cells to merge (inclusive).

• content_appender – Function to use to append the cell contents. The function must have the following signature: `f(a, b) -> c`, where a, b anc c must be of the same type than the cell content. If not provided, the default function is `operator.__add__()`.

Returns

The merged cell.

Raises

ValueError – If the group of cells is empty or if cells cannot be merged.