charming_fork_zephyr/series/
graph.rs

1use serde::{Deserialize, Serialize};
2
3use crate::element::{CoordinateSystem, Label, LabelLayout, LineStyle, ScaleLimit};
4
5#[derive(Serialize)]
6#[serde(rename_all = "camelCase")]
7pub struct GraphLayoutCircular {
8    #[serde(skip_serializing_if = "Option::is_none")]
9    rotate_label: Option<bool>,
10}
11
12impl GraphLayoutCircular {
13    pub fn new() -> Self {
14        Self { rotate_label: None }
15    }
16
17    pub fn rotate_label(mut self, rotate_label: bool) -> Self {
18        self.rotate_label = Some(rotate_label);
19        self
20    }
21}
22
23#[derive(Serialize)]
24#[serde(rename_all = "camelCase")]
25pub struct GraphLayoutForce {
26    #[serde(skip_serializing_if = "Option::is_none")]
27    init_layout: Option<String>,
28
29    #[serde(skip_serializing_if = "Option::is_none")]
30    gravity: Option<i64>,
31
32    #[serde(skip_serializing_if = "Option::is_none")]
33    edge_length: Option<i64>,
34
35    #[serde(skip_serializing_if = "Option::is_none")]
36    layout_animation: Option<bool>,
37
38    #[serde(skip_serializing_if = "Option::is_none")]
39    friction: Option<i64>,
40}
41
42impl GraphLayoutForce {
43    pub fn new() -> Self {
44        Self {
45            init_layout: None,
46            gravity: None,
47            edge_length: None,
48            layout_animation: None,
49            friction: None,
50        }
51    }
52
53    pub fn init_layout<S: Into<String>>(mut self, init_layout: S) -> Self {
54        self.init_layout = Some(init_layout.into());
55        self
56    }
57
58    pub fn gravity(mut self, gravity: i64) -> Self {
59        self.gravity = Some(gravity);
60        self
61    }
62
63    pub fn edge_length(mut self, edge_length: i64) -> Self {
64        self.edge_length = Some(edge_length);
65        self
66    }
67
68    pub fn layout_animation(mut self, layout_animation: bool) -> Self {
69        self.layout_animation = Some(layout_animation);
70        self
71    }
72
73    pub fn friction(mut self, friction: i64) -> Self {
74        self.friction = Some(friction);
75        self
76    }
77}
78
79#[derive(Serialize)]
80#[serde(rename_all = "snake_case")]
81pub enum GraphLayout {
82    None,
83    Circular,
84    Force,
85}
86
87impl From<&str> for GraphLayout {
88    fn from(s: &str) -> Self {
89        match s {
90            "none" => Self::None,
91            "circular" => Self::Circular,
92            "force" => Self::Force,
93            _ => panic!("Invalid Layout"),
94        }
95    }
96}
97
98#[derive(Serialize)]
99#[serde(rename_all = "camelCase")]
100pub struct GraphNodeLabel {
101    #[serde(skip_serializing_if = "Option::is_none")]
102    show: Option<bool>,
103
104    #[serde(skip_serializing_if = "Option::is_none")]
105    position: Option<String>,
106
107    #[serde(skip_serializing_if = "Option::is_none")]
108    formatter: Option<String>,
109
110    #[serde(skip_serializing_if = "Option::is_none")]
111    color: Option<String>,
112
113    #[serde(skip_serializing_if = "Option::is_none")]
114    font_size: Option<u64>,
115}
116
117impl GraphNodeLabel {
118    pub fn new() -> Self {
119        Self {
120            show: None,
121            position: None,
122            formatter: None,
123            color: None,
124            font_size: None,
125        }
126    }
127
128    pub fn show(mut self, show: bool) -> Self {
129        self.show = Some(show);
130        self
131    }
132
133    pub fn position<S: Into<String>>(mut self, position: S) -> Self {
134        self.position = Some(position.into());
135        self
136    }
137
138    pub fn formatter<S: Into<String>>(mut self, formatter: S) -> Self {
139        self.formatter = Some(formatter.into());
140        self
141    }
142
143    pub fn color<S: Into<String>>(mut self, color: S) -> Self {
144        self.color = Some(color.into());
145        self
146    }
147
148    pub fn font_size(mut self, font_size: u64) -> Self {
149        self.font_size = Some(font_size);
150        self
151    }
152}
153
154#[derive(Serialize, Deserialize)]
155#[serde(rename_all = "camelCase")]
156pub struct GraphNode {
157    pub id: String,
158    pub name: String,
159    pub x: i64,
160    pub y: i64,
161    pub value: i64,
162    pub category: u64,
163    pub symbol_size: i64,
164    #[serde(skip_deserializing)]
165    #[serde(skip_serializing_if = "Option::is_none")]
166    pub label: Option<GraphNodeLabel>,
167}
168
169#[derive(Serialize, Deserialize)]
170#[serde(rename_all = "camelCase")]
171pub struct GraphLink {
172    pub source: String,
173    pub target: String,
174    #[serde(skip_serializing_if = "Option::is_none")]
175    pub value: Option<i64>,
176}
177
178#[derive(Serialize, Deserialize)]
179#[serde(rename_all = "camelCase")]
180pub struct GraphCategory {
181    pub name: String,
182}
183
184#[derive(Serialize, Deserialize)]
185#[serde(rename_all = "camelCase")]
186pub struct GraphData {
187    pub nodes: Vec<GraphNode>,
188    pub links: Vec<GraphLink>,
189    pub categories: Vec<GraphCategory>,
190}
191
192#[derive(Serialize)]
193#[serde(rename_all = "camelCase")]
194pub struct Graph {
195    #[serde(rename = "type")]
196    type_: String,
197
198    #[serde(skip_serializing_if = "Option::is_none")]
199    id: Option<String>,
200
201    #[serde(skip_serializing_if = "Option::is_none")]
202    name: Option<String>,
203
204    #[serde(skip_serializing_if = "Option::is_none")]
205    legend_hover_link: Option<bool>,
206
207    #[serde(skip_serializing_if = "Option::is_none")]
208    coordinate_system: Option<CoordinateSystem>,
209
210    #[serde(skip_serializing_if = "Option::is_none")]
211    x_axis_index: Option<u64>,
212
213    #[serde(skip_serializing_if = "Option::is_none")]
214    y_axis_index: Option<u64>,
215
216    #[serde(skip_serializing_if = "Option::is_none")]
217    polar_axis_index: Option<u64>,
218
219    #[serde(skip_serializing_if = "Option::is_none")]
220    geo_index: Option<u64>,
221
222    #[serde(skip_serializing_if = "Option::is_none")]
223    calendar_index: Option<u64>,
224
225    #[serde(skip_serializing_if = "Option::is_none")]
226    layout: Option<GraphLayout>,
227
228    #[serde(skip_serializing_if = "Option::is_none")]
229    circular: Option<GraphLayoutCircular>,
230
231    #[serde(skip_serializing_if = "Option::is_none")]
232    force: Option<GraphLayoutForce>,
233
234    #[serde(skip_serializing_if = "Option::is_none")]
235    roam: Option<bool>,
236
237    #[serde(skip_serializing_if = "Option::is_none")]
238    label: Option<Label>,
239
240    #[serde(skip_serializing_if = "Option::is_none")]
241    label_layout: Option<LabelLayout>,
242
243    #[serde(skip_serializing_if = "Option::is_none")]
244    scale_limit: Option<ScaleLimit>,
245
246    #[serde(skip_serializing_if = "Option::is_none")]
247    line_style: Option<LineStyle>,
248
249    #[serde(skip_serializing_if = "Vec::is_empty")]
250    categories: Vec<GraphCategory>,
251
252    #[serde(skip_serializing_if = "Vec::is_empty")]
253    links: Vec<GraphLink>,
254
255    #[serde(skip_serializing_if = "Vec::is_empty")]
256    data: Vec<GraphNode>,
257
258    #[serde(skip_serializing_if = "Option::is_none")]
259    edge_symbol: Option<(String, String)>,
260}
261
262impl Graph {
263    pub fn new() -> Self {
264        Self {
265            type_: "graph".into(),
266            id: None,
267            name: None,
268            legend_hover_link: None,
269            coordinate_system: None,
270            x_axis_index: None,
271            y_axis_index: None,
272            polar_axis_index: None,
273            geo_index: None,
274            calendar_index: None,
275            layout: None,
276            circular: None,
277            force: None,
278            roam: None,
279            label: None,
280            label_layout: None,
281            scale_limit: None,
282            line_style: None,
283            categories: vec![],
284            links: vec![],
285            data: vec![],
286            edge_symbol: None,
287        }
288    }
289
290    pub fn id<S: Into<String>>(mut self, id: S) -> Self {
291        self.id = Some(id.into());
292        self
293    }
294
295    pub fn name<S: Into<String>>(mut self, name: S) -> Self {
296        self.name = Some(name.into());
297        self
298    }
299
300    pub fn legend_hover_link(mut self, legend_hover_link: bool) -> Self {
301        self.legend_hover_link = Some(legend_hover_link);
302        self
303    }
304
305    pub fn coordinate_system(mut self, coordinate_system: CoordinateSystem) -> Self {
306        self.coordinate_system = Some(coordinate_system);
307        self
308    }
309
310    pub fn x_axis_index(mut self, x_axis_index: u64) -> Self {
311        self.x_axis_index = Some(x_axis_index);
312        self
313    }
314
315    pub fn y_axis_index(mut self, y_axis_index: u64) -> Self {
316        self.y_axis_index = Some(y_axis_index);
317        self
318    }
319
320    pub fn polar_axis_index(mut self, polar_axis_index: u64) -> Self {
321        self.polar_axis_index = Some(polar_axis_index);
322        self
323    }
324
325    pub fn geo_index(mut self, geo_index: u64) -> Self {
326        self.geo_index = Some(geo_index);
327        self
328    }
329
330    pub fn calendar_index(mut self, calendar_index: u64) -> Self {
331        self.calendar_index = Some(calendar_index);
332        self
333    }
334
335    pub fn layout(mut self, layout: GraphLayout) -> Self {
336        self.layout = Some(layout);
337        self
338    }
339
340    pub fn circular(mut self, circular: GraphLayoutCircular) -> Self {
341        self.circular = Some(circular);
342        self
343    }
344
345    pub fn force(mut self, force: GraphLayoutForce) -> Self {
346        self.force = Some(force);
347        self
348    }
349
350    pub fn roam(mut self, roam: bool) -> Self {
351        self.roam = Some(roam);
352        self
353    }
354
355    pub fn label(mut self, label: Label) -> Self {
356        self.label = Some(label);
357        self
358    }
359
360    pub fn label_layout(mut self, label_layout: LabelLayout) -> Self {
361        self.label_layout = Some(label_layout);
362        self
363    }
364
365    pub fn scale_limit(mut self, scale_limit: ScaleLimit) -> Self {
366        self.scale_limit = Some(scale_limit);
367        self
368    }
369
370    pub fn line_style(mut self, line_style: LineStyle) -> Self {
371        self.line_style = Some(line_style);
372        self
373    }
374
375    pub fn data(mut self, data: GraphData) -> Self {
376        self.data = data.nodes;
377        self.links = data.links;
378        self.categories = data.categories;
379        self
380    }
381
382    pub fn edge_symbol(mut self, edge_symbol: Option<(String, String)>) -> Self {
383        self.edge_symbol = edge_symbol;
384        self
385    }
386}