# `Drafter.Widget.Gauge`
[🔗](https://github.com/jaman/drafter/blob/main/lib/drafter/widget/gauge.ex#L1)

A semi-circular gauge chart rendered using Unicode braille characters.

The arc spans 260° (from ~8 o'clock to ~4 o'clock through the top). The
filled portion is coloured green below the low threshold, orange between
thresholds, and red above the high threshold. The unfilled track is rendered
in dim grey. The numeric percentage is displayed centred below the arc.

## Component tag

Tag `:gauge`, built by `Drafter.App` as `{:gauge, opts}`:

    gauge(opts)

There is no positional argument; every prop comes from `opts`.

## Options

  * `:value` - float in `0.0..1.0`. Default `0.0`. Shown as `round(value * 100)%`
  * `:label` - `t:String.t/0` title displayed on a row above the arc. Default
    `nil`, which reclaims that row for the arc
  * `:low_threshold` - fraction where the colour changes to `:mid_color`. Default
    `0.8`
  * `:high_threshold` - fraction where the colour changes to `:high_color`.
    Default `0.9`
  * `:low_color` - `{r, g, b}` for the low range. Default `{80, 200, 80}`
  * `:mid_color` - `{r, g, b}` for the mid range. Default `{220, 140, 0}`
  * `:high_color` - `{r, g, b}` for the high range. Default `{220, 60, 60}`
  * `:track_color` - `{r, g, b}` for the unfilled arc. Default `{55, 55, 55}`
  * `:renderer` - `:text` (default) draws braille cells; any terminal graphics
    protocol atom transmits the arc as an image, falling back to cells when
    that protocol is unavailable
  * `:height` - read only by `preferred_height/2`, never by `mount/1`. Default `5`

`update/2` re-reads only `:value`, `:label` and `:renderer`; the thresholds and
every colour are mount-only. Through the component tree a re-render narrows that
further to `:value` and `:label`, so `:renderer` is mount-only there too.

## Widget value

`Drafter.get_widget_value/1` is not implemented for this widget and returns `nil`.

## Data channel

When the widget is declared with a data buffer, `apply_data_buffer/3` sets
`:value` to the last item in the buffer and ignores everything before it.

## Usage

    gauge(value: 0.72)
    gauge(value: cpu_usage, label: "CPU", low_threshold: 0.6, high_threshold: 0.8)

# `rgb`

```elixir
@type rgb() :: {0..255, 0..255, 0..255}
```

# `t`

```elixir
@type t() :: %Drafter.Widget.Gauge{
  high_color: rgb(),
  high_threshold: float(),
  label: String.t() | nil,
  low_color: rgb(),
  low_threshold: float(),
  mid_color: rgb(),
  renderer: atom(),
  track_color: rgb(),
  value: float()
}
```

# `apply_data_buffer`

```elixir
@spec apply_data_buffer(t(), Drafter.RingBuffer.t(), Drafter.Widget.rect()) :: t()
```

Sets `:value` to the newest item in the widget's data buffer.

Everything buffered before the last item is discarded. An empty buffer leaves the
state alone.

# `component_tag`

```elixir
@spec component_tag() :: :gauge
```

The registry tag for this widget.

    iex> Drafter.Widget.Gauge.component_tag()
    :gauge

# `focused`

# `from_component_opts`

```elixir
@spec from_component_opts(
  term(),
  keyword()
) :: Drafter.Widget.props()
```

Turns the `{:gauge, opts}` element into a props map for `mount/1`. The positional
argument is ignored.

    iex> props = Drafter.Widget.Gauge.from_component_opts(nil, value: 0.5, label: "CPU")
    iex> {props.value, props.label, props.low_threshold, props.renderer}
    {0.5, "CPU", 0.8, :text}

# `handle_event`

```elixir
@spec handle_event(Drafter.Event.t(), t()) :: {:bubble, t()}
```

Bubbles every event; the gauge is not focusable and consumes no input.

    iex> g = Drafter.Widget.Gauge.mount(%{})
    iex> Drafter.Widget.Gauge.handle_event({:key, :enter}, g) |> elem(0)
    :bubble

# `image_active?`

```elixir
@spec image_active?(t()) :: boolean()
```

Whether this gauge is drawing a transmitted image rather than braille cells.

# `mount`

```elixir
@spec mount(Drafter.Widget.props()) :: t()
```

Builds the gauge state from `props`.

    iex> g = Drafter.Widget.Gauge.mount(%{value: 0.72, label: "CPU"})
    iex> {g.value, g.label, g.low_threshold, g.high_threshold, g.renderer}
    {0.72, "CPU", 0.8, 0.9, :text}

    iex> g = Drafter.Widget.Gauge.mount(%{})
    iex> {g.value, g.label, g.low_color, g.mid_color, g.high_color, g.track_color}
    {0.0, nil, {80, 200, 80}, {220, 140, 0}, {220, 60, 60}, {55, 55, 55}}

# `preferred_height`

```elixir
@spec preferred_height(
  term(),
  keyword()
) :: pos_integer()
```

`opts[:height]`, or `5` when it is absent.

    iex> Drafter.Widget.Gauge.preferred_height(nil, [])
    5

    iex> Drafter.Widget.Gauge.preferred_height(nil, height: 9)
    9

# `render`

```elixir
@spec render(t(), Drafter.Widget.rect()) :: [Drafter.Draw.Strip.t()]
```

Draws the gauge into `rect`, returning exactly `rect.height` strips.

With `renderer: :text`, or with a graphics protocol the terminal does not support,
the arc is drawn as braille cells and the percentage is overlaid on the row that
falls just below the arc's centre. Otherwise blank rows are emitted for the image
the widget server transmits separately, with the percentage on the last row. A
`:label` takes the first row in either case.

# `unmount`

# `update`

```elixir
@spec update(Drafter.Widget.props(), t()) :: t()
```

Folds fresh props into `state`, re-reading only `:value`, `:label` and
`:renderer`.

The thresholds and every colour keep the values they were mounted with, whatever
`props` contains.

    iex> g = Drafter.Widget.Gauge.mount(%{value: 0.1})
    iex> updated = Drafter.Widget.Gauge.update(%{value: 0.9, high_threshold: 0.5}, g)
    iex> {updated.value, updated.high_threshold}
    {0.9, 0.9}

# `update_props_from_mount`

```elixir
@spec update_props_from_mount(Drafter.Widget.props(), t(), keyword()) ::
  Drafter.Widget.props()
```

Narrows the props a re-render feeds to `update/2` to `:value` and `:label`, so
`:renderer`, the thresholds and the colours stay as mounted.

---

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