1pub mod elements;
2pub mod presets;
3
4pub use elements::{ElementLine, ElementRect, ElementText};
5
6#[derive(Clone, Debug)]
8pub enum LegendPosition {
9 Right,
10 Left,
11 Top,
12 Bottom,
13 None,
14}
15
16#[derive(Clone, Debug)]
18pub struct Margin {
19 pub top: f64,
20 pub right: f64,
21 pub bottom: f64,
22 pub left: f64,
23}
24
25impl Default for Margin {
26 fn default() -> Self {
27 Margin {
28 top: 10.0,
29 right: 10.0,
30 bottom: 10.0,
31 left: 10.0,
32 }
33 }
34}
35
36#[derive(Clone, Debug)]
38pub struct Theme {
39 pub text: ElementText,
41 pub title: ElementText,
42 pub axis_text_x: ElementText,
43 pub axis_text_y: ElementText,
44 pub axis_title_x: ElementText,
45 pub axis_title_y: ElementText,
46 pub axis_line: ElementLine,
47 pub axis_ticks: ElementLine,
48 pub panel_background: ElementRect,
49 pub panel_grid_major: ElementLine,
50 pub panel_grid_minor: ElementLine,
51 pub plot_background: ElementRect,
52 pub legend_position: LegendPosition,
53 pub plot_margin: Margin,
54
55 pub subtitle: ElementText,
57 pub caption: ElementText,
58 pub legend_title: ElementText,
59 pub legend_text: ElementText,
60 pub strip_text: ElementText,
61
62 pub axis_line_x: Option<ElementLine>,
64 pub axis_line_y: Option<ElementLine>,
65 pub axis_ticks_x: Option<ElementLine>,
66 pub axis_ticks_y: Option<ElementLine>,
67 pub panel_grid_major_x: Option<ElementLine>,
68 pub panel_grid_major_y: Option<ElementLine>,
69 pub panel_grid_minor_x: Option<ElementLine>,
70 pub panel_grid_minor_y: Option<ElementLine>,
71
72 pub panel_border: ElementLine,
74 pub legend_background: ElementRect,
75 pub legend_key: ElementRect,
76 pub strip_background: ElementRect,
77
78 pub axis_ticks_length: f64,
80 pub legend_key_width: f64,
81 pub legend_key_height: f64,
82 pub legend_spacing: f64,
83 pub legend_margin: Margin,
84 pub panel_spacing: f64,
85 pub panel_spacing_x: Option<f64>,
86 pub panel_spacing_y: Option<f64>,
87
88 pub primary: Option<(u8, u8, u8)>,
93}
94
95impl Theme {
96 pub fn primary_or(&self, fallback: (u8, u8, u8)) -> (u8, u8, u8) {
99 self.primary.unwrap_or(fallback)
100 }
101
102 pub fn with_primary(mut self, color: (u8, u8, u8)) -> Self {
104 self.primary = Some(color);
105 self
106 }
107
108 pub fn get_axis_line_x(&self) -> &ElementLine {
111 self.axis_line_x.as_ref().unwrap_or(&self.axis_line)
112 }
113
114 pub fn get_axis_line_y(&self) -> &ElementLine {
115 self.axis_line_y.as_ref().unwrap_or(&self.axis_line)
116 }
117
118 pub fn get_axis_ticks_x(&self) -> &ElementLine {
119 self.axis_ticks_x.as_ref().unwrap_or(&self.axis_ticks)
120 }
121
122 pub fn get_axis_ticks_y(&self) -> &ElementLine {
123 self.axis_ticks_y.as_ref().unwrap_or(&self.axis_ticks)
124 }
125
126 pub fn get_panel_grid_major_x(&self) -> &ElementLine {
127 self.panel_grid_major_x
128 .as_ref()
129 .unwrap_or(&self.panel_grid_major)
130 }
131
132 pub fn get_panel_grid_major_y(&self) -> &ElementLine {
133 self.panel_grid_major_y
134 .as_ref()
135 .unwrap_or(&self.panel_grid_major)
136 }
137
138 pub fn get_panel_grid_minor_x(&self) -> &ElementLine {
139 self.panel_grid_minor_x
140 .as_ref()
141 .unwrap_or(&self.panel_grid_minor)
142 }
143
144 pub fn get_panel_grid_minor_y(&self) -> &ElementLine {
145 self.panel_grid_minor_y
146 .as_ref()
147 .unwrap_or(&self.panel_grid_minor)
148 }
149
150 pub fn get_panel_spacing_x(&self) -> f64 {
151 self.panel_spacing_x.unwrap_or(self.panel_spacing)
152 }
153
154 pub fn get_panel_spacing_y(&self) -> f64 {
155 self.panel_spacing_y.unwrap_or(self.panel_spacing)
156 }
157
158 pub fn set_axis_text_x(mut self, el: ElementText) -> Self {
161 self.axis_text_x = el;
162 self
163 }
164
165 pub fn set_axis_text_y(mut self, el: ElementText) -> Self {
166 self.axis_text_y = el;
167 self
168 }
169
170 pub fn set_axis_title_x(mut self, el: ElementText) -> Self {
171 self.axis_title_x = el;
172 self
173 }
174
175 pub fn set_axis_title_y(mut self, el: ElementText) -> Self {
176 self.axis_title_y = el;
177 self
178 }
179
180 pub fn set_axis_line(mut self, el: ElementLine) -> Self {
181 self.axis_line = el;
182 self
183 }
184
185 pub fn set_axis_ticks(mut self, el: ElementLine) -> Self {
186 self.axis_ticks = el;
187 self
188 }
189
190 pub fn set_panel_background(mut self, el: ElementRect) -> Self {
191 self.panel_background = el;
192 self
193 }
194
195 pub fn set_panel_grid_major(mut self, el: ElementLine) -> Self {
196 self.panel_grid_major = el;
197 self
198 }
199
200 pub fn set_panel_grid_minor(mut self, el: ElementLine) -> Self {
201 self.panel_grid_minor = el;
202 self
203 }
204
205 pub fn set_plot_background(mut self, el: ElementRect) -> Self {
206 self.plot_background = el;
207 self
208 }
209
210 pub fn set_legend_position(mut self, pos: LegendPosition) -> Self {
211 self.legend_position = pos;
212 self
213 }
214
215 pub fn set_plot_margin(mut self, margin: Margin) -> Self {
216 self.plot_margin = margin;
217 self
218 }
219
220 pub fn set_title(mut self, el: ElementText) -> Self {
221 self.title = el;
222 self
223 }
224
225 pub fn set_text(mut self, el: ElementText) -> Self {
226 self.text = el;
227 self
228 }
229
230 pub fn set_subtitle(mut self, el: ElementText) -> Self {
233 self.subtitle = el;
234 self
235 }
236
237 pub fn set_caption(mut self, el: ElementText) -> Self {
238 self.caption = el;
239 self
240 }
241
242 pub fn set_legend_title(mut self, el: ElementText) -> Self {
243 self.legend_title = el;
244 self
245 }
246
247 pub fn set_legend_text(mut self, el: ElementText) -> Self {
248 self.legend_text = el;
249 self
250 }
251
252 pub fn set_strip_text(mut self, el: ElementText) -> Self {
253 self.strip_text = el;
254 self
255 }
256
257 pub fn set_axis_line_x(mut self, el: Option<ElementLine>) -> Self {
258 self.axis_line_x = el;
259 self
260 }
261
262 pub fn set_axis_line_y(mut self, el: Option<ElementLine>) -> Self {
263 self.axis_line_y = el;
264 self
265 }
266
267 pub fn set_axis_ticks_x(mut self, el: Option<ElementLine>) -> Self {
268 self.axis_ticks_x = el;
269 self
270 }
271
272 pub fn set_axis_ticks_y(mut self, el: Option<ElementLine>) -> Self {
273 self.axis_ticks_y = el;
274 self
275 }
276
277 pub fn set_panel_grid_major_x(mut self, el: Option<ElementLine>) -> Self {
278 self.panel_grid_major_x = el;
279 self
280 }
281
282 pub fn set_panel_grid_major_y(mut self, el: Option<ElementLine>) -> Self {
283 self.panel_grid_major_y = el;
284 self
285 }
286
287 pub fn set_panel_grid_minor_x(mut self, el: Option<ElementLine>) -> Self {
288 self.panel_grid_minor_x = el;
289 self
290 }
291
292 pub fn set_panel_grid_minor_y(mut self, el: Option<ElementLine>) -> Self {
293 self.panel_grid_minor_y = el;
294 self
295 }
296
297 pub fn set_panel_border(mut self, el: ElementLine) -> Self {
298 self.panel_border = el;
299 self
300 }
301
302 pub fn set_legend_background(mut self, el: ElementRect) -> Self {
303 self.legend_background = el;
304 self
305 }
306
307 pub fn set_legend_key(mut self, el: ElementRect) -> Self {
308 self.legend_key = el;
309 self
310 }
311
312 pub fn set_strip_background(mut self, el: ElementRect) -> Self {
313 self.strip_background = el;
314 self
315 }
316
317 pub fn set_axis_ticks_length(mut self, val: f64) -> Self {
318 self.axis_ticks_length = val;
319 self
320 }
321
322 pub fn set_legend_key_width(mut self, val: f64) -> Self {
323 self.legend_key_width = val;
324 self
325 }
326
327 pub fn set_legend_key_height(mut self, val: f64) -> Self {
328 self.legend_key_height = val;
329 self
330 }
331
332 pub fn set_legend_spacing(mut self, val: f64) -> Self {
333 self.legend_spacing = val;
334 self
335 }
336
337 pub fn set_legend_margin(mut self, margin: Margin) -> Self {
338 self.legend_margin = margin;
339 self
340 }
341
342 pub fn set_panel_spacing(mut self, val: f64) -> Self {
343 self.panel_spacing = val;
344 self
345 }
346
347 pub fn set_panel_spacing_x(mut self, val: Option<f64>) -> Self {
348 self.panel_spacing_x = val;
349 self
350 }
351
352 pub fn set_panel_spacing_y(mut self, val: Option<f64>) -> Self {
353 self.panel_spacing_y = val;
354 self
355 }
356
357 pub fn update(mut self, upd: ThemeUpdate) -> Self {
360 if let Some(v) = upd.text {
361 self.text = v;
362 }
363 if let Some(v) = upd.title {
364 self.title = v;
365 }
366 if let Some(v) = upd.subtitle {
367 self.subtitle = v;
368 }
369 if let Some(v) = upd.caption {
370 self.caption = v;
371 }
372 if let Some(v) = upd.axis_text_x {
373 self.axis_text_x = v;
374 }
375 if let Some(v) = upd.axis_text_y {
376 self.axis_text_y = v;
377 }
378 if let Some(v) = upd.axis_title_x {
379 self.axis_title_x = v;
380 }
381 if let Some(v) = upd.axis_title_y {
382 self.axis_title_y = v;
383 }
384 if let Some(v) = upd.axis_line {
385 self.axis_line = v;
386 }
387 if let Some(v) = upd.axis_ticks {
388 self.axis_ticks = v;
389 }
390 if let Some(v) = upd.panel_background {
391 self.panel_background = v;
392 }
393 if let Some(v) = upd.panel_grid_major {
394 self.panel_grid_major = v;
395 }
396 if let Some(v) = upd.panel_grid_minor {
397 self.panel_grid_minor = v;
398 }
399 if let Some(v) = upd.panel_border {
400 self.panel_border = v;
401 }
402 if let Some(v) = upd.plot_background {
403 self.plot_background = v;
404 }
405 if let Some(v) = upd.legend_position {
406 self.legend_position = v;
407 }
408 if let Some(v) = upd.legend_title {
409 self.legend_title = v;
410 }
411 if let Some(v) = upd.legend_text {
412 self.legend_text = v;
413 }
414 if let Some(v) = upd.legend_background {
415 self.legend_background = v;
416 }
417 if let Some(v) = upd.strip_text {
418 self.strip_text = v;
419 }
420 if let Some(v) = upd.strip_background {
421 self.strip_background = v;
422 }
423 if let Some(v) = upd.plot_margin {
424 self.plot_margin = v;
425 }
426 self
427 }
428}
429
430#[derive(Clone, Debug, Default)]
433pub struct ThemeUpdate {
434 pub text: Option<ElementText>,
435 pub title: Option<ElementText>,
436 pub subtitle: Option<ElementText>,
437 pub caption: Option<ElementText>,
438 pub axis_text_x: Option<ElementText>,
439 pub axis_text_y: Option<ElementText>,
440 pub axis_title_x: Option<ElementText>,
441 pub axis_title_y: Option<ElementText>,
442 pub axis_line: Option<ElementLine>,
443 pub axis_ticks: Option<ElementLine>,
444 pub panel_background: Option<ElementRect>,
445 pub panel_grid_major: Option<ElementLine>,
446 pub panel_grid_minor: Option<ElementLine>,
447 pub panel_border: Option<ElementLine>,
448 pub plot_background: Option<ElementRect>,
449 pub legend_position: Option<LegendPosition>,
450 pub legend_title: Option<ElementText>,
451 pub legend_text: Option<ElementText>,
452 pub legend_background: Option<ElementRect>,
453 pub strip_text: Option<ElementText>,
454 pub strip_background: Option<ElementRect>,
455 pub plot_margin: Option<Margin>,
456}
457
458impl Default for Theme {
459 fn default() -> Self {
460 presets::theme_gray()
461 }
462}