1pub mod oscilloscope;
2pub mod vectorscope;
3pub mod spectroscope;
4
5use crossterm::event::Event;
6use ratatui::{widgets::{Dataset, Axis, GraphType}, style::{Style, Color}, symbols::Marker};
7
8use crate::input::Matrix;
9
10pub enum Dimension {
11 X, Y
12}
13
14#[derive(Debug, Clone, Default)]
15pub struct GraphConfig {
16 pub pause: bool,
17 pub samples: u32,
18 pub sampling_rate: u32,
19 pub scale: f64,
20 pub width: u32,
21 pub scatter: bool,
22 pub references: bool,
23 pub show_ui: bool,
24 pub marker_type: Marker,
25 pub palette: Vec<Color>,
26 pub labels_color: Color,
27 pub axis_color: Color,
28}
29
30impl GraphConfig {
31 pub fn palette(&self, index: usize) -> Color {
32 *self.palette.get(index % self.palette.len()).unwrap_or(&Color::White)
33 }
34}
35
36#[allow(clippy::ptr_arg)] pub trait DisplayMode {
38 fn axis(&self, cfg: &GraphConfig, dimension: Dimension) -> Axis; fn process(&mut self, cfg: &GraphConfig, data: &Matrix<f64>) -> Vec<DataSet>;
41 fn mode_str(&self) -> &'static str;
42
43 fn channel_name(&self, index: usize) -> String { format!("{}", index) }
45 fn header(&self, _cfg: &GraphConfig) -> String { "".into() }
46 fn references(&self, _cfg: &GraphConfig) -> Vec<DataSet> { vec![] }
47 fn handle(&mut self, _event: Event) {}
48}
49
50pub struct DataSet {
51 name: Option<String>,
52 data: Vec<(f64, f64)>,
53 marker_type: Marker,
54 graph_type: GraphType,
55 color: Color,
56}
57
58impl<'a> From::<&'a DataSet> for Dataset<'a> {
59 fn from(ds: &'a DataSet) -> Dataset<'a> {
60 let mut out = Dataset::default(); if let Some(name) = &ds.name {
62 out = out.name(name.clone());
63 }
64 out
65 .marker(ds.marker_type)
66 .graph_type(ds.graph_type)
67 .style(Style::default().fg(ds.color))
68 .data(&ds.data)
69 }
70}
71
72impl DataSet {
74 pub fn new(
75 name: Option<String>,
76 data: Vec<(f64, f64)>,
77 marker_type: Marker,
78 graph_type: GraphType,
79 color: Color
80 ) -> Self {
81 DataSet { name, data, marker_type, graph_type, color }
82 }
83}
84
85
86pub(crate) fn update_value_f(val: &mut f64, base: f64, magnitude: f64, range: std::ops::Range<f64>) {
87 let delta = base * magnitude;
88 if *val + delta > range.end {
89 *val = range.end
90 } else if *val + delta < range.start {
91 *val = range.start
92 } else {
93 *val += delta;
94 }
95}
96
97pub(crate) fn update_value_i(val: &mut u32, inc: bool, base: u32, magnitude: f64, range: std::ops::Range<u32>) {
98 let delta = (base as f64 * magnitude) as u32;
99 if inc {
100 if range.end - delta < *val {
101 *val = range.end
102 } else {
103 *val += delta
104 }
105 } else if range.start + delta > *val {
106 *val = range.start
107 } else {
108 *val -= delta
109 }
110}