Skip to main content

tui_realm_stdlib/components/chart/
dataset.rs

1use tuirealm::props::{LineStatic, Style};
2use tuirealm::ratatui::symbols::Marker;
3use tuirealm::ratatui::widgets::{Dataset as TuiDataset, GraphType};
4
5/// Dataset describes a set of data for a chart.
6///
7/// This mainly exists to map to ratatui's [`Dataset`](TuiDataset), which does not allow owned data.
8#[derive(Clone, Debug)]
9pub struct ChartDataset {
10    pub name: LineStatic,
11    pub marker: Marker,
12    pub graph_type: GraphType,
13    pub style: Style,
14    data: Vec<(f64, f64)>,
15}
16
17impl Default for ChartDataset {
18    fn default() -> Self {
19        Self {
20            name: LineStatic::default(),
21            marker: Marker::Dot,
22            graph_type: GraphType::Scatter,
23            style: Style::default(),
24            data: Vec::default(),
25        }
26    }
27}
28
29impl ChartDataset {
30    /// Set a name for the dataset.
31    pub fn name<S: Into<LineStatic>>(mut self, name: S) -> Self {
32        self.name = name.into();
33        self
34    }
35
36    /// Set the [`Marker`] type for the dataset.
37    pub fn marker(mut self, m: Marker) -> Self {
38        self.marker = m;
39        self
40    }
41
42    /// Set the [`GraphType`] for the dataset.
43    pub fn graph_type(mut self, g: GraphType) -> Self {
44        self.graph_type = g;
45        self
46    }
47
48    /// Set Style for the dataset.
49    ///
50    /// This style is used for the data points and the legenend (if not overwritten by the text's style).
51    ///
52    /// Read more in [`Dataset::style`](TuiDataset::style).
53    pub fn style(mut self, s: Style) -> Self {
54        self.style = s;
55        self
56    }
57
58    /// Set the data for this dataset.
59    pub fn data(mut self, data: Vec<(f64, f64)>) -> Self {
60        self.data = data;
61        self
62    }
63
64    /// Push a new point to the back of this dataset.
65    pub fn push(&mut self, point: (f64, f64)) {
66        self.data.push(point);
67    }
68
69    /// Pop the last point from this dataset.
70    pub fn pop(&mut self) {
71        self.data.pop();
72    }
73
74    /// Pop the first point in this dataset.
75    pub fn pop_front(&mut self) {
76        if !self.data.is_empty() {
77            self.data.remove(0);
78        }
79    }
80
81    /// Get a reference to the data.
82    pub fn get_data(&self) -> &[(f64, f64)] {
83        &self.data
84    }
85
86    /// Create ratatui [`Dataset`](TuiDataset) from the current [`ChartDataset`].
87    ///
88    /// Only elements from `start` are included.
89    pub fn as_tuichart<'a>(&'a self, start: usize) -> TuiDataset<'a> {
90        // Prepare data storage
91        TuiDataset::default()
92            .name(self.name.clone())
93            .marker(self.marker)
94            .graph_type(self.graph_type)
95            .style(self.style)
96            .data(&self.get_data()[start..])
97    }
98}
99
100impl PartialEq for ChartDataset {
101    fn eq(&self, other: &Self) -> bool {
102        self.name == other.name && self.data == other.data
103    }
104}
105
106impl<'a> From<&'a ChartDataset> for TuiDataset<'a> {
107    fn from(data: &'a ChartDataset) -> TuiDataset<'a> {
108        data.as_tuichart(0)
109    }
110}
111
112#[cfg(test)]
113mod test {
114
115    use pretty_assertions::assert_eq;
116    use tuirealm::ratatui::style::Color;
117
118    use super::*;
119
120    #[test]
121    fn dataset() {
122        let mut dataset: ChartDataset = ChartDataset::default()
123            .name("Avg temperatures")
124            .graph_type(GraphType::Scatter)
125            .marker(Marker::Braille)
126            .style(Style::default().fg(Color::Cyan))
127            .data(vec![
128                (0.0, -1.0),
129                (1.0, 1.0),
130                (2.0, 3.0),
131                (3.0, 7.0),
132                (4.0, 11.0),
133                (5.0, 15.0),
134                (6.0, 17.0),
135                (7.0, 17.0),
136                (8.0, 13.0),
137                (9.0, 9.0),
138                (10.0, 4.0),
139                (11.0, 0.0),
140            ]);
141        assert_eq!(dataset.name.to_string(), "Avg temperatures");
142        assert_eq!(dataset.style.fg.unwrap_or(Color::Reset), Color::Cyan);
143        assert_eq!(dataset.get_data().len(), 12);
144        // mut
145        dataset.push((12.0, 1.0));
146        assert_eq!(dataset.get_data().len(), 13);
147        dataset.pop();
148        assert_eq!(dataset.get_data().len(), 12);
149        dataset.pop_front();
150        assert_eq!(dataset.get_data().len(), 11);
151        // From
152        let _: TuiDataset = TuiDataset::from(&dataset);
153    }
154}