use crate::{
datatype::CompositeValue,
element::{
AnimationTime, Color, Icon, ItemStyle, LabelAlign, LineStyle, Orient, Padding, TextStyle,
},
};
use charming_macros::CharmingSetters;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
#[serde(untagged)]
pub enum LegendConfig {
Single(Box<Legend>),
Multiple(Vec<Legend>),
}
impl From<Legend> for LegendConfig {
fn from(legend: Legend) -> Self {
Self::Single(Box::new(legend))
}
}
impl From<Vec<Legend>> for LegendConfig {
fn from(legends: Vec<Legend>) -> Self {
LegendConfig::Multiple(legends)
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Clone, Copy)]
#[serde(rename_all = "snake_case")]
pub enum LegendType {
Plain,
Scroll,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Clone, Copy)]
#[serde(rename_all = "snake_case")]
pub enum LegendSelectedMode {
Multiple,
Single,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, PartialOrd, Clone)]
#[serde(rename_all = "camelCase")]
pub struct LegendItem {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub icon: Option<Icon>,
}
impl From<&str> for LegendItem {
fn from(name: &str) -> Self {
Self {
name: name.to_string(),
icon: None,
}
}
}
impl From<String> for LegendItem {
fn from(name: String) -> Self {
Self { name, icon: None }
}
}
impl From<(&str, &str)> for LegendItem {
fn from((name, icon): (&str, &str)) -> Self {
Self {
name: name.to_string(),
icon: Some(icon.into()),
}
}
}
impl From<(String, String)> for LegendItem {
fn from((name, icon): (String, String)) -> Self {
Self {
name,
icon: Some(icon.into()),
}
}
}
#[serde_with::apply(
Option => #[serde(skip_serializing_if = "Option::is_none")],
Vec => #[serde(default, skip_serializing_if = "Vec::is_empty")]
)]
#[derive(Serialize, Deserialize, CharmingSetters, Debug, PartialEq, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Legend {
#[serde(rename = "type")]
type_: Option<LegendType>,
id: Option<String>,
show: Option<bool>,
zlevel: Option<f64>,
z: Option<f64>,
left: Option<CompositeValue>,
top: Option<CompositeValue>,
right: Option<CompositeValue>,
bottom: Option<CompositeValue>,
width: Option<CompositeValue>,
height: Option<CompositeValue>,
orient: Option<Orient>,
align: Option<LabelAlign>,
padding: Option<Padding>,
item_gap: Option<f64>,
item_width: Option<f64>,
item_height: Option<f64>,
item_style: Option<ItemStyle>,
line_style: Option<LineStyle>,
text_style: Option<TextStyle>,
symbol_rotate: Option<String>,
formatter: Option<String>,
#[charming_skip_setter]
selected: Option<BTreeMap<String, bool>>,
selected_mode: Option<LegendSelectedMode>,
border_color: Option<Color>,
inactive_color: Option<Color>,
#[charming_set_vec]
data: Vec<LegendItem>,
animation: Option<bool>,
animation_duration_update: Option<AnimationTime>,
}
impl Legend {
pub fn selected<S: Into<String>, I: IntoIterator<Item = (S, bool)>>(
mut self,
selected: I,
) -> Self {
self.selected = Some(selected.into_iter().map(|(k, v)| (k.into(), v)).collect());
self
}
}