1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use super::axis::Axis;
use super::curve::Curve;
use crate::tsdb::{Aggregation, Sample, SampleMetrics};
#[derive(Clone)]
pub struct Chart {
pub title: Option<String>,
pub x_axis: Axis,
pub y_axis: Axis,
pub grid: bool,
pub curves: Vec<Curve>,
}
impl Default for Chart {
fn default() -> Self {
Chart {
title: None,
x_axis: Axis::default(),
y_axis: Axis::default(),
grid: true,
curves: vec![],
}
}
}
impl Chart {
pub fn set_title(&mut self, title: &str) {
self.title = Some(title.to_string());
}
pub fn set_xlabel(&mut self, label: &str) {
self.x_axis.label = Some(label.to_string());
}
pub fn set_ylabel(&mut self, label: &str) {
self.y_axis.label = Some(label.to_string());
}
pub fn add_curve(&mut self, curve: Curve) {
self.curves.push(curve);
}
pub fn zoom_horizontal(&mut self, amount: f64) {
let domain = self.x_axis.domain();
let step = domain * amount;
let x1 = self.x_axis.begin() - step;
let x2 = self.x_axis.end() + step;
self.x_axis.set_limits(x1, x2);
}
pub fn zoom_vertical(&mut self, amount: f64) {
let domain = self.y_axis.domain();
let step = domain * amount;
let y1 = self.y_axis.begin() - step;
let y2 = self.y_axis.end() + step;
self.y_axis.set_limits(y1, y2);
}
pub fn pan_horizontal(&mut self, amount: f64) {
let domain = self.x_axis.domain();
let step = domain * amount;
let x1 = self.x_axis.begin() + step;
let x2 = self.x_axis.end() + step;
self.x_axis.set_limits(x1, x2);
}
pub fn pan_vertical(&mut self, amount: f64) {
let domain = self.y_axis.domain();
let step = domain * amount;
let y1 = self.y_axis.begin() + step;
let y2 = self.y_axis.end() + step;
self.y_axis.set_limits(y1, y2);
}
pub fn autoscale(&mut self) {
let summaries: Vec<Aggregation<Sample, SampleMetrics>> =
self.curves.iter().filter_map(|c| c.summary()).collect();
if let Some(summary) = Aggregation::from_aggregations(&summaries) {
self.x_axis
.set_limits(summary.timespan.start.amount, summary.timespan.end.amount);
self.y_axis
.set_limits(summary.metrics().min, summary.metrics().max);
}
}
}