1use ratatui::Frame;
2use ratatui::layout::Rect;
3use ratatui::style::{Color, Modifier, Style};
4use ratatui::text::{Line, Span};
5use ratatui::widgets::{Block, Borders, Paragraph};
6
7use kenwood_thd75::types::SMeterReading;
8
9use crate::app::{App, BandState, InputMode, Pane};
10
11pub(crate) fn render(app: &App, frame: &mut Frame<'_>, area: Rect, pane: Pane) {
18 let (title, band) = match pane {
19 Pane::BandA => (" Band A ", &app.state.band_a),
20 Pane::BandB => (" Band B ", &app.state.band_b),
21 _ => return,
22 };
23
24 let block = Block::default()
25 .title(title)
26 .borders(Borders::ALL)
27 .border_style(super::border_style(app, pane));
28
29 let mut lines = band_lines(band);
30
31 if app.focus == pane
33 && let InputMode::FreqInput(ref buf) = app.input_mode
34 {
35 lines.push(Line::from(vec![
36 Span::styled(" Freq: ", Style::default().fg(Color::Yellow)),
37 Span::styled(
38 format!("{buf}▎ MHz"),
39 Style::default()
40 .fg(Color::White)
41 .add_modifier(Modifier::BOLD),
42 ),
43 ]));
44 }
45
46 frame.render_widget(Paragraph::new(lines).block(block), area);
47}
48
49fn band_lines(band: &BandState) -> Vec<Line<'static>> {
55 let freq = format!("{:.6} MHz", band.frequency.as_mhz());
56 let freq_line = Line::from(Span::styled(
57 format!(" {freq}"),
58 Style::default()
59 .fg(Color::White)
60 .add_modifier(Modifier::BOLD),
61 ));
62
63 let busy_span = if band.busy {
64 Span::styled(" RX ", Style::default().fg(Color::Black).bg(Color::Green))
65 } else {
66 Span::raw(" ")
67 };
68
69 let mode_line = Line::from(vec![
70 Span::styled(
71 format!(" {} ", band.mode),
72 Style::default().fg(Color::Cyan),
73 ),
74 Span::styled("Pwr:", Style::default().fg(Color::DarkGray)),
75 Span::styled(
76 power_label(band.power_level).to_string(),
77 Style::default().fg(Color::Yellow),
78 ),
79 Span::raw(" "),
80 Span::styled("Sq:", Style::default().fg(Color::DarkGray)),
81 Span::styled(
82 format!("{}", band.squelch.as_u8()),
83 Style::default().fg(Color::Yellow),
84 ),
85 Span::raw(" "),
86 busy_span,
87 ]);
88
89 let s_meter_line = s_meter_line(band.s_meter);
90
91 let step_str = band
92 .step_size
93 .map_or_else(|| "N/A".into(), |s| format!("{s}"));
94 let mut extra = vec![
95 Span::styled(" Step:", Style::default().fg(Color::DarkGray)),
96 Span::styled(step_str, Style::default().fg(Color::Yellow)),
97 ];
98 if band.attenuator {
99 extra.push(Span::styled(" ATT", Style::default().fg(Color::Red)));
100 }
101 let extra_line = Line::from(extra);
102
103 vec![freq_line, mode_line, s_meter_line, extra_line]
104}
105
106fn s_meter_line(reading: SMeterReading) -> Line<'static> {
111 let label = reading.s_unit(); let s_unit: u8 = match reading.as_u8() {
115 1 => 1,
116 2 => 3,
117 3 => 5,
118 4 => 7,
119 5 => 9,
120 _ => 0,
121 };
122
123 let filled = s_unit.min(9) as usize;
125 let empty = 9 - filled;
126 let bar: String = "▓".repeat(filled) + &"░".repeat(empty);
127
128 let color = if s_unit >= 9 {
129 Color::Red
130 } else if s_unit >= 5 {
131 Color::Yellow
132 } else {
133 Color::Green
134 };
135
136 Line::from(vec![
137 Span::styled(" S ", Style::default().fg(Color::DarkGray)),
138 Span::styled(bar, Style::default().fg(color)),
139 Span::styled(format!(" {label}"), Style::default().fg(Color::White)),
140 ])
141}
142
143const fn power_label(level: kenwood_thd75::types::PowerLevel) -> &'static str {
145 use kenwood_thd75::types::PowerLevel;
146 match level {
147 PowerLevel::High => "H",
148 PowerLevel::Medium => "M",
149 PowerLevel::Low => "L",
150 PowerLevel::ExtraLow => "EL",
151 }
152}