use iced::Color; use iced::Element; use iced::Task; use iced::widget::container; use iced::widget::row; use iced::widget::text; use iced_layershell::daemon; use iced_layershell::reexport::Anchor; use iced_layershell::settings::LayerShellSettings; use iced_layershell::settings::Settings; use iced_layershell::to_layer_message; use std::time::Duration; pub fn main() -> Result<(), iced_layershell::Error> { daemon(App::default, || "rbaw".into(), App::update, App::view) .style(App::style) .theme(App::theme) .subscription(App::subscription) .settings(Settings { layer_settings: LayerShellSettings { size: Some((0, 32)), exclusive_zone: 32, anchor: Anchor::Top | Anchor::Left | Anchor::Right, start_mode: iced_layershell::settings::StartMode::AllScreens, // valid here in daemon ..Default::default() }, ..Default::default() }) .run() } struct App { time_widget: TimeWidget, battery_widget: BatteryWidget, } impl Default for App { fn default() -> Self { let mut output = Self { time_widget: Default::default(), battery_widget: Default::default(), }; let _ = output.update(Message::Clock); output } } impl App { fn view(&self, _id: iced::window::Id) -> Element<'_, Message> { let content = row![ self.time_widget.view(), iced::widget::space().width(iced::Length::Fill), self.battery_widget.view(), ] .padding(iced::Padding::from([0, 5])) .height(iced::Length::Fill) .width(iced::Length::Fill) .align_y(iced::Alignment::Center); container(content).into() } fn update(&mut self, message: Message) -> Task { if let Message::Clock = message { self.time_widget.update(); } Task::none() } fn style(&self, theme: &iced::Theme) -> iced::theme::Style { iced::theme::Style { background_color: Color::TRANSPARENT, text_color: theme.palette().text, } } fn theme(&self, _id: iced::window::Id) -> iced::Theme { iced::Theme::GruvboxDark } fn subscription(&self) -> iced::Subscription { 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, } 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::() 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, } 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] #[derive(Debug)] enum Message { IcedEvent(iced::Event), Clock, }