thd75_tui/ui/
mod.rs

1mod aprs;
2mod band;
3mod channels;
4mod dstar;
5mod fm_radio;
6mod gps;
7mod help;
8mod mcp;
9mod settings;
10mod status_bar;
11
12use ratatui::Frame;
13use ratatui::layout::{Constraint, Direction, Layout};
14
15use crate::app::{App, MainView, Pane};
16
17/// Render the full TUI frame.
18pub(crate) fn render(app: &App, frame: &mut Frame<'_>) {
19    let chunks = Layout::default()
20        .direction(Direction::Vertical)
21        .constraints([
22            Constraint::Length(6), // Band row (A + B side by side)
23            Constraint::Min(8),    // Main content row
24            Constraint::Length(1), // Status bar
25        ])
26        .split(frame.area());
27
28    // Band row: split horizontally for Band A and Band B
29    let band_row = Layout::default()
30        .direction(Direction::Horizontal)
31        .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
32        .split(chunks[0]);
33
34    band::render(app, frame, band_row[0], Pane::BandA);
35    band::render(app, frame, band_row[1], Pane::BandB);
36
37    // Main content row: split for list + detail
38    let main_row = Layout::default()
39        .direction(Direction::Horizontal)
40        .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
41        .split(chunks[1]);
42
43    // Main content + Detail
44    match app.main_view {
45        MainView::Channels => {
46            channels::render_list(app, frame, main_row[0]);
47            channels::render_detail(app, frame, main_row[1]);
48        }
49        MainView::SettingsCat => {
50            settings::render_cat(app, frame, main_row[0], main_row[1]);
51        }
52        MainView::SettingsMcp => {
53            settings::render_mcp(app, frame, main_row[0], main_row[1]);
54        }
55        MainView::Aprs => {
56            aprs::render(app, frame, main_row[0], main_row[1]);
57        }
58        MainView::DStar => {
59            dstar::render(app, frame, main_row[0], main_row[1]);
60        }
61        MainView::Gps => {
62            gps::render(app, frame, main_row[0], main_row[1]);
63        }
64        MainView::Mcp => {
65            mcp::render(app, frame, main_row[0], main_row[1]);
66        }
67        MainView::FmRadio => {
68            fm_radio::render(app, frame, main_row[0], main_row[1]);
69        }
70    }
71
72    // Status bar
73    status_bar::render(app, frame, chunks[2]);
74
75    // Help overlay (on top of everything)
76    if app.show_help {
77        help::render(frame);
78    }
79}
80
81fn border_style(app: &App, pane: Pane) -> ratatui::style::Style {
82    use ratatui::style::{Color, Style};
83    if app.focus == pane {
84        Style::default().fg(Color::Cyan)
85    } else {
86        Style::default().fg(Color::DarkGray)
87    }
88}