diff --git a/src/modules/volume.rs b/src/modules/volume.rs index 54c536e..3c454ad 100644 --- a/src/modules/volume.rs +++ b/src/modules/volume.rs @@ -1,3 +1,12 @@ +use std::collections::HashMap; + +use glib::Propagation; +use gtk::pango::EllipsizeMode; +use gtk::prelude::*; +use gtk::{Button, CellRendererText, ComboBoxText, Image, Label, Orientation, Scale, ToggleButton}; +use serde::Deserialize; +use tokio::sync::mpsc; + use crate::clients::volume::{self, Event}; use crate::config::CommonConfig; use crate::gtk_helpers::IronbarGtkExt; @@ -6,20 +15,17 @@ use crate::modules::{ Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, PopupButton, WidgetContext, }; use crate::{glib_recv, lock, module_impl, send_async, spawn, try_send}; -use glib::Propagation; -use gtk::pango::EllipsizeMode; -use gtk::prelude::*; -use gtk::{ - Box as GtkBox, Button, CellRendererText, ComboBoxText, Image, Label, Orientation, Scale, - ToggleButton, -}; -use serde::Deserialize; -use std::collections::HashMap; -use tokio::sync::mpsc; #[derive(Debug, Clone, Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct VolumeModule { + /// The format string to use for the widget button label. + /// For available tokens, see [below](#formatting-tokens). + /// + /// **Default**: `{icon} {percentage}%` + #[serde(default = "default_format")] + format: String, + /// Maximum value to allow volume sliders to reach. /// Pulse supports values > 100 but this may result in distortion. /// @@ -27,6 +33,12 @@ pub struct VolumeModule { #[serde(default = "default_max_volume")] max_volume: f64, + /// Volume state icons. + /// + /// See [icons](#icons). + #[serde(default)] + icons: Icons, + #[serde(default = "default_icon_size")] icon_size: i32, @@ -35,10 +47,79 @@ pub struct VolumeModule { pub common: Option, } +fn default_format() -> String { + String::from("{icon} {percentage}%") +} + +#[derive(Debug, Clone, Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +pub struct Icons { + /// Icon to show for high volume levels. + /// + /// **Default**: `󰕾` + #[serde(default = "default_icon_volume_high")] + volume_high: String, + + /// Icon to show for medium volume levels. + /// + /// **Default**: `󰖀` + #[serde(default = "default_icon_volume_medium")] + volume_medium: String, + + /// Icon to show for low volume levels. + /// + /// **Default**: `󰕿` + #[serde(default = "default_icon_volume_low")] + volume_low: String, + + /// Icon to show for muted outputs. + /// + /// **Default**: `󰝟` + #[serde(default = "default_icon_muted")] + muted: String, +} + +impl Icons { + fn volume_icon(&self, volume_percent: f64) -> &str { + match volume_percent as u32 { + 0..=33 => &self.volume_low, + 34..=66 => &self.volume_medium, + 67.. => &self.volume_high, + } + } +} + +impl Default for Icons { + fn default() -> Self { + Self { + volume_high: default_icon_volume_high(), + volume_medium: default_icon_volume_medium(), + volume_low: default_icon_volume_low(), + muted: default_icon_muted(), + } + } +} + const fn default_max_volume() -> f64 { 100.0 } +fn default_icon_volume_high() -> String { + String::from("󰕾") +} + +fn default_icon_volume_medium() -> String { + String::from("󰖀") +} + +fn default_icon_volume_low() -> String { + String::from("󰕿") +} + +fn default_icon_muted() -> String { + String::from("󰝟") +} + const fn default_icon_size() -> i32 { 24 } @@ -182,16 +263,16 @@ impl Module