perspective_viewer/config/number_series_style.rs
1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors. ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13use serde::{Deserialize, Serialize};
14use strum::{Display, EnumIter};
15use ts_rs::TS;
16
17/// Render glyph for a numeric aggregate in the Y Bar plugin. Serialized as
18/// a lowercase string to match the plugin's runtime lookup (which does a
19/// case-insensitive `chart_type` match against the same literal set).
20#[derive(
21 Clone, Copy, Debug, Default, Deserialize, Display, EnumIter, Eq, PartialEq, Serialize, TS,
22)]
23pub enum ChartType {
24 #[default]
25 #[serde(rename = "bar")]
26 Bar,
27
28 #[serde(rename = "line")]
29 Line,
30
31 #[serde(rename = "scatter")]
32 Scatter,
33
34 #[serde(rename = "area")]
35 Area,
36}
37
38impl ChartType {
39 pub fn is_default(&self) -> bool {
40 *self == Self::Bar
41 }
42
43 /// Glyphs for which `stack` is a meaningful option. Line/Scatter never
44 /// stack; Bar/Area stack by default but can be opted out per column.
45 pub fn supports_stack(&self) -> bool {
46 matches!(self, Self::Bar | Self::Area)
47 }
48}
49
50/// Per-column render-style config for numeric aggregates in series charts
51/// (currently Y Bar). Stored flat in the column's
52/// `serde_json::Map<String, serde_json::Value>`, so the JSON shape at the
53/// viewer boundary is `{ "chart_type": "line", "stack": false }`.
54///
55/// Default `Bar` + `None` stack serializes as an empty object so plugins
56/// that never touch these fields don't pay any JSON overhead.
57#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, TS)]
58pub struct NumberSeriesStyleConfig {
59 #[serde(default)]
60 #[serde(skip_serializing_if = "ChartType::is_default")]
61 pub chart_type: ChartType,
62
63 /// Stack override. `None` means "use the glyph default"
64 /// (Bar/Area stack, Line/Scatter don't). `Some(false)` on a Bar/Area
65 /// forces non-stacking.
66 #[serde(default)]
67 #[serde(skip_serializing_if = "Option::is_none")]
68 pub stack: Option<bool>,
69}
70
71/// Defaults-only shape carried by `ControlSpec::NumberSeriesStyle`. The
72/// presence of this control in a plugin's `column_config_schema` is the
73/// signal for the sidebar to render the chart-type picker.
74#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq)]
75pub struct NumberSeriesStyleDefaultConfig {
76 pub chart_type: ChartType,
77 #[serde(default)]
78 pub stack: Option<bool>,
79}