charming_fork_zephyr/series/
graph.rs1use 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}