redbear-power: live graph labels, sort indicator, toast for governor/throttle
- Graph titles now show live values: 'CPU 45%', 'Temp 62°C', 'Pwr 8.3W', etc. - Process panel shows sort direction arrow (▲ ascending / ▼ descending) - Governor cycle and throttle mode now trigger flash_toast (floating box) instead of flash_status (keybar only) - BrailleGraph.title changed from &str to String for dynamic titles
This commit is contained in:
@@ -867,7 +867,7 @@ impl App {
|
||||
return;
|
||||
}
|
||||
if let Some(name) = self.cpufreq.cycle() {
|
||||
self.flash_status(format!("governor → {name}"));
|
||||
self.flash_toast(format!("Governor \u{2192} {}", name));
|
||||
} else {
|
||||
self.flash_status("governor cycle: no other governor available");
|
||||
}
|
||||
@@ -989,7 +989,7 @@ impl App {
|
||||
ThrottleMode::User => "USER (no throttling)",
|
||||
ThrottleMode::ForcedMin => "FORCED MIN (manual)",
|
||||
};
|
||||
self.flash_status(format!("throttle mode → {label}"));
|
||||
self.flash_toast(format!("Throttle: {}", label));
|
||||
}
|
||||
|
||||
pub fn flash_status(&mut self, msg: impl Into<String>) {
|
||||
|
||||
@@ -35,7 +35,7 @@ pub struct BrailleGraph<'a> {
|
||||
/// Color for the graph line.
|
||||
pub color: Color,
|
||||
/// Title rendered in the block border.
|
||||
pub title: &'a str,
|
||||
pub title: String,
|
||||
/// Whether this graph has keyboard focus (affects border style).
|
||||
pub focused: bool,
|
||||
/// Optional x-axis label range. If `Some((min_label, max_label))`,
|
||||
@@ -58,7 +58,7 @@ impl<'a> BrailleGraph<'a> {
|
||||
} else {
|
||||
self.theme.border_dim
|
||||
})
|
||||
.title(self.title)
|
||||
.title(self.title.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ mod tests {
|
||||
values: &values,
|
||||
max_value: 50.0,
|
||||
color: ratatui::style::Color::Cyan,
|
||||
title: " Test ",
|
||||
title: " Test ".to_string(),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some(("50".into(), " 0".into())),
|
||||
@@ -311,7 +311,7 @@ mod tests {
|
||||
values: &[],
|
||||
max_value: 100.0,
|
||||
color: ratatui::style::Color::Red,
|
||||
title: " Empty ",
|
||||
title: " Empty ".to_string(),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: None,
|
||||
@@ -332,7 +332,7 @@ mod tests {
|
||||
values: &[42.0],
|
||||
max_value: 100.0,
|
||||
color: ratatui::style::Color::Green,
|
||||
title: " Single ",
|
||||
title: " Single ".to_string(),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: None,
|
||||
|
||||
@@ -450,12 +450,13 @@ fn main() -> io::Result<()> {
|
||||
Constraint::Length(w),
|
||||
]));
|
||||
if ca.width >= 10 && ca.height >= GRAPH_HEIGHT {
|
||||
let cur = app.cpu_graph_history.last().unwrap_or(0.0);
|
||||
f.render_widget(
|
||||
BrailleGraph {
|
||||
values: app.cpu_graph_history.as_slice(),
|
||||
max_value: 100.0,
|
||||
color: Color::Cyan,
|
||||
title: " CPU Load % ",
|
||||
title: format!(" CPU {:.0}% ", cur),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some(("100".into(), " 0".into())),
|
||||
@@ -466,12 +467,13 @@ fn main() -> io::Result<()> {
|
||||
}
|
||||
if ta.width >= 10 && ta.height >= GRAPH_HEIGHT {
|
||||
let max_t = app.temp_graph_history.display_max().max(50.0);
|
||||
let cur_t = app.temp_graph_history.last().unwrap_or(0.0);
|
||||
f.render_widget(
|
||||
BrailleGraph {
|
||||
values: app.temp_graph_history.as_slice(),
|
||||
max_value: max_t,
|
||||
color: Color::Red,
|
||||
title: " Temp °C ",
|
||||
title: format!(" Temp {:.0}\u{B0}C ", cur_t),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some((format!("{:.0}", max_t), "0".into())),
|
||||
@@ -482,12 +484,13 @@ fn main() -> io::Result<()> {
|
||||
}
|
||||
if pa.width >= 10 && pa.height >= GRAPH_HEIGHT {
|
||||
let max_p = app.power_graph_history.display_max().max(20.0);
|
||||
let cur_p = app.power_graph_history.last().unwrap_or(0.0);
|
||||
f.render_widget(
|
||||
BrailleGraph {
|
||||
values: app.power_graph_history.as_slice(),
|
||||
max_value: max_p,
|
||||
color: Color::Yellow,
|
||||
title: " Pkg Power W ",
|
||||
title: format!(" Pwr {:.1}W ", cur_p),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some((format!("{:.0}", max_p), "0".into())),
|
||||
@@ -510,12 +513,13 @@ fn main() -> io::Result<()> {
|
||||
f.render_widget(render_network_panel(&app, true), net_area);
|
||||
if graph_area.width >= 10 && graph_area.height >= GRAPH_HEIGHT {
|
||||
let max_n = app.net_graph_history.display_max();
|
||||
let cur_n = app.net_graph_history.last().unwrap_or(0.0);
|
||||
f.render_widget(
|
||||
BrailleGraph {
|
||||
values: app.net_graph_history.as_slice(),
|
||||
max_value: max_n,
|
||||
color: Color::Green,
|
||||
title: " Net Throughput KiB/s ",
|
||||
title: format!(" Net {:.0} KiB/s ", cur_n),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some((format!("{:.0}", max_n), "0".into())),
|
||||
@@ -537,12 +541,13 @@ fn main() -> io::Result<()> {
|
||||
f.render_widget(render_storage_panel(&app, true), sto_area);
|
||||
if graph_area.width >= 10 && graph_area.height >= GRAPH_HEIGHT {
|
||||
let max_s = app.storage_graph_history.display_max();
|
||||
let cur_s = app.storage_graph_history.last().unwrap_or(0.0);
|
||||
f.render_widget(
|
||||
BrailleGraph {
|
||||
values: app.storage_graph_history.as_slice(),
|
||||
max_value: max_s,
|
||||
color: Color::Magenta,
|
||||
title: " Disk Throughput KiB/s ",
|
||||
title: format!(" Disk {:.0} KiB/s ", cur_s),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some((format!("{:.0}", max_s), "0".into())),
|
||||
@@ -670,11 +675,12 @@ fn main() -> io::Result<()> {
|
||||
Constraint::Length(w),
|
||||
]));
|
||||
if cpu_area.width >= 10 && cpu_area.height >= GRAPH_HEIGHT {
|
||||
let cur = app.cpu_graph_history.last().unwrap_or(0.0);
|
||||
let g = BrailleGraph {
|
||||
values: app.cpu_graph_history.as_slice(),
|
||||
max_value: 100.0,
|
||||
color: Color::Cyan,
|
||||
title: " CPU Load % ",
|
||||
title: format!(" CPU {:.0}% ", cur),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some(("100".into(), " 0".into())),
|
||||
@@ -684,11 +690,12 @@ fn main() -> io::Result<()> {
|
||||
}
|
||||
if temp_area.width >= 10 && temp_area.height >= GRAPH_HEIGHT {
|
||||
let max_t = app.temp_graph_history.display_max().max(50.0);
|
||||
let cur_t = app.temp_graph_history.last().unwrap_or(0.0);
|
||||
let g = BrailleGraph {
|
||||
values: app.temp_graph_history.as_slice(),
|
||||
max_value: max_t,
|
||||
color: Color::Red,
|
||||
title: " Temp °C ",
|
||||
title: format!(" Temp {:.0}\u{B0}C ", cur_t),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some((format!("{:.0}", max_t), "0".into())),
|
||||
@@ -698,11 +705,12 @@ fn main() -> io::Result<()> {
|
||||
}
|
||||
if power_area.width >= 10 && power_area.height >= GRAPH_HEIGHT {
|
||||
let max_p = app.power_graph_history.display_max().max(20.0);
|
||||
let cur_p = app.power_graph_history.last().unwrap_or(0.0);
|
||||
let g = BrailleGraph {
|
||||
values: app.power_graph_history.as_slice(),
|
||||
max_value: max_p,
|
||||
color: Color::Yellow,
|
||||
title: " Pkg Power W ",
|
||||
title: format!(" Pwr {:.1}W ", cur_p),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some((format!("{:.0}", max_p), "0".into())),
|
||||
@@ -744,7 +752,7 @@ fn main() -> io::Result<()> {
|
||||
values: app.net_graph_history.as_slice(),
|
||||
max_value: max_n,
|
||||
color: Color::Green,
|
||||
title: " Net Throughput KiB/s ",
|
||||
title: " Net Throughput KiB/s ".to_string(),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some((format!("{:.0}", max_n), "0".into())),
|
||||
@@ -771,7 +779,7 @@ fn main() -> io::Result<()> {
|
||||
values: app.storage_graph_history.as_slice(),
|
||||
max_value: max_s,
|
||||
color: Color::Magenta,
|
||||
title: " Disk Throughput KiB/s ",
|
||||
title: " Disk Throughput KiB/s ".to_string(),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some((format!("{:.0}", max_s), "0".into())),
|
||||
|
||||
@@ -1151,15 +1151,21 @@ pub fn render_process_panel<'a>(app: &'a App, focused: bool) -> Paragraph<'a> {
|
||||
} else {
|
||||
format!("; filter: \"{}\" (press Esc to clear)", app.process_filter)
|
||||
};
|
||||
let sort_arrow = if app.sort_ascending {
|
||||
"\u{25B2}"
|
||||
} else {
|
||||
"\u{25BC}"
|
||||
};
|
||||
lines.push(Line::from(format!(
|
||||
"Showing top {} of {} process(es); total RSS: {}; sort: {}{}{} (press 'o' to cycle, 'y' for tree, 'F' to filter)",
|
||||
proc.count(),
|
||||
proc.total_count,
|
||||
crate::process::ProcessInfo::format_memory_kb(proc.total_memory_kb),
|
||||
app.process_sort.name(),
|
||||
if app.process_tree { "; view: tree" } else { "" },
|
||||
filter_indicator,
|
||||
).set_style(theme::LABEL_BOLD)));
|
||||
"Showing top {} of {} process(es); total RSS: {}; sort: {} {}{}{} (press 'o' to cycle, 'y' for tree, 'F' to filter)",
|
||||
proc.count(),
|
||||
proc.total_count,
|
||||
crate::process::ProcessInfo::format_memory_kb(proc.total_memory_kb),
|
||||
app.process_sort.name(),
|
||||
sort_arrow,
|
||||
if app.process_tree { "; view: tree" } else { "" },
|
||||
filter_indicator,
|
||||
).set_style(theme::LABEL_BOLD)));
|
||||
lines.push(Line::from(""));
|
||||
// The MEM column header swaps between RSS and VSZ depending on
|
||||
// the active sort. Default and most modes use RSS (resident
|
||||
@@ -2251,7 +2257,7 @@ fn render_graph_snapshot(
|
||||
values,
|
||||
max_value: max_val,
|
||||
color,
|
||||
title,
|
||||
title: title.to_string(),
|
||||
focused: false,
|
||||
x_labels: None,
|
||||
y_labels: Some((top_label.to_string(), bot_label.to_string())),
|
||||
|
||||
Reference in New Issue
Block a user