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