# `Bsp.Layout`
[🔗](https://github.com/W3NDO/jigsaw/tree/main/apps/jigsaw/blob/main/lib/bsp/layout.ex#L1)

	This module allows for manipulation of the layout tree.

# `t`

```elixir
@type t() :: %{root: tree(), focused: String.t(), pane_ids: [String.t()]}
```

# `tree`

```elixir
@type tree() :: Bsp.Pane.t() | Bsp.Node.t()
```

# `children`

```elixir
@spec children(
  %Bsp.Layout{focused: term(), pane_ids: term(), root: term()},
  String.t()
) ::
  {:ok, [Bsp.Pane.t()]} | {:error, :node_not_found} | {:error, :no_children}
```

Returns a Node struct, or {:error, :node_not_found} or {:error, :no_children}.

# `close`

```elixir
@spec close(
  %Bsp.Layout{focused: term(), pane_ids: term(), root: term()},
  Types.Id.t()
) ::
  {:ok, %Bsp.Layout{focused: term(), pane_ids: term(), root: term()}}
  | {:error, :pane_not_found}
```

Takes in a layout and a `pane_id` to close. Returns a new layout with the pane with the specified `pane_id` removed from the tree.

# `find`

```elixir
@spec find(%Bsp.Layout{focused: term(), pane_ids: term(), root: term()}, Types.Id.t()) ::
  Bsp.Pane.t() | {:error, :pane_not_found}
```

Finds a pane with the specified `pane_id` in the tree. Returns a pane struct or `{:error, :pane_not_found}`

# `focus`

```elixir
@spec focus(
  %Bsp.Layout{focused: term(), pane_ids: term(), root: term()},
  Types.Id.t()
) ::
  {:ok, %Bsp.Layout{focused: term(), pane_ids: term(), root: term()}}
  | {:error, :pane_not_found}
```

# `focused`

```elixir
@spec focused(%Bsp.Layout{focused: term(), pane_ids: term(), root: term()}) ::
  {:ok, Types.Id.t()}
```

Returns `{:ok, pane_id}` with `pane_id` being the id of the pane in focus. Could also return nil if there are no panes.

# `focused!`

```elixir
@spec focused!(%Bsp.Layout{focused: term(), pane_ids: term(), root: term()}) ::
  Types.Id.t()
```

Returns `pane_id` in focus or nil.

# `focused?`

```elixir
@spec focused?(
  %Bsp.Layout{focused: term(), pane_ids: term(), root: term()},
  Types.Id.t()
) :: boolean()
```

Queries whether a pane is in focus or not. Returns a boolean or `{:error, :pane_not_found}` if the `pane_id` doesn't exist

# `insert`

```elixir
@spec insert(t(), Bsp.Pane.t()) :: t() | {:error, :invalid_layout}
```

Takes an empty layout and a pane and returns the layout with the pane.

## Examples

    iex> Bsp.Layout.insert(%Bsp.Layout{root: nil, focused: nil, pane_ids: []}, %Bsp.Pane{id: "temp"})
    %Bsp.Layout{root: %Bsp.Pane{id: "temp"}, focused: "temp", pane_ids: ["temp"]}

# `new`

```elixir
@spec new() :: %Bsp.Layout{focused: term(), pane_ids: term(), root: term()}
```

Creates a new empty layout

# `new`

```elixir
@spec new(Bsp.Pane.t()) :: %Bsp.Layout{
  focused: term(),
  pane_ids: term(),
  root: term()
}
```

Creates a new Layout with a single pane

# `panes`

```elixir
@spec panes(%Bsp.Layout{focused: term(), pane_ids: term(), root: term()}) :: [
  Types.Id.t()
]
```

Returns a list of pane_ids that exist in the layout tree

# `parent`

```elixir
@spec parent(
  %Bsp.Layout{focused: term(), pane_ids: term(), root: term()},
  Types.Id.t()
) ::
  {:ok, Bsp.Node.t()} | {:error, :pane_not_found} | {:error, :no_parent}
```

Returns a Node struct, or {:error, :pane_not_found} or {:error, :no_parent}.

# `split`

```elixir
@spec split(
  %Bsp.Layout{focused: term(), pane_ids: term(), root: term()},
  Types.Id.t(),
  Types.Id.t()
) ::
  {:ok, %Bsp.Layout{focused: term(), pane_ids: term(), root: term()}}
  | {:error, :pane_not_found}
  | {:error, :duplicate_pane_id}
```

Takes in a layout, a pane ID and a new pane ID to split it with. Returns an updated layout with the specified pane split into a node with 2 panes.

# `swap`

```elixir
@spec swap(
  %Bsp.Layout{focused: term(), pane_ids: term(), root: term()},
  Types.Id.t(),
  Types.Id.t()
) ::
  {:ok, %Bsp.Layout{focused: term(), pane_ids: term(), root: term()}}
  | {:error, :pane_not_found}
  | {:error, :swap_failed}
```

Swaps the positions of panes. For now you can only swap panes on the same node.

# `validate`

```elixir
@spec validate(%Bsp.Layout{focused: term(), pane_ids: term(), root: term()}) ::
  {:ok, :valid} | {:error, :invalid}
```

Validates the layout based on specified invariants on nodes, panes and other crucial elements

# `validate_node`

---

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