feat: keybinds for toggling displays

This commit is contained in:
electria 2026-08-16 13:56:18 -07:00
commit e310ca570b
Signed by: electria
SSH key fingerprint: SHA256:8LlB3ucPbBHqozqkhsNbaV5oG3SlzzqUj8FZDL6IPQs
4 changed files with 101 additions and 26 deletions

View file

@ -1,13 +1,28 @@
use std::time::Duration; use std::time::Duration;
use iced::{Color, Element, Error, Length, Renderer, Task, Theme, application, theme, widget}; use iced::{
Color, Error, Event, Length, Renderer, Subscription, Task, Theme, application, event,
keyboard::{self, Key},
theme, widget,
};
use crate::{app::graph::Graph, sysinfo_snapshot::SysinfoSnapshot}; use crate::{
app::{graph::Graph, utils::maybe_widget},
sysinfo_snapshot::SysinfoSnapshot,
utils::Toggle,
};
mod graph; mod graph;
mod info_stream; mod info_stream;
mod utils;
type Element<'a> = iced::Element<'a, Message, Theme, Renderer>;
enum Message { enum Message {
ToggleMain,
ToggleCpu,
ToggleMemory,
Info(SysinfoSnapshot), Info(SysinfoSnapshot),
} }
@ -15,18 +30,33 @@ enum Message {
struct State { struct State {
uptime: Duration, uptime: Duration,
is_main_section_shown: bool,
total_cpu_graph: Graph, total_cpu_graph: Graph,
is_cpu_section_shown: bool,
cpu_graphs: Vec<Graph>, cpu_graphs: Vec<Graph>,
is_memory_section_shown: bool,
memory_graph: Graph, memory_graph: Graph,
swap_graph: Graph, swap_graph: Graph,
} }
impl State { impl State {
fn new() -> (Self, Task<Message>) { fn new() -> (Self, Task<Message>) {
(Self::default(), info_stream::create()) (
Self {
is_main_section_shown: true,
..Default::default()
},
info_stream::create(),
)
} }
fn update(&mut self, message: Message) -> Task<Message> { fn update(&mut self, message: Message) -> Task<Message> {
match message { match message {
Message::ToggleMain => self.is_main_section_shown.toggle(),
Message::ToggleCpu => self.is_cpu_section_shown.toggle(),
Message::ToggleMemory => self.is_memory_section_shown.toggle(),
Message::Info(snapshot) => { Message::Info(snapshot) => {
self.uptime = snapshot.uptime(); self.uptime = snapshot.uptime();
@ -55,38 +85,58 @@ impl State {
Task::none() Task::none()
} }
fn view(&self) -> Element<'_, Message, Theme, Renderer> { fn view(&self) -> Element<'_> {
widget::column([ widget::column([
widget::row([ widget::row([
widget::canvas(&self.total_cpu_graph) maybe_widget(self.is_main_section_shown, || {
.width(Length::Fill) widget::canvas(&self.total_cpu_graph)
.width(Length::Fill)
.height(Length::Fill)
.into()
}),
maybe_widget(self.is_cpu_section_shown, || {
widget::grid(
self.cpu_graphs
.iter()
.map(|graph| widget::Canvas::new(graph).into()),
)
.columns(2)
.height(Length::Fill) .height(Length::Fill)
.into(), .into()
widget::grid( }),
self.cpu_graphs
.iter()
.map(|graph| widget::Canvas::new(graph).into()),
)
.columns(2)
.height(Length::Fill)
.into(),
])
.into(),
widget::row([
widget::canvas(&self.memory_graph)
.width(Length::Fill)
.height(Length::Fill)
.into(),
widget::canvas(&self.swap_graph)
.width(Length::Fill)
.height(Length::Fill)
.into(),
]) ])
.into(), .into(),
maybe_widget(self.is_memory_section_shown, || {
widget::row([
widget::canvas(&self.memory_graph)
.width(Length::Fill)
.height(Length::Fill)
.into(),
widget::canvas(&self.swap_graph)
.width(Length::Fill)
.height(Length::Fill)
.into(),
])
.into()
}),
]) ])
.into() .into()
} }
fn subscription(&self) -> Subscription<Message> {
event::listen().filter_map(|event| match event {
Event::Keyboard(keyboard::Event::KeyPressed { key, modifiers, .. }) => {
match key.as_ref() {
Key::Character("m" | "1") if modifiers.shift() => Some(Message::ToggleMain),
Key::Character("c" | "2") => Some(Message::ToggleCpu),
Key::Character("m" | "3") => Some(Message::ToggleMemory),
_ => None,
}
}
_ => None,
})
}
fn title(&self) -> String { fn title(&self) -> String {
format!("itop {:?}", self.uptime) format!("itop {:?}", self.uptime)
} }
@ -94,6 +144,7 @@ impl State {
pub fn run() -> Result<(), Error> { pub fn run() -> Result<(), Error> {
application(State::new, State::update, State::view) application(State::new, State::update, State::view)
.subscription(State::subscription)
.title(State::title) .title(State::title)
.theme(theme::Theme::custom( .theme(theme::Theme::custom(
"high-contrast-dark", "high-contrast-dark",

14
src/app/utils.rs Normal file
View file

@ -0,0 +1,14 @@
use iced::widget;
use crate::app;
pub fn maybe_widget<'a>(
condition: bool,
widget: impl FnOnce() -> app::Element<'a>,
) -> app::Element<'a> {
if condition {
widget()
} else {
widget::space().into()
}
}

View file

@ -3,6 +3,7 @@ use std::env;
mod app; mod app;
mod server; mod server;
mod sysinfo_snapshot; mod sysinfo_snapshot;
mod utils;
fn main() { fn main() {
match env::args().nth(1).as_deref() { match env::args().nth(1).as_deref() {

9
src/utils.rs Normal file
View file

@ -0,0 +1,9 @@
pub trait Toggle {
fn toggle(&mut self);
}
impl Toggle for bool {
fn toggle(&mut self) {
*self = !*self
}
}