1use esoc_gfx::color::Color;
5use esoc_gfx::style::DashPattern;
6
7use crate::axis::AxisConfig;
8use crate::chart::{
9 BarSeries, BoxPlotSeries, ErrorBarSeries, HeatmapSeries, HistogramSeries, LineSeries,
10 ScatterSeries,
11};
12use crate::legend::LegendPosition;
13use crate::series::SeriesRenderer;
14
15#[derive(Default)]
17pub struct Axes {
18 pub title: Option<String>,
20 pub x_config: AxisConfig,
22 pub y_config: AxisConfig,
24 pub(crate) series: Vec<Box<dyn SeriesRenderer>>,
26 pub legend_position: LegendPosition,
28 pub show_legend: bool,
30}
31
32impl Axes {
33 pub fn new() -> Self {
35 Self {
36 show_legend: true,
37 ..Self::default()
38 }
39 }
40
41 pub fn title(&mut self, title: impl Into<String>) -> &mut Self {
43 self.title = Some(title.into());
44 self
45 }
46
47 pub fn x_label(&mut self, label: impl Into<String>) -> &mut Self {
49 self.x_config.label = Some(label.into());
50 self
51 }
52
53 pub fn y_label(&mut self, label: impl Into<String>) -> &mut Self {
55 self.y_config.label = Some(label.into());
56 self
57 }
58
59 pub fn x_range(&mut self, min: f64, max: f64) -> &mut Self {
61 self.x_config.range = Some((min, max));
62 self
63 }
64
65 pub fn y_range(&mut self, min: f64, max: f64) -> &mut Self {
67 self.y_config.range = Some((min, max));
68 self
69 }
70
71 pub fn x_axis(&mut self, config: AxisConfig) -> &mut Self {
73 self.x_config = config;
74 self
75 }
76
77 pub fn y_axis(&mut self, config: AxisConfig) -> &mut Self {
79 self.y_config = config;
80 self
81 }
82
83 pub fn legend(&mut self, position: LegendPosition) -> &mut Self {
85 self.legend_position = position;
86 self
87 }
88
89 pub fn line(&mut self, x: &[f64], y: &[f64]) -> LineBuilder<'_> {
91 LineBuilder {
92 axes: self,
93 series: Some(LineSeries::new(x, y)),
94 }
95 }
96
97 pub fn scatter(&mut self, x: &[f64], y: &[f64]) -> ScatterBuilder<'_> {
99 ScatterBuilder {
100 axes: self,
101 series: Some(ScatterSeries::new(x, y)),
102 }
103 }
104
105 pub fn bar(&mut self, x: &[f64], heights: &[f64]) -> BarBuilder<'_> {
107 BarBuilder {
108 axes: self,
109 series: Some(BarSeries::new(x, heights)),
110 }
111 }
112
113 pub fn histogram(&mut self, data: &[f64]) -> HistogramBuilder<'_> {
115 HistogramBuilder {
116 axes: self,
117 series: Some(HistogramSeries::new(data)),
118 }
119 }
120
121 pub fn boxplot(&mut self, datasets: Vec<Vec<f64>>) -> BoxPlotBuilder<'_> {
123 BoxPlotBuilder {
124 axes: self,
125 series: Some(BoxPlotSeries::new(datasets)),
126 }
127 }
128
129 pub fn heatmap(&mut self, data: Vec<Vec<f64>>) -> HeatmapBuilder<'_> {
131 HeatmapBuilder {
132 axes: self,
133 series: Some(HeatmapSeries::new(data)),
134 }
135 }
136
137 pub fn errorbar(&mut self, x: &[f64], y: &[f64], err: &[f64]) -> ErrorBarBuilder<'_> {
139 ErrorBarBuilder {
140 axes: self,
141 series: Some(ErrorBarSeries::new(x, y, err)),
142 }
143 }
144
145 pub fn add_series(&mut self, series: Box<dyn SeriesRenderer>) -> &mut Self {
147 self.series.push(series);
148 self
149 }
150}
151
152pub struct LineBuilder<'a> {
158 axes: &'a mut Axes,
159 series: Option<LineSeries>,
160}
161
162impl<'a> LineBuilder<'a> {
163 pub fn label(mut self, label: impl Into<String>) -> Self {
165 if let Some(s) = &mut self.series {
166 s.label = Some(label.into());
167 }
168 self
169 }
170
171 pub fn color(mut self, color: Color) -> Self {
173 if let Some(s) = &mut self.series {
174 s.color = Some(color);
175 }
176 self
177 }
178
179 pub fn width(mut self, width: f64) -> Self {
181 if let Some(s) = &mut self.series {
182 s.width = Some(width);
183 }
184 self
185 }
186
187 pub fn dash(mut self, dashes: &[f64]) -> Self {
189 if let Some(s) = &mut self.series {
190 s.dash = Some(DashPattern::new(dashes));
191 }
192 self
193 }
194
195 pub fn done(mut self) -> &'a mut Axes {
197 if let Some(s) = self.series.take() {
198 self.axes.series.push(Box::new(s));
199 }
200 self.axes
201 }
202}
203
204pub struct ScatterBuilder<'a> {
206 axes: &'a mut Axes,
207 series: Option<ScatterSeries>,
208}
209
210impl<'a> ScatterBuilder<'a> {
211 pub fn label(mut self, label: impl Into<String>) -> Self {
213 if let Some(s) = &mut self.series {
214 s.label = Some(label.into());
215 }
216 self
217 }
218
219 pub fn color(mut self, color: Color) -> Self {
221 if let Some(s) = &mut self.series {
222 s.color = Some(color);
223 }
224 self
225 }
226
227 pub fn radius(mut self, r: f64) -> Self {
229 if let Some(s) = &mut self.series {
230 s.radius = Some(r);
231 }
232 self
233 }
234
235 pub fn done(mut self) -> &'a mut Axes {
237 if let Some(s) = self.series.take() {
238 self.axes.series.push(Box::new(s));
239 }
240 self.axes
241 }
242}
243
244pub struct BarBuilder<'a> {
246 axes: &'a mut Axes,
247 series: Option<BarSeries>,
248}
249
250impl<'a> BarBuilder<'a> {
251 pub fn label(mut self, label: impl Into<String>) -> Self {
253 if let Some(s) = &mut self.series {
254 s.label = Some(label.into());
255 }
256 self
257 }
258
259 pub fn color(mut self, color: Color) -> Self {
261 if let Some(s) = &mut self.series {
262 s.color = Some(color);
263 }
264 self
265 }
266
267 pub fn bar_width(mut self, width: f64) -> Self {
269 if let Some(s) = &mut self.series {
270 s.bar_width = width;
271 }
272 self
273 }
274
275 pub fn horizontal(mut self) -> Self {
277 if let Some(s) = &mut self.series {
278 s.horizontal = true;
279 }
280 self
281 }
282
283 pub fn done(mut self) -> &'a mut Axes {
285 if let Some(s) = self.series.take() {
286 self.axes.series.push(Box::new(s));
287 }
288 self.axes
289 }
290}
291
292pub struct HistogramBuilder<'a> {
294 axes: &'a mut Axes,
295 series: Option<HistogramSeries>,
296}
297
298impl<'a> HistogramBuilder<'a> {
299 pub fn label(mut self, label: impl Into<String>) -> Self {
301 if let Some(s) = &mut self.series {
302 s.label = Some(label.into());
303 }
304 self
305 }
306
307 pub fn color(mut self, color: Color) -> Self {
309 if let Some(s) = &mut self.series {
310 s.color = Some(color);
311 }
312 self
313 }
314
315 pub fn bins(mut self, bins: usize) -> Self {
317 if let Some(s) = &mut self.series {
318 s.bin_count = Some(bins);
319 }
320 self
321 }
322
323 pub fn done(mut self) -> &'a mut Axes {
325 if let Some(s) = self.series.take() {
326 self.axes.series.push(Box::new(s));
327 }
328 self.axes
329 }
330}
331
332pub struct BoxPlotBuilder<'a> {
334 axes: &'a mut Axes,
335 series: Option<BoxPlotSeries>,
336}
337
338impl<'a> BoxPlotBuilder<'a> {
339 pub fn label(mut self, label: impl Into<String>) -> Self {
341 if let Some(s) = &mut self.series {
342 s.label = Some(label.into());
343 }
344 self
345 }
346
347 pub fn labels(mut self, labels: Vec<String>) -> Self {
349 if let Some(s) = &mut self.series {
350 s.labels = Some(labels);
351 }
352 self
353 }
354
355 pub fn done(mut self) -> &'a mut Axes {
357 if let Some(s) = self.series.take() {
358 self.axes.series.push(Box::new(s));
359 }
360 self.axes
361 }
362}
363
364pub struct HeatmapBuilder<'a> {
366 axes: &'a mut Axes,
367 series: Option<HeatmapSeries>,
368}
369
370impl<'a> HeatmapBuilder<'a> {
371 pub fn label(mut self, label: impl Into<String>) -> Self {
373 if let Some(s) = &mut self.series {
374 s.label = Some(label.into());
375 }
376 self
377 }
378
379 pub fn annotate(mut self) -> Self {
381 if let Some(s) = &mut self.series {
382 s.annotate = true;
383 }
384 self
385 }
386
387 pub fn row_labels(mut self, labels: Vec<String>) -> Self {
389 if let Some(s) = &mut self.series {
390 s.row_labels = Some(labels);
391 }
392 self
393 }
394
395 pub fn col_labels(mut self, labels: Vec<String>) -> Self {
397 if let Some(s) = &mut self.series {
398 s.col_labels = Some(labels);
399 }
400 self
401 }
402
403 pub fn done(mut self) -> &'a mut Axes {
405 if let Some(s) = self.series.take() {
406 self.axes.series.push(Box::new(s));
407 }
408 self.axes
409 }
410}
411
412pub struct ErrorBarBuilder<'a> {
414 axes: &'a mut Axes,
415 series: Option<ErrorBarSeries>,
416}
417
418impl<'a> ErrorBarBuilder<'a> {
419 pub fn label(mut self, label: impl Into<String>) -> Self {
421 if let Some(s) = &mut self.series {
422 s.label = Some(label.into());
423 }
424 self
425 }
426
427 pub fn color(mut self, color: Color) -> Self {
429 if let Some(s) = &mut self.series {
430 s.color = Some(color);
431 }
432 self
433 }
434
435 pub fn done(mut self) -> &'a mut Axes {
437 if let Some(s) = self.series.take() {
438 self.axes.series.push(Box::new(s));
439 }
440 self.axes
441 }
442}