1use super::{Box, Color, NIL_VALUE};
14use crate::Point;
15use serde::{Deserialize, Serialize};
16
17#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)]
18pub enum AxisScale {
19 #[default]
20 Linear,
21 Log(f32),
23}
24
25#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
26pub enum Position {
27 #[default]
28 Left,
29 Top,
30 Right,
31 Bottom,
32 Inside,
33}
34
35#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)]
36pub enum Align {
37 Left,
38 #[default]
39 Center,
40 Right,
41}
42
43#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
44pub enum Symbol {
45 None,
46 Circle(f32, Option<Color>),
48 Rect(f32, Option<Color>),
50 Triangle(f32, Option<Color>),
52 Diamond(f32, Option<Color>),
54}
55
56#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
57pub enum SeriesCategory {
58 Line,
59 Bar,
60}
61
62#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)]
63pub enum MarkLineCategory {
64 #[default]
65 Average,
66 Min,
67 Max,
68}
69
70#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)]
71pub enum MarkPointCategory {
72 #[default]
73 Min,
74 Max,
75}
76
77#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)]
78pub struct MarkLine {
79 pub category: MarkLineCategory,
80}
81
82#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)]
83pub struct MarkPoint {
84 pub category: MarkPointCategory,
85}
86
87#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)]
88pub struct Series {
89 pub name: String,
91 pub data: Vec<Option<f32>>,
93 pub start_index: usize,
95 pub index: Option<usize>,
97 pub y_axis_index: usize,
99 pub label_show: bool,
101 pub mark_lines: Vec<MarkLine>,
103 pub mark_points: Vec<MarkPoint>,
105 pub colors: Option<Vec<Option<Color>>>,
107 pub category: Option<SeriesCategory>,
109 pub stroke_dash_array: Option<String>,
111 pub stack: Option<String>,
113}
114
115#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
120pub struct AnimationConfig {
121 pub duration: u32,
123 pub easing: String,
125 pub delay: u32,
128}
129
130impl Default for AnimationConfig {
131 fn default() -> Self {
132 AnimationConfig {
133 duration: 1000,
134 easing: "ease".to_string(),
135 delay: 80,
136 }
137 }
138}
139
140#[derive(Clone, PartialEq, Debug, Default)]
141pub struct SeriesLabel {
142 pub point: Point,
143 pub text: String,
144}
145
146impl Series {
147 pub fn new(name: String, data: Vec<f32>) -> Self {
150 Series {
151 name,
152 data: data
153 .into_iter()
154 .map(|v| if v == NIL_VALUE { None } else { Some(v) })
155 .collect(),
156 index: None,
157 ..Default::default()
158 }
159 }
160 pub fn new_nullable(name: String, data: Vec<Option<f32>>) -> Self {
163 Series {
164 name,
165 data,
166 index: None,
167 ..Default::default()
168 }
169 }
170 pub(crate) fn data_values(&self) -> Vec<f32> {
174 self.data.iter().map(|v| v.unwrap_or(NIL_VALUE)).collect()
175 }
176}
177impl From<(&str, Vec<f32>)> for Series {
178 fn from(value: (&str, Vec<f32>)) -> Self {
179 Series::new(value.0.to_string(), value.1)
180 }
181}
182impl From<(&str, Vec<Option<f32>>)> for Series {
183 fn from(value: (&str, Vec<Option<f32>>)) -> Self {
184 Series::new_nullable(value.0.to_string(), value.1)
185 }
186}
187
188#[derive(Serialize, Deserialize, Clone, Debug, Default)]
189pub struct YAxisConfig {
190 pub axis_font_size: f32,
191 pub axis_font_color: Color,
192 pub axis_font_weight: Option<String>,
193 pub axis_stroke_color: Color,
194 pub axis_width: Option<f32>,
195 pub axis_split_number: usize,
196 pub axis_name_gap: f32,
197 pub axis_name_align: Option<Align>,
198 pub axis_margin: Option<Box>,
199 pub axis_formatter: Option<String>,
200 pub axis_min: Option<f32>,
201 pub axis_max: Option<f32>,
202 pub axis_scale: AxisScale,
203}
204
205#[derive(Clone, Copy, PartialEq, Debug)]
207pub enum Fill {
208 Solid(Color),
209 LinearGradient {
210 start_color: Color,
211 end_color: Color,
212 angle: f32,
214 },
215}
216
217impl Default for Fill {
218 fn default() -> Self {
219 Fill::Solid(Color::default())
220 }
221}
222
223impl From<Color> for Fill {
224 fn from(c: Color) -> Self {
225 Fill::Solid(c)
226 }
227}
228
229impl Fill {
230 pub fn is_transparent(&self) -> bool {
232 matches!(self, Fill::Solid(c) if c.is_transparent())
233 }
234}