meow
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
//! Battery module: Android-style battery icon fed by the battery service.
|
//! Battery module: Android-style battery icon fed by the battery service.
|
||||||
|
|
||||||
use iced::widget::{container, row, text};
|
use iced::widget::{container, row, stack, text};
|
||||||
use iced::{Border, Color, Element, Length, Task, Theme};
|
use iced::{alignment, Border, Color, Element, Length, Task, Theme};
|
||||||
|
|
||||||
use common::{BarModule, BatteryEvent, BatteryMsg, BatteryStatus, ModuleEffect, Service, Wire};
|
use common::{BarModule, BatteryEvent, BatteryMsg, BatteryStatus, ModuleEffect, Service, Wire};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use toml::Table;
|
||||||
|
|
||||||
/// Icon shell size (logical px); fill scales inside it.
|
/// Icon shell size (logical px); fill scales inside it.
|
||||||
const SHELL_W: f32 = 28.0;
|
const SHELL_W: f32 = 28.0;
|
||||||
@@ -14,13 +16,27 @@ const PAD: f32 = 2.0;
|
|||||||
pub struct Battery {
|
pub struct Battery {
|
||||||
percent: Option<i32>,
|
percent: Option<i32>,
|
||||||
status: BatteryStatus,
|
status: BatteryStatus,
|
||||||
|
numbers_in_icon: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `module.battery` table; everything optional.
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
struct BatteryConfig {
|
||||||
|
/// Render the percentage as a number centered inside the icon shell.
|
||||||
|
#[serde(default)]
|
||||||
|
numbers_in_icon: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Battery {
|
impl Battery {
|
||||||
pub fn new() -> Self {
|
pub fn new(config: Option<Table>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
percent: None,
|
percent: None,
|
||||||
status: BatteryStatus::default(),
|
status: BatteryStatus::default(),
|
||||||
|
numbers_in_icon: config
|
||||||
|
.and_then(|table| table.get("battery").cloned())
|
||||||
|
.and_then(|battery| battery.try_into().ok())
|
||||||
|
.map(|cfg: BatteryConfig| cfg.numbers_in_icon)
|
||||||
|
.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,17 +91,36 @@ impl BarModule for Battery {
|
|||||||
|
|
||||||
fn view(&self, _window_id: Option<iced::window::Id>) -> Element<'_, Wire> {
|
fn view(&self, _window_id: Option<iced::window::Id>) -> Element<'_, Wire> {
|
||||||
let status = self.status;
|
let status = self.status;
|
||||||
|
let shell = container(
|
||||||
|
container(text(""))
|
||||||
|
.width(Length::Fixed(self.fill_w()))
|
||||||
|
.height(Length::Fill)
|
||||||
|
.style(solid_style(status)),
|
||||||
|
)
|
||||||
|
.width(Length::Fixed(SHELL_W))
|
||||||
|
.height(Length::Fixed(SHELL_H))
|
||||||
|
.padding(PAD)
|
||||||
|
.style(shell_style(status));
|
||||||
|
// Optional percentage readout centered over the fill, in the bar's
|
||||||
|
// background color — legible on the light fill, dim where unfilled.
|
||||||
|
let shell: Element<'_, Wire> = match (self.numbers_in_icon, self.percent) {
|
||||||
|
(true, Some(percent)) => stack![
|
||||||
|
shell,
|
||||||
|
container(
|
||||||
|
text(format!("{percent}")).size(9).style(|theme: &Theme| text::Style {
|
||||||
|
color: Some(theme.palette().background),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill)
|
||||||
|
.align_x(alignment::Horizontal::Center)
|
||||||
|
.align_y(alignment::Vertical::Center),
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
|
_ => shell.into(),
|
||||||
|
};
|
||||||
let icon = row![
|
let icon = row![
|
||||||
container(
|
shell,
|
||||||
container(text(""))
|
|
||||||
.width(Length::Fixed(self.fill_w()))
|
|
||||||
.height(Length::Fill)
|
|
||||||
.style(solid_style(status)),
|
|
||||||
)
|
|
||||||
.width(Length::Fixed(SHELL_W))
|
|
||||||
.height(Length::Fixed(SHELL_H))
|
|
||||||
.padding(PAD)
|
|
||||||
.style(shell_style(status)),
|
|
||||||
// Nub cap on the right edge.
|
// Nub cap on the right edge.
|
||||||
container(text(""))
|
container(text(""))
|
||||||
.width(Length::Fixed(2.5))
|
.width(Length::Fixed(2.5))
|
||||||
@@ -94,10 +129,18 @@ impl BarModule for Battery {
|
|||||||
]
|
]
|
||||||
.spacing(2)
|
.spacing(2)
|
||||||
.align_y(iced::Alignment::Center);
|
.align_y(iced::Alignment::Center);
|
||||||
row![icon]
|
if self.numbers_in_icon {
|
||||||
.spacing(6)
|
icon.into()
|
||||||
.align_y(iced::Alignment::Center)
|
} else {
|
||||||
.into()
|
let label = match self.percent {
|
||||||
|
Some(percent) => text(format!("{percent}%")),
|
||||||
|
None => text("--"),
|
||||||
|
};
|
||||||
|
row![icon, label]
|
||||||
|
.spacing(6)
|
||||||
|
.align_y(iced::Alignment::Center)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, msg: Wire) -> Task<ModuleEffect> {
|
fn update(&mut self, msg: Wire) -> Task<ModuleEffect> {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub use weather::*;
|
|||||||
pub fn all(module_config: Table) -> Vec<Box<dyn BarModule>> {
|
pub fn all(module_config: Table) -> Vec<Box<dyn BarModule>> {
|
||||||
vec![
|
vec![
|
||||||
Box::new(audio::Audio::new()),
|
Box::new(audio::Audio::new()),
|
||||||
Box::new(battery::Battery::new()),
|
Box::new(battery::Battery::new(Some(module_config.clone()))),
|
||||||
Box::new(clock::Clock::new(Some(module_config.clone()))),
|
Box::new(clock::Clock::new(Some(module_config.clone()))),
|
||||||
Box::new(weather::WeatherModule::default()),
|
Box::new(weather::WeatherModule::default()),
|
||||||
Box::new(workspaces::Workspaces::new(Some(module_config))),
|
Box::new(workspaces::Workspaces::new(Some(module_config))),
|
||||||
|
|||||||
Reference in New Issue
Block a user