-
Notifications
You must be signed in to change notification settings - Fork 18
/
stream.rs
153 lines (132 loc) · 4.94 KB
/
stream.rs
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Hegemon - A modular system monitor
// Copyright (C) 2018-2020 Philipp Emanuel Weidmann <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use termion::color::Fg;
use crate::theme::Theme;
use crate::view::{format_quantity, printed_width};
pub trait StreamProvider {
/// Returns a list of data stream objects.
fn streams(&self) -> Vec<Box<dyn Stream>>;
}
pub trait Stream {
/// Returns the name of this data stream, to be used both as an identifier
/// and for labeling the stream in the user interface.
/// This method **must** return the same value each time it is called,
/// and that value **must** be unique among all data streams.
fn name(&self) -> String;
/// Returns a detailed description of this data stream.
/// This method **must** return the same value each time it is called.
fn description(&self) -> String;
/// Returns the current value of the quantity represented by this data stream,
/// or `None` if no value can be determined at this time.
fn value(&mut self) -> Option<f64>;
/// Returns the minimum value of the quantity represented by this data stream,
/// or `None` to have the minimum dynamically calculated from all value samples.
/// This method **must** return the same value each time it is called.
fn min(&self) -> Option<f64> {
None
}
/// Returns the maximum value of the quantity represented by this data stream,
/// or `None` to have the maximum dynamically calculated from all value samples.
/// This method **must** return the same value each time it is called.
fn max(&self) -> Option<f64> {
None
}
/// Returns a human-readable representation of the given value.
/// The result should make use of the appropriate colors from the given theme.
fn format(&self, value: f64, theme: &Theme) -> String;
/// Returns the maximum width, in characters when printed to the terminal,
/// of all values that the `format` method can return.
/// This method **must** return the same value each time it is called.
fn format_width(&self) -> usize;
}
impl dyn Stream {
#[allow(clippy::too_many_arguments)]
pub fn new(
name: impl Into<String>,
description: impl Into<String>,
value: impl FnMut() -> Option<f64> + 'static,
min: Option<f64>,
max: Option<f64>,
unit: impl Into<String>,
digits_before_decimal: Option<usize>,
precision: usize,
signed: bool,
) -> Box<dyn Stream> {
let unit_1 = unit.into();
let unit_2 = unit_1.clone();
let use_prefix = digits_before_decimal.is_none();
Box::new(SimpleStream {
name: name.into(),
description: description.into(),
value: Box::new(value),
min,
max,
format: Box::new(move |value: f64, theme: &Theme| {
format_quantity(
value,
&unit_1,
use_prefix,
precision,
Fg(theme.stream_number_color),
Fg(theme.stream_unit_color),
)
}),
format_width:
// Sign
(if signed { 1 } else { 0 }) +
// Digits before decimal point
digits_before_decimal.unwrap_or(3) +
// Decimal point and digits after it
(if precision > 0 { 1 + precision } else { 0 }) +
// Unit prefix
(if use_prefix { 1 } else { 0 }) +
// Unit
printed_width(unit_2),
})
}
}
struct SimpleStream {
name: String,
description: String,
value: Box<dyn FnMut() -> Option<f64>>,
min: Option<f64>,
max: Option<f64>,
format: Box<dyn Fn(f64, &Theme) -> String>,
format_width: usize,
}
impl Stream for SimpleStream {
fn name(&self) -> String {
self.name.clone()
}
fn description(&self) -> String {
self.description.clone()
}
fn value(&mut self) -> Option<f64> {
(self.value)()
}
fn min(&self) -> Option<f64> {
self.min
}
fn max(&self) -> Option<f64> {
self.max
}
fn format(&self, value: f64, theme: &Theme) -> String {
(self.format)(value, theme)
}
fn format_width(&self) -> usize {
self.format_width
}
}