Renders a circular pie chart using Unicode block and braille characters.
Each slice is proportional to its value relative to the total. The chart uses quarter-block and half-block Unicode characters for sub-cell resolution rendering, and braille characters where finer detail is needed.
Component tag
Tag :pie_chart, built by Drafter.App as {:pie_chart, data, opts}:
pie_chart(data, opts)The positional argument becomes :data when it is a non-empty list that is not
a keyword list; otherwise :data is read from opts.
Options
:data-[{label, value} | {label, value, rgb}]. Default[]. A slice without an explicit colour takes the palette entry at its index, cycling. A total of zero gives every slice a percentage of0.0.:show_legend-boolean/0, draw labels down the right-hand side. Defaulttrue. The legend takesmin(longest_entry + 4, 30)columns and the pie takes the rest, with at least one column.:show_percentages-boolean/0, append(12.5%)to each legend label. Defaulttrue. Only read when the legend is drawn.:colors-[{r, g, b}]palette. Default[{100, 180, 255}, {255, 130, 80}, {100, 220, 140}, {220, 100, 220}, {255, 220, 80}, {120, 220, 220}, {255, 100, 100}, {180, 140, 255}].:renderer-:text(default) draws block and braille cells. Any other atom is treated as a terminal graphics protocol and passed toDrafter.Widget.Chart.Pixel, falling back to cells when that protocol is unavailable.:style-map/0of style overrides passed to the theme computation. Default%{}.:class- theme class atom or list of them, normalised byDrafter.Style.normalize_classes/1and reachingmount/1as:classes. Default[].:height-pos_integer/0read only bypreferred_height/2, never bymount/1. Default10.
Every option except :height is live-updatable: update_props_from_mount/3
passes the full mount props through.
Usage
pie_chart([{"Elixir", 45}, {"Rust", 30}, {"Go", 25}])
pie_chart([{"A", 60, {255, 100, 100}}, {"B", 40, {100, 100, 255}}])
pie_chart([{"X", 10}, {"Y", 20}], show_legend: false)
Summary
Functions
Replaces :data with a non-empty list of slice entries.
The component tag this widget registers under.
Builds the props map for a {:pie_chart, data, opts} element.
Ignores every event and returns {:bubble, state}, letting it continue to the
parent widget and then to the app.
Whether this pie chart is drawing a transmitted image rather than cells.
Builds the widget state from props.
The number of rows the element asks for: opts[:height], default 10.
Draws the chart into rect, always returning exactly rect.height strips.
Callback implementation for Drafter.Widget.unmount/1.
Replaces the state fields named in props, keeping the current value for any key
that is absent.
Passes the mount props through unchanged, so every option is live-updatable through the component tree.
Types
@type rgb() :: {0..255, 0..255, 0..255}
Functions
@spec apply_data_buffer(t(), [entry() | term()], Drafter.Widget.rect() | nil) :: t()
Replaces :data with a non-empty list of slice entries.
Unlike the other data-driven widgets this expects a plain list rather than a
Drafter.RingBuffer: {label, value} and {label, value, color} tuples pass
through, and anything else becomes {"", term}. An empty list or a value that is
not a list returns state unchanged.
iex> state = Drafter.Widget.PieChart.mount(%{})
iex> Drafter.Widget.PieChart.apply_data_buffer(state, [{"A", 1}, 7], nil).data
[{"A", 1}, {"", 7}]
iex> state = Drafter.Widget.PieChart.mount(%{data: [{"A", 1}]})
iex> Drafter.Widget.PieChart.apply_data_buffer(state, [], nil).data
[{"A", 1}]
@spec component_tag() :: :pie_chart
The component tag this widget registers under.
iex> Drafter.Widget.PieChart.component_tag()
:pie_chart
@spec from_component_opts( term(), keyword() ) :: Drafter.Widget.props()
Builds the props map for a {:pie_chart, data, opts} element.
data becomes :data when it is a non-empty list that is not a keyword list;
otherwise opts[:data] is used, defaulting to []. :class is normalised into
:classes and :__app_module__ becomes :app_module.
iex> props = Drafter.Widget.PieChart.from_component_opts([{"A", 1}], show_legend: false)
iex> {props.data, props.show_legend, props.renderer}
{[{"A", 1}], false, :text}
iex> Drafter.Widget.PieChart.from_component_opts(nil, data: [{"B", 2}]).data
[{"B", 2}]
@spec handle_event(Drafter.Event.t(), t()) :: {:bubble, t()}
Ignores every event and returns {:bubble, state}, letting it continue to the
parent widget and then to the app.
Whether this pie chart is drawing a transmitted image rather than cells.
@spec mount(Drafter.Widget.props()) :: t()
Builds the widget state from props.
Every option listed in the module doc is read here with the default stated there.
iex> state = Drafter.Widget.PieChart.mount(%{data: [{"A", 60}, {"B", 40}]})
iex> {state.data, state.show_legend, state.show_percentages, state.renderer}
{[{"A", 60}, {"B", 40}], true, true, :text}
iex> Drafter.Widget.PieChart.mount(%{}).colors |> length()
8
@spec preferred_height( term(), keyword() ) :: pos_integer()
The number of rows the element asks for: opts[:height], default 10.
iex> Drafter.Widget.PieChart.preferred_height(nil, [])
10
iex> Drafter.Widget.PieChart.preferred_height(nil, height: 20)
20
@spec render(t() | Drafter.Widget.props(), Drafter.Widget.rect()) :: [ Drafter.Draw.Strip.t() ]
Draws the chart into rect, always returning exactly rect.height strips.
state may be a plain props map, in which case it is passed through mount/1
first. Slices are laid out clockwise starting at twelve o'clock. This is the cell
renderer and is used whatever :renderer says; image/3 is the graphics path.
Callback implementation for Drafter.Widget.unmount/1.
@spec update(Drafter.Widget.props(), t()) :: t()
Replaces the state fields named in props, keeping the current value for any key
that is absent.
Accepts :data, :show_legend, :show_percentages, :colors, :style,
:classes, :app_module and :renderer.
iex> state = Drafter.Widget.PieChart.mount(%{data: [{"A", 1}]})
iex> updated = Drafter.Widget.PieChart.update(%{show_legend: false}, state)
iex> {updated.data, updated.show_legend}
{[{"A", 1}], false}
@spec update_props_from_mount(Drafter.Widget.props(), term(), keyword()) :: Drafter.Widget.props()
Passes the mount props through unchanged, so every option is live-updatable through the component tree.
iex> props = Drafter.Widget.PieChart.from_component_opts([{"A", 1}], [])
iex> Drafter.Widget.PieChart.update_props_from_mount(props, %{}, []) == props
true