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.
The pie, without its legend, as a Drafter.Render.Picture at the left of rect, or
nil when the pie is not drawn as an image.
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 image_raster(t() | Drafter.Widget.props(), Drafter.Widget.rect()) :: Drafter.Render.Picture.t() | nil
The pie, without its legend, as a Drafter.Render.Picture at the left of rect, or
nil when the pie is not drawn as an image.
@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