meow
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
//! Battery module: Android-style battery icon fed by the battery service.
|
||||
|
||||
use iced::widget::{container, row, text};
|
||||
use iced::{Border, Color, Element, Length, Task, Theme};
|
||||
use iced::widget::{container, row, stack, text};
|
||||
use iced::{alignment, Border, Color, Element, Length, Task, Theme};
|
||||
|
||||
use common::{BarModule, BatteryEvent, BatteryMsg, BatteryStatus, ModuleEffect, Service, Wire};
|
||||
use serde::Deserialize;
|
||||
use toml::Table;
|
||||
|
||||
/// Icon shell size (logical px); fill scales inside it.
|
||||
const SHELL_W: f32 = 28.0;
|
||||
@@ -14,13 +16,27 @@ const PAD: f32 = 2.0;
|
||||
pub struct Battery {
|
||||
percent: Option<i32>,
|
||||
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 {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(config: Option<Table>) -> Self {
|
||||
Self {
|
||||
percent: None,
|
||||
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,8 +91,7 @@ impl BarModule for Battery {
|
||||
|
||||
fn view(&self, _window_id: Option<iced::window::Id>) -> Element<'_, Wire> {
|
||||
let status = self.status;
|
||||
let icon = row![
|
||||
container(
|
||||
let shell = container(
|
||||
container(text(""))
|
||||
.width(Length::Fixed(self.fill_w()))
|
||||
.height(Length::Fill)
|
||||
@@ -85,7 +100,27 @@ impl BarModule for Battery {
|
||||
.width(Length::Fixed(SHELL_W))
|
||||
.height(Length::Fixed(SHELL_H))
|
||||
.padding(PAD)
|
||||
.style(shell_style(status)),
|
||||
.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![
|
||||
shell,
|
||||
// Nub cap on the right edge.
|
||||
container(text(""))
|
||||
.width(Length::Fixed(2.5))
|
||||
@@ -94,11 +129,19 @@ impl BarModule for Battery {
|
||||
]
|
||||
.spacing(2)
|
||||
.align_y(iced::Alignment::Center);
|
||||
row![icon]
|
||||
if self.numbers_in_icon {
|
||||
icon.into()
|
||||
} else {
|
||||
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> {
|
||||
match msg.downcast::<BatteryEvent>() {
|
||||
|
||||
@@ -16,7 +16,7 @@ pub use weather::*;
|
||||
pub fn all(module_config: Table) -> Vec<Box<dyn BarModule>> {
|
||||
vec![
|
||||
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(weather::WeatherModule::default()),
|
||||
Box::new(workspaces::Workspaces::new(Some(module_config))),
|
||||
|
||||
Reference in New Issue
Block a user