# `RasterExRatatui.Grid`
[🔗](https://github.com/mcass19/raster_ex_ratatui/blob/v0.4.0/lib/raster_ex_ratatui/grid.ex#L1)

The current frame of an `ExRatatui.CellSession`, as a cell map plus the list of pixel regions on screen.

A `CellSession` hands out a `%Snapshot{}` (every cell) or a `%Diff{}` (only the cells that changed since the last one). The grid folds either into a map keyed by `{col, row}` and reports what changed, which is what lets `RasterExRatatui.Raster` rasterise only those cells.

Regions are never merged: every payload carries the **complete** list of regions on screen (see `ExRatatui.CellSession.Region`), so the payload's list replaces the grid's outright.

## Examples

    iex> alias ExRatatui.CellSession.{Cell, Diff}
    iex> alias RasterExRatatui.Grid
    iex> full = %Diff{width: 2, height: 1, ops: [%Cell{col: 0, symbol: "a"}, %Cell{col: 1, symbol: "b"}]}
    iex> {grid, :all, false} = Grid.apply_diff(Grid.new(), full)
    iex> {grid, [{1, 0}], false} = Grid.apply_diff(grid, %Diff{width: 2, height: 1, ops: [%Cell{col: 1, symbol: "c"}]})
    iex> Grid.cell(grid, 1, 0).symbol
    "c"

# `changed`

```elixir
@type changed() :: :all | [{non_neg_integer(), non_neg_integer()}]
```

What changed: every cell, or the positions of the cells that did.

# `t`

```elixir
@type t() :: %RasterExRatatui.Grid{
  cells: %{
    required({non_neg_integer(), non_neg_integer()}) =&gt;
      ExRatatui.CellSession.Cell.t()
  },
  height: non_neg_integer(),
  regions: [ExRatatui.CellSession.Region.t()],
  width: non_neg_integer()
}
```

# `apply`

```elixir
@spec apply(t(), ExRatatui.CellSession.Snapshot.t() | ExRatatui.CellSession.Diff.t()) ::
  {t(), changed(), regions_changed? :: boolean()}
```

Folds a snapshot or a diff into the grid; see `put_snapshot/2` and `apply_diff/2`.

## Examples

    iex> alias ExRatatui.CellSession.Snapshot
    iex> {_grid, changed, _} = RasterExRatatui.Grid.apply(RasterExRatatui.Grid.new(), %Snapshot{width: 1, height: 1})
    iex> changed
    :all

# `apply_diff`

```elixir
@spec apply_diff(t(), ExRatatui.CellSession.Diff.t()) :: {t(), changed(), boolean()}
```

Merges a diff's cells into the grid and replaces its regions.

Returns `{grid, changed, regions_changed?}`. `changed` is `:all` for a full payload (every cell present, which a `CellSession` sends first, after a resize, and after a close) or when the diff's dimensions differ from the grid's; the cell map then starts over from the diff alone. Otherwise it lists the `{col, row}` of every op.

## Examples

    iex> alias ExRatatui.CellSession.{Cell, Diff, Region}
    iex> alias RasterExRatatui.Grid
    iex> {grid, :all, false} = Grid.apply_diff(Grid.new(), %Diff{width: 1, height: 1, ops: [%Cell{}]})
    iex> region = %Region{width: 1, height: 1, pixel_width: 1, pixel_height: 1, data: <<0, 0, 0>>}
    iex> {_grid, [], true} = Grid.apply_diff(grid, %Diff{width: 1, height: 1, regions: [region]})

# `cell`

```elixir
@spec cell(t(), non_neg_integer(), non_neg_integer()) ::
  ExRatatui.CellSession.Cell.t() | nil
```

The cell at `{col, row}`, or `nil` when no payload has set it.

## Examples

    iex> RasterExRatatui.Grid.cell(RasterExRatatui.Grid.new(), 0, 0)
    nil

# `new`

```elixir
@spec new() :: t()
```

An empty grid, 0×0 with no regions.

## Examples

    iex> RasterExRatatui.Grid.new()
    %RasterExRatatui.Grid{width: 0, height: 0, cells: %{}, regions: []}

# `put_snapshot`

```elixir
@spec put_snapshot(t(), ExRatatui.CellSession.Snapshot.t()) :: {t(), :all, boolean()}
```

Replaces the grid with a snapshot's cells and regions. Everything counts as changed.

Returns `{grid, :all, regions_changed?}`.

## Examples

    iex> alias ExRatatui.CellSession.{Cell, Snapshot}
    iex> snapshot = %Snapshot{width: 1, height: 1, cells: [%Cell{symbol: "x"}]}
    iex> {grid, :all, false} = RasterExRatatui.Grid.put_snapshot(RasterExRatatui.Grid.new(), snapshot)
    iex> RasterExRatatui.Grid.cell(grid, 0, 0).symbol
    "x"

---

*Consult [api-reference.md](api-reference.md) for complete listing*
