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 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 info_stream;
mod utils;
type Element<'a> = iced::Element<'a, Message, Theme, Renderer>;
enum Message {
ToggleMain,
ToggleCpu,
ToggleMemory,
Info(SysinfoSnapshot),
}
@ -15,18 +30,33 @@ enum Message {
struct State {
uptime: Duration,
is_main_section_shown: bool,
total_cpu_graph: Graph,
is_cpu_section_shown: bool,
cpu_graphs: Vec<Graph>,
is_memory_section_shown: bool,
memory_graph: Graph,
swap_graph: Graph,
}
impl State {
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> {
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) => {
self.uptime = snapshot.uptime();
@ -55,38 +85,58 @@ impl State {
Task::none()
}
fn view(&self) -> Element<'_, Message, Theme, Renderer> {
fn view(&self) -> Element<'_> {
widget::column([
widget::row([
widget::canvas(&self.total_cpu_graph)
.width(Length::Fill)
maybe_widget(self.is_main_section_shown, || {
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)
.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()
}
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 {
format!("itop {:?}", self.uptime)
}
@ -94,6 +144,7 @@ impl State {
pub fn run() -> Result<(), Error> {
application(State::new, State::update, State::view)
.subscription(State::subscription)
.title(State::title)
.theme(theme::Theme::custom(
"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 server;
mod sysinfo_snapshot;
mod utils;
fn main() {
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
}
}