Widget system

This commit is contained in:
Jiří Maxmilián Stříbrný 2026-03-17 20:53:46 +01:00
parent 958b7714da
commit 51d49b9cf1
2 changed files with 89 additions and 23 deletions

View file

@ -1,19 +1,19 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
if [[ ! -d "/home/maxag/Projects/Rust/wayland_panel" ]]; then if [[ ! -d "/mnt/removable/Projects/Rust/wayland_panel" ]]; then
echo "Cannot find source directory; Did you move it?" echo "Cannot find source directory; Did you move it?"
echo "(Looking for "/home/maxag/Projects/Rust/wayland_panel")" echo "(Looking for "/mnt/removable/Projects/Rust/wayland_panel")"
echo 'Cannot force reload with this script - use "direnv reload" manually and then try again' echo 'Cannot force reload with this script - use "direnv reload" manually and then try again'
exit 1 exit 1
fi fi
# rebuild the cache forcefully # rebuild the cache forcefully
_nix_direnv_force_reload=1 direnv exec "/home/maxag/Projects/Rust/wayland_panel" true _nix_direnv_force_reload=1 direnv exec "/mnt/removable/Projects/Rust/wayland_panel" true
# Update the mtime for .envrc. # Update the mtime for .envrc.
# This will cause direnv to reload again - but without re-building. # This will cause direnv to reload again - but without re-building.
touch "/home/maxag/Projects/Rust/wayland_panel/.envrc" touch "/mnt/removable/Projects/Rust/wayland_panel/.envrc"
# Also update the timestamp of whatever profile_rc we have. # Also update the timestamp of whatever profile_rc we have.
# This makes sure that we know we are up to date. # This makes sure that we know we are up to date.
touch -r "/home/maxag/Projects/Rust/wayland_panel/.envrc" "/home/maxag/Projects/Rust/wayland_panel/.direnv"/*.rc touch -r "/mnt/removable/Projects/Rust/wayland_panel/.envrc" "/mnt/removable/Projects/Rust/wayland_panel/.direnv"/*.rc

View file

@ -1,4 +1,3 @@
use chrono::Local;
use iced::Color; use iced::Color;
use iced::Element; use iced::Element;
use iced::Task; use iced::Task;
@ -31,15 +30,15 @@ pub fn main() -> Result<(), iced_layershell::Error> {
} }
struct App { struct App {
time: chrono::DateTime<chrono::Local>, time_widget: TimeWidget,
battery: String, battery_widget: BatteryWidget,
} }
impl Default for App { impl Default for App {
fn default() -> Self { fn default() -> Self {
let mut output = Self { let mut output = Self {
time: Default::default(), time_widget: Default::default(),
battery: Default::default(), battery_widget: Default::default(),
}; };
let _ = output.update(Message::Clock); let _ = output.update(Message::Clock);
@ -49,12 +48,10 @@ impl Default for App {
impl App { impl App {
fn view(&self, _id: iced::window::Id) -> Element<'_, Message> { fn view(&self, _id: iced::window::Id) -> Element<'_, Message> {
let display_time = self.time.format("%H:%M");
let content = row![ let content = row![
text!("{}", display_time), self.time_widget.view(),
iced::widget::space().width(iced::Length::Fill), iced::widget::space().width(iced::Length::Fill),
text!("{}", self.battery), self.battery_widget.view(),
] ]
.padding(iced::Padding::from([0, 5])) .padding(iced::Padding::from([0, 5]))
.height(iced::Length::Fill) .height(iced::Length::Fill)
@ -66,33 +63,102 @@ impl App {
fn update(&mut self, message: Message) -> Task<Message> { fn update(&mut self, message: Message) -> Task<Message> {
if let Message::Clock = message { if let Message::Clock = message {
self.time = Local::now(); self.time_widget.update();
self.battery = format!(
"{} 󰁽",
std::fs::read_to_string(std::path::Path::new(
"/sys/class/power_supply/BAT0/capacity",
))
.unwrap()
.trim_ascii_end()
);
} }
Task::none() Task::none()
} }
fn style(&self, theme: &iced::Theme) -> iced::theme::Style { fn style(&self, theme: &iced::Theme) -> iced::theme::Style {
iced::theme::Style { iced::theme::Style {
background_color: Color::TRANSPARENT, background_color: Color::TRANSPARENT,
text_color: theme.palette().text, text_color: theme.palette().text,
} }
} }
fn theme(&self, _id: iced::window::Id) -> iced::Theme { fn theme(&self, _id: iced::window::Id) -> iced::Theme {
iced::Theme::GruvboxDark iced::Theme::GruvboxDark
} }
fn subscription(&self) -> iced::Subscription<Message> { fn subscription(&self) -> iced::Subscription<Message> {
iced::time::every(Duration::from_secs(1)).map(|_| Message::Clock) iced::time::every(Duration::from_secs(1)).map(|_| Message::Clock)
} }
} }
trait PanelWidget {
fn update(&mut self);
fn view(&self) -> Element<'_, Message>;
}
#[derive(Default)]
struct BatteryWidget {
battery: Option<usize>,
}
impl PanelWidget for BatteryWidget {
fn update(&mut self) {
let file_content = std::fs::read_to_string(std::path::Path::new(
"/sys/class/power_supply/BAT0/capacity",
));
let Ok(file_string) = file_content else {
self.battery = None;
return;
};
let file_string = file_string.trim();
let Ok(value) = file_string.parse::<usize>() else {
self.battery = None;
return;
};
self.battery = Some(value);
}
fn view(&self) -> Element<'_, Message> {
match self.battery {
Some(battery) => text!("{} {}", battery.to_string(), Self::get_icon(battery)),
None => text("󱉞"),
}
.into()
}
}
impl BatteryWidget {
fn get_icon(battery: usize) -> &'static str {
match battery {
0..6 => "󰂎",
6..11 => "󰁺",
11..21 => "󰁻",
21..31 => "󰁼",
31..41 => "󰁽",
41..51 => "󰁾",
51..61 => "󰁿",
61..71 => "󰂀",
71..81 => "󰂁",
81..91 => "󰂂",
91..101 => "󰁹",
_ => "󰂃",
}
}
}
#[derive(Default)]
struct TimeWidget {
current_time: chrono::DateTime<chrono::Local>,
}
impl PanelWidget for TimeWidget {
fn update(&mut self) {
self.current_time = chrono::Local::now();
}
fn view(&self) -> Element<'_, Message> {
text!("{}", self.current_time.format("%H:%m")).into()
}
}
#[to_layer_message] #[to_layer_message]
#[derive(Debug)] #[derive(Debug)]
enum Message { enum Message {