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