charts_rs/charts/
theme.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13use super::color::Color;
14use super::common::Align;
15use super::font::DEFAULT_FONT_FAMILY;
16use super::util::Box;
17use ahash::AHashMap;
18use arc_swap::ArcSwap;
19use once_cell::sync::Lazy;
20use serde::{Deserialize, Serialize};
21use std::sync::Arc;
22
23pub static DEFAULT_WIDTH: f32 = 600.0;
24pub static DEFAULT_HEIGHT: f32 = 400.0;
25
26pub static DEFAULT_TITLE_HEIGHT: f32 = 30.0;
27pub static DEFAULT_SUB_TITLE_HEIGHT: f32 = 20.0;
28
29pub static DEFAULT_X_AXIS_HEIGHT: f32 = 30.0;
30pub static DEFAULT_X_AXIS_NAME_GAP: f32 = 5.0;
31
32pub static DEFAULT_Y_AXIS_WIDTH: f32 = 40.0;
33pub static DEFAULT_Y_AXIS_NAME_GAP: f32 = 8.0;
34pub static DEFAULT_Y_AXIS_SPLIT_NUMBER: usize = 6;
35pub static DEFAULT_FONT_SIZE: f32 = 14.0;
36
37pub static DEFAULT_SERIES_STROKE_WIDTH: f32 = 2.0;
38
39pub static THEME_DARK: &str = "dark";
40pub static THEME_ANT: &str = "ant";
41pub static THEME_GRAFANA: &str = "grafana";
42
43static LIGHT_THEME_NAME: &str = "light";
44
45#[derive(Clone, Debug, Default, Serialize, Deserialize)]
46
47pub struct Theme {
48    pub is_light: bool,
49    pub font_family: String,
50    pub margin: Box,
51    pub width: f32,
52    pub height: f32,
53    pub background_color: Color,
54
55    // title
56    pub title_font_size: f32,
57    pub title_font_color: Color,
58    pub title_font_weight: Option<String>,
59    pub title_margin: Option<Box>,
60    pub title_align: Align,
61    pub title_height: f32,
62
63    // sub title
64    pub sub_title_font_size: f32,
65    pub sub_title_font_color: Color,
66    pub sub_title_margin: Option<Box>,
67    pub sub_title_align: Align,
68    pub sub_title_height: f32,
69
70    // legend
71    pub legend_font_size: f32,
72    pub legend_font_color: Color,
73    pub legend_align: Align,
74    pub legend_margin: Option<Box>,
75
76    // x axis
77    pub x_axis_font_size: f32,
78    pub x_axis_stroke_color: Color,
79    pub x_axis_font_color: Color,
80    pub x_axis_name_gap: f32,
81    pub x_axis_height: f32,
82
83    // y axis
84    pub y_axis_font_size: f32,
85    pub y_axis_font_color: Color,
86    pub y_axis_stroke_color: Color,
87    pub y_axis_split_number: usize,
88    pub y_axis_name_gap: f32,
89
90    // grid
91    pub grid_stroke_color: Color,
92    pub grid_stroke_width: f32,
93
94    // series
95    pub series_stroke_width: f32,
96    pub series_label_font_size: f32,
97    pub series_label_font_color: Color,
98    pub series_colors: Vec<Color>,
99
100    // table
101    pub table_header_color: Color,
102    pub table_body_colors: Vec<Color>,
103    pub table_border_color: Color,
104}
105
106static LIGHT_THEME: Lazy<Theme> = Lazy::new(|| {
107    let x_axis_color = (110, 112, 121).into();
108    let font_color: Color = (70, 70, 70).into();
109    Theme {
110        is_light: true,
111        font_family: DEFAULT_FONT_FAMILY.to_string(),
112        margin: (5.0).into(),
113        width: DEFAULT_WIDTH,
114        height: DEFAULT_HEIGHT,
115        background_color: Color::white(),
116
117        title_font_color: font_color,
118        title_font_size: 18.0,
119        title_font_weight: Some("bold".to_string()),
120        title_margin: None,
121        title_align: Align::Center,
122        title_height: DEFAULT_TITLE_HEIGHT,
123
124        sub_title_font_color: font_color,
125        sub_title_font_size: DEFAULT_FONT_SIZE,
126        sub_title_margin: None,
127        sub_title_align: Align::Center,
128        sub_title_height: DEFAULT_SUB_TITLE_HEIGHT,
129
130        legend_font_size: DEFAULT_FONT_SIZE,
131        legend_font_color: font_color,
132        legend_align: Align::Center,
133        legend_margin: None,
134
135        x_axis_font_size: DEFAULT_FONT_SIZE,
136        x_axis_stroke_color: x_axis_color,
137        x_axis_font_color: x_axis_color,
138        x_axis_name_gap: DEFAULT_X_AXIS_NAME_GAP,
139        x_axis_height: DEFAULT_X_AXIS_HEIGHT,
140
141        y_axis_font_size: DEFAULT_FONT_SIZE,
142        y_axis_font_color: x_axis_color,
143        y_axis_stroke_color: Color::transparent(),
144        y_axis_split_number: DEFAULT_Y_AXIS_SPLIT_NUMBER,
145        y_axis_name_gap: DEFAULT_Y_AXIS_NAME_GAP,
146
147        grid_stroke_color: (224, 230, 242).into(),
148        grid_stroke_width: 1.0,
149
150        series_stroke_width: DEFAULT_SERIES_STROKE_WIDTH,
151        series_label_font_size: DEFAULT_FONT_SIZE,
152        series_label_font_color: font_color,
153        series_colors: vec![
154            "#5470c6".into(),
155            "#91cc75".into(),
156            "#fac858".into(),
157            "#ee6666".into(),
158            "#73c0de".into(),
159            "#3ba272".into(),
160            "#fc8452".into(),
161            "#9a60b4".into(),
162            "#ea7ccc".into(),
163        ],
164
165        table_header_color: (242, 243, 245).into(),
166        table_body_colors: vec![(255, 255, 255).into()],
167        table_border_color: (229, 230, 235).into(),
168    }
169});
170
171static DARK_THEME: Lazy<Theme> = Lazy::new(|| {
172    let x_axis_color = (185, 184, 206).into();
173    let bg_color = (16, 12, 42).into();
174
175    let font_color: Color = (238, 238, 238).into();
176    Theme {
177        is_light: false,
178        font_family: DEFAULT_FONT_FAMILY.to_string(),
179        margin: (5.0).into(),
180        width: DEFAULT_WIDTH,
181        height: DEFAULT_HEIGHT,
182        background_color: bg_color,
183
184        title_font_color: font_color,
185        title_font_size: 18.0,
186        title_font_weight: Some("bold".to_string()),
187        title_margin: None,
188        title_align: Align::Center,
189        title_height: DEFAULT_TITLE_HEIGHT,
190
191        sub_title_font_color: font_color,
192        sub_title_font_size: DEFAULT_FONT_SIZE,
193        sub_title_margin: None,
194        sub_title_align: Align::Center,
195        sub_title_height: DEFAULT_SUB_TITLE_HEIGHT,
196
197        legend_font_size: DEFAULT_FONT_SIZE,
198        legend_font_color: font_color,
199        legend_align: Align::Center,
200        legend_margin: None,
201
202        x_axis_font_size: DEFAULT_FONT_SIZE,
203        x_axis_stroke_color: x_axis_color,
204        x_axis_font_color: x_axis_color,
205        x_axis_name_gap: DEFAULT_X_AXIS_NAME_GAP,
206        x_axis_height: DEFAULT_X_AXIS_HEIGHT,
207
208        y_axis_font_size: DEFAULT_FONT_SIZE,
209        y_axis_font_color: x_axis_color,
210        y_axis_stroke_color: Color::transparent(),
211        y_axis_split_number: DEFAULT_Y_AXIS_SPLIT_NUMBER,
212        y_axis_name_gap: DEFAULT_Y_AXIS_NAME_GAP,
213
214        grid_stroke_color: (71, 71, 83).into(),
215        grid_stroke_width: 1.0,
216
217        series_stroke_width: DEFAULT_SERIES_STROKE_WIDTH,
218        series_label_font_size: DEFAULT_FONT_SIZE,
219        series_label_font_color: font_color,
220        series_colors: vec![
221            "#5470c6".into(),
222            "#91cc75".into(),
223            "#fac858".into(),
224            "#ee6666".into(),
225            "#73c0de".into(),
226            "#3ba272".into(),
227            "#fc8452".into(),
228            "#9a60b4".into(),
229            "#ea7ccc".into(),
230        ],
231
232        table_header_color: bg_color,
233        table_body_colors: vec![bg_color.with_alpha(230)],
234        table_border_color: (100, 100, 100).into(),
235    }
236});
237
238static ANT_THEME: Lazy<Theme> = Lazy::new(|| {
239    let x_axis_color = (110, 112, 121).into();
240
241    let font_color: Color = (70, 70, 70).into();
242    Theme {
243        is_light: true,
244        font_family: DEFAULT_FONT_FAMILY.to_string(),
245        margin: (5.0).into(),
246        width: DEFAULT_WIDTH,
247        height: DEFAULT_HEIGHT,
248        background_color: Color::white(),
249
250        title_font_color: font_color,
251        title_font_size: 18.0,
252        title_font_weight: Some("bold".to_string()),
253        title_margin: None,
254        title_align: Align::Center,
255        title_height: DEFAULT_TITLE_HEIGHT,
256
257        sub_title_font_color: font_color,
258        sub_title_font_size: DEFAULT_FONT_SIZE,
259        sub_title_margin: None,
260        sub_title_align: Align::Center,
261        sub_title_height: DEFAULT_SUB_TITLE_HEIGHT,
262
263        legend_font_size: DEFAULT_FONT_SIZE,
264        legend_font_color: font_color,
265        legend_align: Align::Center,
266        legend_margin: None,
267
268        x_axis_font_size: DEFAULT_FONT_SIZE,
269        x_axis_stroke_color: x_axis_color,
270        x_axis_font_color: x_axis_color,
271        x_axis_name_gap: DEFAULT_X_AXIS_NAME_GAP,
272        x_axis_height: DEFAULT_X_AXIS_HEIGHT,
273
274        y_axis_font_size: DEFAULT_FONT_SIZE,
275        y_axis_font_color: x_axis_color,
276        y_axis_stroke_color: Color::transparent(),
277        y_axis_split_number: DEFAULT_Y_AXIS_SPLIT_NUMBER,
278        y_axis_name_gap: DEFAULT_Y_AXIS_NAME_GAP,
279
280        grid_stroke_color: (224, 230, 242).into(),
281        grid_stroke_width: 1.0,
282
283        series_stroke_width: DEFAULT_SERIES_STROKE_WIDTH,
284        series_label_font_size: DEFAULT_FONT_SIZE,
285        series_label_font_color: font_color,
286
287        series_colors: vec![
288            "#5b8ff9".into(),
289            "#5ad8a6".into(),
290            "#5d7092".into(),
291            "#f6bd16".into(),
292            "#6f5ef9".into(),
293            "#6dc8ec".into(),
294            "#945fb9".into(),
295            "#ff9845".into(),
296        ],
297
298        table_header_color: (250, 250, 250).into(),
299        table_body_colors: vec![(255, 255, 255).into()],
300        table_border_color: (239, 239, 244).into(),
301    }
302});
303
304static VINTAGE_THEME: Lazy<Theme> = Lazy::new(|| {
305    let x_axis_color = (0, 0, 0).into();
306
307    let font_color: Color = (51, 51, 51).into();
308    Theme {
309        is_light: true,
310        font_family: DEFAULT_FONT_FAMILY.to_string(),
311        margin: (5.0).into(),
312        width: DEFAULT_WIDTH,
313        height: DEFAULT_HEIGHT,
314        background_color: (254, 248, 239).into(),
315
316        title_font_color: font_color,
317        title_font_size: 18.0,
318        title_font_weight: Some("bold".to_string()),
319        title_margin: None,
320        title_align: Align::Center,
321        title_height: DEFAULT_TITLE_HEIGHT,
322
323        sub_title_font_color: font_color,
324        sub_title_font_size: DEFAULT_FONT_SIZE,
325        sub_title_margin: None,
326        sub_title_align: Align::Center,
327        sub_title_height: DEFAULT_SUB_TITLE_HEIGHT,
328
329        legend_font_size: DEFAULT_FONT_SIZE,
330        legend_font_color: font_color,
331        legend_align: Align::Center,
332        legend_margin: None,
333
334        x_axis_font_size: DEFAULT_FONT_SIZE,
335        x_axis_stroke_color: x_axis_color,
336        x_axis_font_color: x_axis_color,
337        x_axis_name_gap: DEFAULT_X_AXIS_NAME_GAP,
338        x_axis_height: DEFAULT_X_AXIS_HEIGHT,
339
340        y_axis_font_size: DEFAULT_FONT_SIZE,
341        y_axis_font_color: x_axis_color,
342        y_axis_stroke_color: Color::transparent(),
343        y_axis_split_number: DEFAULT_Y_AXIS_SPLIT_NUMBER,
344        y_axis_name_gap: DEFAULT_Y_AXIS_NAME_GAP,
345
346        grid_stroke_color: (224, 230, 242).into(),
347        grid_stroke_width: 1.0,
348
349        series_stroke_width: DEFAULT_SERIES_STROKE_WIDTH,
350        series_label_font_size: DEFAULT_FONT_SIZE,
351        series_label_font_color: font_color,
352
353        series_colors: vec![
354            "#d87c7c".into(),
355            "#919e8b".into(),
356            "#d7ab82".into(),
357            "#6e7074".into(),
358            "#61a0a8".into(),
359            "#efa18d".into(),
360            "#787464".into(),
361            "#cc7e63".into(),
362            "#724e58".into(),
363            "#4b565b".into(),
364        ],
365
366        table_header_color: (250, 250, 250).into(),
367        table_body_colors: vec![(255, 255, 255).into()],
368        table_border_color: (239, 239, 244).into(),
369    }
370});
371
372static SHINE_THEME: Lazy<Theme> = Lazy::new(|| {
373    let x_axis_color = (0, 0, 0).into();
374
375    let font_color: Color = (51, 51, 51).into();
376    Theme {
377        is_light: true,
378        font_family: DEFAULT_FONT_FAMILY.to_string(),
379        margin: (5.0).into(),
380        width: DEFAULT_WIDTH,
381        height: DEFAULT_HEIGHT,
382        background_color: (255, 255, 255).into(),
383
384        title_font_color: font_color,
385        title_font_size: 18.0,
386        title_font_weight: Some("bold".to_string()),
387        title_margin: None,
388        title_align: Align::Center,
389        title_height: DEFAULT_TITLE_HEIGHT,
390
391        sub_title_font_color: font_color,
392        sub_title_font_size: DEFAULT_FONT_SIZE,
393        sub_title_margin: None,
394        sub_title_align: Align::Center,
395        sub_title_height: DEFAULT_SUB_TITLE_HEIGHT,
396
397        legend_font_size: DEFAULT_FONT_SIZE,
398        legend_font_color: font_color,
399        legend_align: Align::Center,
400        legend_margin: None,
401
402        x_axis_font_size: DEFAULT_FONT_SIZE,
403        x_axis_stroke_color: x_axis_color,
404        x_axis_font_color: x_axis_color,
405        x_axis_name_gap: DEFAULT_X_AXIS_NAME_GAP,
406        x_axis_height: DEFAULT_X_AXIS_HEIGHT,
407
408        y_axis_font_size: DEFAULT_FONT_SIZE,
409        y_axis_font_color: x_axis_color,
410        y_axis_stroke_color: Color::transparent(),
411        y_axis_split_number: DEFAULT_Y_AXIS_SPLIT_NUMBER,
412        y_axis_name_gap: DEFAULT_Y_AXIS_NAME_GAP,
413
414        grid_stroke_color: (224, 230, 242).into(),
415        grid_stroke_width: 1.0,
416
417        series_stroke_width: DEFAULT_SERIES_STROKE_WIDTH,
418        series_label_font_size: DEFAULT_FONT_SIZE,
419        series_label_font_color: font_color,
420
421        series_colors: vec![
422            "#c12e34".into(),
423            "#e6b600".into(),
424            "#0098d9".into(),
425            "#2b821d".into(),
426            "#005eaa".into(),
427            "#339ca8".into(),
428            "#cda819".into(),
429            "#32a487".into(),
430        ],
431
432        table_header_color: (250, 250, 250).into(),
433        table_body_colors: vec![(255, 255, 255).into()],
434        table_border_color: (239, 239, 244).into(),
435    }
436});
437
438static WALDEN_THEME: Lazy<Theme> = Lazy::new(|| {
439    let x_axis_color = (110, 112, 121).into();
440
441    let font_color: Color = (70, 70, 70).into();
442    Theme {
443        is_light: true,
444        font_family: DEFAULT_FONT_FAMILY.to_string(),
445        margin: (5.0).into(),
446        width: DEFAULT_WIDTH,
447        height: DEFAULT_HEIGHT,
448        background_color: Color::white(),
449
450        title_font_color: font_color,
451        title_font_size: 18.0,
452        title_font_weight: Some("bold".to_string()),
453        title_margin: None,
454        title_align: Align::Center,
455        title_height: DEFAULT_TITLE_HEIGHT,
456
457        sub_title_font_color: font_color,
458        sub_title_font_size: DEFAULT_FONT_SIZE,
459        sub_title_margin: None,
460        sub_title_align: Align::Center,
461        sub_title_height: DEFAULT_SUB_TITLE_HEIGHT,
462
463        legend_font_size: DEFAULT_FONT_SIZE,
464        legend_font_color: font_color,
465        legend_align: Align::Center,
466        legend_margin: None,
467
468        x_axis_font_size: DEFAULT_FONT_SIZE,
469        x_axis_stroke_color: x_axis_color,
470        x_axis_font_color: x_axis_color,
471        x_axis_name_gap: DEFAULT_X_AXIS_NAME_GAP,
472        x_axis_height: DEFAULT_X_AXIS_HEIGHT,
473
474        y_axis_font_size: DEFAULT_FONT_SIZE,
475        y_axis_font_color: x_axis_color,
476        y_axis_stroke_color: Color::transparent(),
477        y_axis_split_number: DEFAULT_Y_AXIS_SPLIT_NUMBER,
478        y_axis_name_gap: DEFAULT_Y_AXIS_NAME_GAP,
479
480        grid_stroke_color: (224, 230, 242).into(),
481        grid_stroke_width: 1.0,
482
483        series_stroke_width: DEFAULT_SERIES_STROKE_WIDTH,
484        series_label_font_size: DEFAULT_FONT_SIZE,
485        series_label_font_color: font_color,
486
487        series_colors: vec![
488            "#3fb1e3".into(),
489            "#6be6c1".into(),
490            "#626c91".into(),
491            "#a0a7e6".into(),
492            "#c4ebad".into(),
493            "#96dee8".into(),
494        ],
495
496        table_header_color: (250, 250, 250).into(),
497        table_body_colors: vec![(255, 255, 255).into()],
498        table_border_color: (239, 239, 244).into(),
499    }
500});
501
502static WESTEROS_THEME: Lazy<Theme> = Lazy::new(|| {
503    let x_axis_color = (110, 112, 121).into();
504
505    let font_color: Color = (70, 70, 70).into();
506    Theme {
507        is_light: true,
508        font_family: DEFAULT_FONT_FAMILY.to_string(),
509        margin: (5.0).into(),
510        width: DEFAULT_WIDTH,
511        height: DEFAULT_HEIGHT,
512        background_color: Color::white(),
513
514        title_font_color: font_color,
515        title_font_size: 18.0,
516        title_font_weight: Some("bold".to_string()),
517        title_margin: None,
518        title_align: Align::Center,
519        title_height: DEFAULT_TITLE_HEIGHT,
520
521        sub_title_font_color: font_color,
522        sub_title_font_size: DEFAULT_FONT_SIZE,
523        sub_title_margin: None,
524        sub_title_align: Align::Center,
525        sub_title_height: DEFAULT_SUB_TITLE_HEIGHT,
526
527        legend_font_size: DEFAULT_FONT_SIZE,
528        legend_font_color: font_color,
529        legend_align: Align::Center,
530        legend_margin: None,
531
532        x_axis_font_size: DEFAULT_FONT_SIZE,
533        x_axis_stroke_color: x_axis_color,
534        x_axis_font_color: x_axis_color,
535        x_axis_name_gap: DEFAULT_X_AXIS_NAME_GAP,
536        x_axis_height: DEFAULT_X_AXIS_HEIGHT,
537
538        y_axis_font_size: DEFAULT_FONT_SIZE,
539        y_axis_font_color: x_axis_color,
540        y_axis_stroke_color: Color::transparent(),
541        y_axis_split_number: DEFAULT_Y_AXIS_SPLIT_NUMBER,
542        y_axis_name_gap: DEFAULT_Y_AXIS_NAME_GAP,
543
544        grid_stroke_color: (224, 230, 242).into(),
545        grid_stroke_width: 1.0,
546
547        series_stroke_width: DEFAULT_SERIES_STROKE_WIDTH,
548        series_label_font_size: DEFAULT_FONT_SIZE,
549        series_label_font_color: font_color,
550
551        series_colors: vec![
552            "#516b91".into(),
553            "#59c4e6".into(),
554            "#edafda".into(),
555            "#93b7e3".into(),
556            "#a5e7f0".into(),
557            "#cbb0e3".into(),
558        ],
559
560        table_header_color: (250, 250, 250).into(),
561        table_body_colors: vec![(255, 255, 255).into()],
562        table_border_color: (239, 239, 244).into(),
563    }
564});
565
566static CHALK_THEME: Lazy<Theme> = Lazy::new(|| {
567    let x_axis_color = (170, 170, 170).into();
568
569    let font_color: Color = (255, 255, 255).into();
570    let bg_color: Color = (41, 52, 65).into();
571    Theme {
572        is_light: true,
573        font_family: DEFAULT_FONT_FAMILY.to_string(),
574        margin: (5.0).into(),
575        width: DEFAULT_WIDTH,
576        height: DEFAULT_HEIGHT,
577        background_color: bg_color,
578
579        title_font_color: font_color,
580        title_font_size: 18.0,
581        title_font_weight: Some("bold".to_string()),
582        title_margin: None,
583        title_align: Align::Center,
584        title_height: DEFAULT_TITLE_HEIGHT,
585
586        sub_title_font_color: font_color,
587        sub_title_font_size: DEFAULT_FONT_SIZE,
588        sub_title_margin: None,
589        sub_title_align: Align::Center,
590        sub_title_height: DEFAULT_SUB_TITLE_HEIGHT,
591
592        legend_font_size: DEFAULT_FONT_SIZE,
593        legend_font_color: font_color,
594        legend_align: Align::Center,
595        legend_margin: None,
596
597        x_axis_font_size: DEFAULT_FONT_SIZE,
598        x_axis_stroke_color: x_axis_color,
599        x_axis_font_color: x_axis_color,
600        x_axis_name_gap: DEFAULT_X_AXIS_NAME_GAP,
601        x_axis_height: DEFAULT_X_AXIS_HEIGHT,
602
603        y_axis_font_size: DEFAULT_FONT_SIZE,
604        y_axis_font_color: x_axis_color,
605        y_axis_stroke_color: Color::transparent(),
606        y_axis_split_number: DEFAULT_Y_AXIS_SPLIT_NUMBER,
607        y_axis_name_gap: DEFAULT_Y_AXIS_NAME_GAP,
608
609        grid_stroke_color: (41, 52, 65, 0).into(),
610        grid_stroke_width: 1.0,
611
612        series_stroke_width: DEFAULT_SERIES_STROKE_WIDTH,
613        series_label_font_size: DEFAULT_FONT_SIZE,
614        series_label_font_color: font_color,
615
616        series_colors: vec![
617            "#fc97af".into(),
618            "#87f7cf".into(),
619            "#f7f494".into(),
620            "#72ccff".into(),
621            "#f7c5a0".into(),
622            "#d4a4eb".into(),
623            "#d2f5a6".into(),
624            "#76f2f2".into(),
625        ],
626
627        table_header_color: bg_color,
628        table_body_colors: vec![bg_color.with_alpha(230)],
629        table_border_color: (100, 100, 100).into(),
630    }
631});
632
633static GRAFANA_THEME: Lazy<Theme> = Lazy::new(|| {
634    let x_axis_color = (185, 184, 206).into();
635
636    let font_color: Color = (216, 217, 218).into();
637    let bg_color = (31, 29, 29).into();
638    Theme {
639        is_light: false,
640        font_family: DEFAULT_FONT_FAMILY.to_string(),
641        margin: (5.0).into(),
642        width: DEFAULT_WIDTH,
643        height: DEFAULT_HEIGHT,
644        background_color: bg_color,
645
646        title_font_color: font_color,
647        title_font_size: 18.0,
648        title_font_weight: Some("bold".to_string()),
649        title_margin: None,
650        title_align: Align::Center,
651        title_height: DEFAULT_TITLE_HEIGHT,
652
653        sub_title_font_color: font_color,
654        sub_title_font_size: DEFAULT_FONT_SIZE,
655        sub_title_margin: None,
656        sub_title_align: Align::Center,
657        sub_title_height: DEFAULT_SUB_TITLE_HEIGHT,
658
659        legend_font_size: DEFAULT_FONT_SIZE,
660        legend_font_color: font_color,
661        legend_align: Align::Center,
662        legend_margin: None,
663
664        x_axis_font_size: DEFAULT_FONT_SIZE,
665        x_axis_stroke_color: x_axis_color,
666        x_axis_font_color: x_axis_color,
667        x_axis_name_gap: DEFAULT_X_AXIS_NAME_GAP,
668        x_axis_height: DEFAULT_X_AXIS_HEIGHT,
669
670        y_axis_font_size: DEFAULT_FONT_SIZE,
671        y_axis_font_color: x_axis_color,
672        y_axis_stroke_color: Color::transparent(),
673        y_axis_split_number: DEFAULT_Y_AXIS_SPLIT_NUMBER,
674        y_axis_name_gap: DEFAULT_Y_AXIS_NAME_GAP,
675
676        grid_stroke_color: (68, 67, 67).into(),
677        grid_stroke_width: 1.0,
678
679        series_stroke_width: DEFAULT_SERIES_STROKE_WIDTH,
680        series_label_font_size: DEFAULT_FONT_SIZE,
681        series_label_font_color: font_color,
682
683        series_colors: vec![
684            "#7EB26D".into(),
685            "#EAB839".into(),
686            "#6ED0E0".into(),
687            "#EF843C".into(),
688            "#E24D42".into(),
689            "#1F78C1".into(),
690            "#705DA0".into(),
691            "#508642".into(),
692        ],
693
694        table_header_color: bg_color,
695        table_body_colors: vec![bg_color.with_alpha(230)],
696        table_border_color: (239, 239, 244).into(),
697    }
698});
699
700static SHADCN_THEME: Lazy<Theme> = Lazy::new(|| {
701    let x_axis_color = (39, 39, 42).into();
702
703    let font_color: Color = (161, 161, 170).into();
704    let bg_color = (9, 9, 11).into();
705    Theme {
706        is_light: false,
707        font_family: DEFAULT_FONT_FAMILY.to_string(),
708        margin: (5.0).into(),
709        width: DEFAULT_WIDTH,
710        height: DEFAULT_HEIGHT,
711        background_color: bg_color,
712
713        title_font_color: font_color,
714        title_font_size: 18.0,
715        title_font_weight: Some("bold".to_string()),
716        title_margin: None,
717        title_align: Align::Center,
718        title_height: DEFAULT_TITLE_HEIGHT,
719
720        sub_title_font_color: font_color,
721        sub_title_font_size: DEFAULT_FONT_SIZE,
722        sub_title_margin: None,
723        sub_title_align: Align::Center,
724        sub_title_height: DEFAULT_SUB_TITLE_HEIGHT,
725
726        legend_font_size: DEFAULT_FONT_SIZE,
727        legend_font_color: font_color,
728        legend_align: Align::Center,
729        legend_margin: None,
730
731        x_axis_font_size: DEFAULT_FONT_SIZE,
732        x_axis_stroke_color: x_axis_color,
733        x_axis_font_color: font_color,
734        x_axis_name_gap: DEFAULT_X_AXIS_NAME_GAP,
735        x_axis_height: DEFAULT_X_AXIS_HEIGHT,
736
737        y_axis_font_size: DEFAULT_FONT_SIZE,
738        y_axis_font_color: font_color,
739        y_axis_stroke_color: Color::transparent(),
740        y_axis_split_number: DEFAULT_Y_AXIS_SPLIT_NUMBER,
741        y_axis_name_gap: DEFAULT_Y_AXIS_NAME_GAP,
742
743        grid_stroke_color: (39, 39, 42).into(),
744        grid_stroke_width: 1.0,
745
746        series_stroke_width: DEFAULT_SERIES_STROKE_WIDTH,
747        series_label_font_size: DEFAULT_FONT_SIZE,
748        series_label_font_color: font_color,
749
750        series_colors: vec![
751            "#2662d9".into(),
752            "#e23670".into(),
753            "#2eb88a".into(),
754            "#e88c30".into(),
755            "#af57db".into(),
756            "#0e2014".into(),
757            "#3b86f7".into(),
758            "#f17e92".into(),
759        ],
760
761        table_header_color: bg_color.with_alpha(230),
762        table_body_colors: vec![bg_color],
763        table_border_color: (39, 39, 42).into(),
764    }
765});
766
767type Themes = AHashMap<String, Arc<Theme>>;
768static THEME_MAP: Lazy<ArcSwap<Themes>> = Lazy::new(|| {
769    let mut m = AHashMap::new();
770    m.insert("dark".to_string(), Arc::new(DARK_THEME.clone()));
771    m.insert("ant".to_string(), Arc::new(ANT_THEME.clone()));
772    m.insert("grafana".to_string(), Arc::new(GRAFANA_THEME.clone()));
773    m.insert("vintage".to_string(), Arc::new(VINTAGE_THEME.clone()));
774    m.insert("shine".to_string(), Arc::new(SHINE_THEME.clone()));
775    m.insert("walden".to_string(), Arc::new(WALDEN_THEME.clone()));
776    m.insert("westeros".to_string(), Arc::new(WESTEROS_THEME.clone()));
777    m.insert("chalk".to_string(), Arc::new(CHALK_THEME.clone()));
778    m.insert("shadcn".to_string(), Arc::new(SHADCN_THEME.clone()));
779    m.insert("light".to_string(), Arc::new(LIGHT_THEME.clone()));
780    ArcSwap::from_pointee(m)
781});
782
783/// Add theme of charts
784pub fn add_theme(name: &str, data: Theme) {
785    let mut m: Themes = AHashMap::new();
786    for (name, data) in THEME_MAP.load().iter() {
787        m.insert(name.to_string(), data.clone());
788    }
789    m.insert(name.to_string(), Arc::new(data));
790    THEME_MAP.store(Arc::new(m))
791}
792
793/// Get the theme of charts
794pub fn get_theme(theme: &str) -> Arc<Theme> {
795    if let Some(theme) = THEME_MAP.load().get(theme) {
796        theme.clone()
797    } else {
798        Arc::new(LIGHT_THEME.clone())
799    }
800}
801
802/// List the theme name
803pub fn list_theme_name() -> Vec<String> {
804    let mut themes = vec![];
805    for name in THEME_MAP.load().keys() {
806        themes.push(name.to_string());
807    }
808    themes
809}
810
811/// Get default theme
812pub fn get_default_theme_name() -> String {
813    LIGHT_THEME_NAME.to_string()
814}