charming_fork_zephyr/component/
legend.rs

1use serde::Serialize;
2
3use crate::{
4    datatype::CompositeValue,
5    element::{Color, Icon, ItemStyle, LabelAlign, LineStyle, Orient, Padding, TextStyle},
6};
7
8#[derive(Serialize)]
9#[serde(rename_all = "snake_case")]
10pub enum LegendType {
11    /// Simple legend.
12    Plain,
13
14    /// Scrollable legend.
15    Scroll,
16}
17
18#[derive(Serialize)]
19#[serde(rename_all = "snake_case")]
20pub enum LegendSelectedMode {
21    /// Multiple selection.
22    Multiple,
23
24    /// Single selection.
25    Single,
26}
27
28#[derive(Serialize)]
29#[serde(rename_all = "camelCase")]
30pub struct LegendItem {
31    pub name: String,
32
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub icon: Option<Icon>,
35}
36
37impl From<&str> for LegendItem {
38    fn from(name: &str) -> Self {
39        Self {
40            name: name.to_string(),
41            icon: None,
42        }
43    }
44}
45
46impl From<String> for LegendItem {
47    fn from(name: String) -> Self {
48        Self { name, icon: None }
49    }
50}
51
52impl From<(&str, &str)> for LegendItem {
53    fn from((name, icon): (&str, &str)) -> Self {
54        Self {
55            name: name.to_string(),
56            icon: Some(icon.into()),
57        }
58    }
59}
60
61impl From<(String, String)> for LegendItem {
62    fn from((name, icon): (String, String)) -> Self {
63        Self {
64            name,
65            icon: Some(icon.into()),
66        }
67    }
68}
69
70#[derive(Serialize)]
71#[serde(rename_all = "camelCase")]
72pub struct Legend {
73    /// Type of legend.
74    #[serde(skip_serializing_if = "Option::is_none")]
75    #[serde(rename = "type")]
76    type_: Option<LegendType>,
77
78    /// Component ID.
79    #[serde(skip_serializing_if = "Option::is_none")]
80    id: Option<String>,
81
82    /// Whether to show the legend component.
83    #[serde(skip_serializing_if = "Option::is_none")]
84    show: Option<bool>,
85
86    /// The `zlevel` value of all graphical elements in.
87    #[serde(skip_serializing_if = "Option::is_none")]
88    zlevel: Option<i64>,
89
90    /// The `z` value of all graphical elements in.
91    #[serde(skip_serializing_if = "Option::is_none")]
92    z: Option<i64>,
93
94    /// Distance between title component and the left side of the container.
95    #[serde(skip_serializing_if = "Option::is_none")]
96    left: Option<CompositeValue>,
97
98    /// Distance between title component and the top side of the container.
99    #[serde(skip_serializing_if = "Option::is_none")]
100    top: Option<CompositeValue>,
101
102    /// Distance between title component and the right side of the container.
103    #[serde(skip_serializing_if = "Option::is_none")]
104    right: Option<CompositeValue>,
105
106    /// Distance between title component and the bottom side of the container.
107    #[serde(skip_serializing_if = "Option::is_none")]
108    bottom: Option<CompositeValue>,
109
110    /// Width of legend component.
111    #[serde(skip_serializing_if = "Option::is_none")]
112    width: Option<CompositeValue>,
113
114    /// Height of legend component.
115    #[serde(skip_serializing_if = "Option::is_none")]
116    height: Option<CompositeValue>,
117
118    /// The layout orientation of legend.
119    #[serde(skip_serializing_if = "Option::is_none")]
120    orient: Option<Orient>,
121
122    /// The align of legend.
123    #[serde(skip_serializing_if = "Option::is_none")]
124    align: Option<LabelAlign>,
125
126    /// Legend padding.
127    #[serde(skip_serializing_if = "Option::is_none")]
128    padding: Option<Padding>,
129
130    /// The gap between each legend.
131    #[serde(skip_serializing_if = "Option::is_none")]
132    item_gap: Option<i64>,
133
134    /// Width of legend symbol.
135    #[serde(skip_serializing_if = "Option::is_none")]
136    item_width: Option<i64>,
137
138    /// Height of legend symbol.
139    #[serde(skip_serializing_if = "Option::is_none")]
140    item_height: Option<i64>,
141
142    /// Legend item style.
143    #[serde(skip_serializing_if = "Option::is_none")]
144    item_style: Option<ItemStyle>,
145
146    /// Legend line style.
147    #[serde(skip_serializing_if = "Option::is_none")]
148    line_style: Option<LineStyle>,
149
150    #[serde(skip_serializing_if = "Option::is_none")]
151    text_style: Option<TextStyle>,
152
153    /// Rotation of the symbol.
154    #[serde(skip_serializing_if = "Option::is_none")]
155    symbol_rotate: Option<String>,
156
157    /// Formatter is used to format label of legend.
158    #[serde(skip_serializing_if = "Option::is_none")]
159    formatter: Option<String>,
160
161    #[serde(skip_serializing_if = "Option::is_none")]
162    selected_mode: Option<LegendSelectedMode>,
163
164    #[serde(skip_serializing_if = "Option::is_none")]
165    border_color: Option<Color>,
166
167    #[serde(skip_serializing_if = "Option::is_none")]
168    inactive_color: Option<Color>,
169
170    #[serde(skip_serializing_if = "Vec::is_empty")]
171    data: Vec<LegendItem>,
172}
173
174impl Legend {
175    pub fn new() -> Self {
176        Self {
177            type_: None,
178            id: None,
179            show: None,
180            zlevel: None,
181            z: None,
182            left: None,
183            top: None,
184            right: None,
185            bottom: None,
186            width: None,
187            height: None,
188            orient: None,
189            align: None,
190            padding: None,
191            item_gap: None,
192            item_width: None,
193            item_height: None,
194            item_style: None,
195            line_style: None,
196            text_style: None,
197            symbol_rotate: None,
198            formatter: None,
199            selected_mode: None,
200            border_color: None,
201            inactive_color: None,
202            data: vec![],
203        }
204    }
205
206    pub fn type_<T: Into<LegendType>>(mut self, type_: T) -> Self {
207        self.type_ = Some(type_.into());
208        self
209    }
210
211    pub fn show(mut self, show: bool) -> Self {
212        self.show = Some(show);
213        self
214    }
215
216    pub fn zlevel<F: Into<i64>>(mut self, zlevel: F) -> Self {
217        self.zlevel = Some(zlevel.into());
218        self
219    }
220
221    pub fn z<F: Into<i64>>(mut self, z: F) -> Self {
222        self.z = Some(z.into());
223        self
224    }
225
226    pub fn left<C: Into<CompositeValue>>(mut self, left: C) -> Self {
227        self.left = Some(left.into());
228        self
229    }
230
231    pub fn top<C: Into<CompositeValue>>(mut self, top: C) -> Self {
232        self.top = Some(top.into());
233        self
234    }
235
236    pub fn right<C: Into<CompositeValue>>(mut self, right: C) -> Self {
237        self.right = Some(right.into());
238        self
239    }
240
241    pub fn bottom<C: Into<CompositeValue>>(mut self, bottom: C) -> Self {
242        self.bottom = Some(bottom.into());
243        self
244    }
245
246    pub fn width<C: Into<CompositeValue>>(mut self, width: C) -> Self {
247        self.width = Some(width.into());
248        self
249    }
250
251    pub fn height<C: Into<CompositeValue>>(mut self, height: C) -> Self {
252        self.height = Some(height.into());
253        self
254    }
255
256    pub fn orient<O: Into<Orient>>(mut self, orient: O) -> Self {
257        self.orient = Some(orient.into());
258        self
259    }
260
261    pub fn align<A: Into<LabelAlign>>(mut self, align: A) -> Self {
262        self.align = Some(align.into());
263        self
264    }
265
266    pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
267        self.padding = Some(padding.into());
268        self
269    }
270
271    pub fn item_gap<F: Into<i64>>(mut self, item_gap: F) -> Self {
272        self.item_gap = Some(item_gap.into());
273        self
274    }
275
276    pub fn item_width<F: Into<i64>>(mut self, item_width: F) -> Self {
277        self.item_width = Some(item_width.into());
278        self
279    }
280
281    pub fn item_height<F: Into<i64>>(mut self, item_height: F) -> Self {
282        self.item_height = Some(item_height.into());
283        self
284    }
285
286    pub fn item_style<S: Into<ItemStyle>>(mut self, item_style: S) -> Self {
287        self.item_style = Some(item_style.into());
288        self
289    }
290
291    pub fn line_style<S: Into<LineStyle>>(mut self, line_style: S) -> Self {
292        self.line_style = Some(line_style.into());
293        self
294    }
295
296    pub fn text_style<S: Into<TextStyle>>(mut self, text_style: S) -> Self {
297        self.text_style = Some(text_style.into());
298        self
299    }
300
301    pub fn symbol_rotate<S: Into<String>>(mut self, symbol_rotate: S) -> Self {
302        self.symbol_rotate = Some(symbol_rotate.into());
303        self
304    }
305
306    pub fn formatter<S: Into<String>>(mut self, formatter: S) -> Self {
307        self.formatter = Some(formatter.into());
308        self
309    }
310
311    pub fn selected_mode<S: Into<LegendSelectedMode>>(mut self, selected_mode: S) -> Self {
312        self.selected_mode = Some(selected_mode.into());
313        self
314    }
315
316    pub fn border_color<C: Into<Color>>(mut self, border_color: C) -> Self {
317        self.border_color = Some(border_color.into());
318        self
319    }
320
321    pub fn inactive_color<C: Into<Color>>(mut self, inactive_color: C) -> Self {
322        self.inactive_color = Some(inactive_color.into());
323        self
324    }
325
326    pub fn data<L: Into<LegendItem>>(mut self, data: Vec<L>) -> Self {
327        self.data = data.into_iter().map(|s| s.into()).collect();
328        self
329    }
330}