diff --git a/src/device.rs b/src/device.rs index 6ad0e01..364bc80 100644 --- a/src/device.rs +++ b/src/device.rs @@ -14,6 +14,11 @@ use bevy::{ prelude::Deref, }; use rapidhash::RapidHashSet; +use ratatui::{ + style::{Color, Stylize}, + text::{Line, Span, Text, ToSpan}, + widgets::{Block, Padding, Paragraph, Widget}, +}; use crate::net::DiscoverResponse; @@ -39,6 +44,31 @@ pub struct DeviceDetector { pub duty: u16, } +impl Widget for DeviceDetector { + fn render(self, area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer) + where + Self: Sized, + { + let detector_lines = [ + Line::from_iter([Span::raw("Threshold: "), self.blip_threshold.to_span()]), + Line::from_iter([Span::raw("Blip Size: "), self.blip_size.to_span()]), + Line::from_iter([Span::raw("Max Duty: "), self.max_duty.to_span()]), + Line::from_iter([Span::raw("Current Duty: "), self.duty.to_span()]), + ]; + + let detector_info = Paragraph::new(Text::from_iter(detector_lines)) + .block( + Block::bordered() + .title("Settings") + .padding(Padding::horizontal(1)) + .border_style(Color::LightGreen), + ) + .white(); + + detector_info.render(area, buf); + } +} + fn on_remove_device(mut world: DeferredWorld, context: HookContext) { let component = world .entity(context.entity) diff --git a/src/views/monitoring.rs b/src/views/monitoring.rs index accc10b..7d25c57 100644 --- a/src/views/monitoring.rs +++ b/src/views/monitoring.rs @@ -20,7 +20,7 @@ use ratatui::{ layout::{Constraint, HorizontalAlignment, Layout}, style::{Color, Stylize}, text::{Line, Span, Text, ToSpan}, - widgets::{Axis, Block, Chart, Dataset, Padding, Paragraph}, + widgets::{Axis, Block, Chart, Dataset, Padding, Paragraph, Widget}, }; use striker_proto::{Response, StrikerRequest, StrikerResponse, Update}; @@ -206,27 +206,87 @@ pub fn monitoring_view( let timestamp = latest_signal.map(|(t, _, _)| t); + let info = DeviceInfo { + name: device, + connected: &connected, + timestamp, + level: latest_level, + }; + + let signal_chart = SignalChart { + signal: latest_signal, + }; + + let help = Paragraph::new("Keys: 'q'/ESC Quit, BACKSPACE Return to Device select") + .block( + Block::bordered() + .padding(Padding::horizontal(2)) + .border_style(Color::LightGreen), + ) + .white(); + + let detector = detector.copied().unwrap_or_default(); + + frame.render_widget(info, device_block); + frame.render_widget(signal_chart, chart_block); + frame.render_widget(detector, detector_block); + frame.render_widget(help, bottom); + })?; + + Ok(()) +} + +struct DeviceInfo<'a> { + name: &'a Name, + connected: &'a ConnectedDevice, + timestamp: Option<&'a Timestamp>, + level: Option<&'a StormLevel>, +} + +impl Widget for DeviceInfo<'_> { + fn render(self, area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer) + where + Self: Sized, + { let lines = [ - Line::from(device.to_span()), - Line::from_iter([Span::raw("Status: "), connected.connection_state.to_span()]), + Line::from(self.name.to_span()), + Line::from_iter([ + Span::raw("Status: "), + self.connected.connection_state.to_span(), + ]), ] .into_iter() - .chain(timestamp.map(|t| Line::from(t.0.to_span()))) + .chain(self.timestamp.map(|t| Line::from(t.0.to_span()))) .chain( - latest_level.map(|level| Line::from_iter([Span::raw("Level: "), level.0.to_span()])), + self.level + .map(|level| Line::from_iter([Span::raw("Level: "), level.0.to_span()])), ); let info = Paragraph::new(Text::from_iter(lines)) .block( Block::bordered() - .padding(Padding::horizontal(2)) + .padding(Padding::horizontal(1)) .title("Device") .title_alignment(HorizontalAlignment::Center) .border_style(Color::LightGreen), ) .white(); - let (data, detected) = latest_signal + info.render(area, buf); + } +} + +struct SignalChart<'a> { + signal: Option<(&'a Timestamp, &'a StormSignal, &'a SignalPeaks)>, +} + +impl Widget for SignalChart<'_> { + fn render(self, area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer) + where + Self: Sized, + { + let (data, detected) = self + .signal .map(|(_, samples, signals)| { ( samples @@ -298,38 +358,7 @@ pub fn monitoring_view( ) .block(block); - let help = Paragraph::new("Keys: 'q'/ESC Quit, BACKSPACE Return to Device select") - .block( - Block::bordered() - .padding(Padding::horizontal(2)) - .border_style(Color::LightGreen), - ) - .white(); - - let detector = detector.copied().unwrap_or_default(); - - let detector_lines = [ - Line::from_iter([Span::raw("Threshold: "), detector.blip_threshold.to_span()]), - Line::from_iter([Span::raw("Blip Size: "), detector.blip_size.to_span()]), - Line::from_iter([Span::raw("Max Duty: "), detector.max_duty.to_span()]), - Line::from_iter([Span::raw("Current Duty: "), detector.duty.to_span()]), - ]; - - let detector_info = Paragraph::new(Text::from_iter(detector_lines)) - .block( - Block::bordered() - .title("Settings") - .padding(Padding::horizontal(2)) - .border_style(Color::LightGreen), - ) - .white(); - - frame.render_widget(info, device_block); - frame.render_widget(chart2, chart_block); - frame.render_widget(chart, chart_block); - frame.render_widget(detector_info, detector_block); - frame.render_widget(help, bottom); - })?; - - Ok(()) + chart2.render(area, buf); + chart.render(area, buf); + } }