scope/display/
vectorscope.rs

1use ratatui::{widgets::{Axis, GraphType}, style::Style, text::Span};
2
3use crate::input::Matrix;
4
5use super::{DisplayMode, GraphConfig, DataSet, Dimension};
6
7#[derive(Default)]
8pub struct Vectorscope {}
9
10impl DisplayMode for Vectorscope {
11	fn mode_str(&self) -> &'static str {
12		"vector"
13	}
14
15	fn channel_name(&self, index: usize) -> String {
16		format!("{}", index)
17	}
18
19	fn header(&self, _: &GraphConfig) -> String {
20		"live".into()
21	}
22
23	fn axis(&self, cfg: &GraphConfig, dimension: Dimension) -> Axis {
24		let (name, bounds) = match dimension {
25			Dimension::X => ("left -", [-cfg.scale, cfg.scale]),
26			Dimension::Y => ("| right", [-cfg.scale, cfg.scale]),
27		};
28		let mut a = Axis::default();
29		if cfg.show_ui { // TODO don't make it necessary to check show_ui inside here
30			a = a.title(Span::styled(name, Style::default().fg(cfg.labels_color)));
31		}
32		a.style(Style::default().fg(cfg.axis_color)).bounds(bounds)
33	}
34
35	fn references(&self, cfg: &GraphConfig) -> Vec<DataSet> {
36		vec![
37			DataSet::new(None, vec![(-cfg.scale, 0.0), (cfg.scale, 0.0)], cfg.marker_type, GraphType::Line, cfg.axis_color), 
38			DataSet::new(None, vec![(0.0, -cfg.scale), (0.0, cfg.scale)], cfg.marker_type, GraphType::Line, cfg.axis_color),
39		]
40	}
41
42	fn process(&mut self, cfg: &GraphConfig, data: &Matrix<f64>) -> Vec<DataSet> {
43		let mut out = Vec::new();
44
45		for (n, chunk) in data.chunks(2).enumerate() {
46			let mut tmp = vec![];
47			match chunk.len() {
48				2 => {
49					for i in 0..std::cmp::min(chunk[0].len(), chunk[1].len()) {
50						if i > cfg.samples as usize { break }
51						tmp.push((chunk[0][i], chunk[1][i]));
52					}
53				},
54				1 => {
55					for i in 0..chunk[0].len() {
56						if i > cfg.samples as usize { break }
57						tmp.push((chunk[0][i], i as f64));
58					}
59				},
60				_ => continue,
61			}
62			// split it in two for easier coloring
63			// TODO configure splitting in multiple parts?
64			let pivot = tmp.len() / 2;
65			out.push(DataSet::new(
66				Some(self.channel_name((n * 2) + 1)),
67				tmp[pivot..].to_vec(),
68				cfg.marker_type,
69				if cfg.scatter { GraphType::Scatter } else { GraphType::Line },
70				cfg.palette((n * 2) + 1),
71			));
72			out.push(DataSet::new(
73				Some(self.channel_name(n * 2)),
74				tmp[..pivot].to_vec(),
75				cfg.marker_type,
76				if cfg.scatter { GraphType::Scatter } else { GraphType::Line },
77				cfg.palette(n * 2),
78			));
79		}
80
81		out
82	}
83}