diff --git a/Cargo.lock b/Cargo.lock index ae8bf35..d981825 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3200,7 +3200,7 @@ dependencies = [ "dbusmenu-gtk3-sys", "gtk", "serde", - "thiserror 2.0.0", + "thiserror 2.0.3", "tokio", "tracing", "zbus", @@ -3230,11 +3230,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.0" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15291287e9bff1bc6f9ff3409ed9af665bec7a5fc8ac079ea96be07bca0e2668" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" dependencies = [ - "thiserror-impl 2.0.0", + "thiserror-impl 2.0.3", ] [[package]] @@ -3250,9 +3250,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.0" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22efd00f33f93fa62848a7cab956c3d38c8d43095efda1decfc2b3a5dc0b8972" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote 1.0.35", @@ -3681,9 +3681,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.8.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", ] diff --git a/docs/modules/Clipboard.md b/docs/modules/Clipboard.md index 212a60d..f168f8f 100644 --- a/docs/modules/Clipboard.md +++ b/docs/modules/Clipboard.md @@ -12,15 +12,15 @@ Supports plain text and images. > Type: `clipboard` -| Name | Type | Default | Description | -|-----------------------|---------------------------------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------| -| `icon` | `string` or [image](images) | `󰨸` | Icon to show on the widget button. | -| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | -| `max_items` | `integer` | `10` | Maximum number of items to show in the popup. | -| `truncate` | `'start'` or `'middle'` or `'end'` or `Map` | `null` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. Use the long-hand `Map` version if specifying a length. | -| `truncate.mode` | `'start'` or `'middle'` or `'end'` | `null` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. | -| `truncate.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. | -| `truncate.max_length` | `integer` | `null` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. | +| Name | Type | Default | Description | +|-----------------------|------------------------------------------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------| +| `icon` | `string` or [image](images) | `󰨸` | Icon to show on the widget button. | +| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | +| `max_items` | `integer` | `10` | Maximum number of items to show in the popup. | +| `truncate` | `'start'` or `'middle'` or `'end'` or `off` or `Map` | `off` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. Use the long-hand `Map` version if specifying a length. | +| `truncate.mode` | `'start'` or `'middle'` or `'end'` or `off` | `off` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. | +| `truncate.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. | +| `truncate.max_length` | `integer` | `null` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. |
JSON diff --git a/docs/modules/Focused.md b/docs/modules/Focused.md index 009b125..066004a 100644 --- a/docs/modules/Focused.md +++ b/docs/modules/Focused.md @@ -10,15 +10,15 @@ Displays the title and/or icon of the currently focused window. > Type: `focused` -| Name | Type | Default | Description | -|-----------------------|---------------------------------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------| -| `show_icon` | `boolean` | `true` | Whether to show the app's icon. | -| `show_title` | `boolean` | `true` | Whether to show the app's title. | -| `icon_size` | `integer` | `32` | Size of icon in pixels. | -| `truncate` | `'start'` or `'middle'` or `'end'` or `Map` | `null` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. Use the long-hand `Map` version if specifying a length. | -| `truncate.mode` | `'start'` or `'middle'` or `'end'` | `null` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. | -| `truncate.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. | -| `truncate.max_length` | `integer` | `null` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. | +| Name | Type | Default | Description | +|-----------------------|------------------------------------------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------| +| `show_icon` | `boolean` | `true` | Whether to show the app's icon. | +| `show_title` | `boolean` | `true` | Whether to show the app's title. | +| `icon_size` | `integer` | `32` | Size of icon in pixels. | +| `truncate` | `'start'` or `'middle'` or `'end'` or `off` or `Map` | `off` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. Use the long-hand `Map` version if specifying a length. | +| `truncate.mode` | `'start'` or `'middle'` or `'end'` or `off` | `off` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. | +| `truncate.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. | +| `truncate.max_length` | `integer` | `null` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. |
JSON diff --git a/docs/modules/Launcher.md b/docs/modules/Launcher.md index 14040d2..f5bba43 100644 --- a/docs/modules/Launcher.md +++ b/docs/modules/Launcher.md @@ -12,13 +12,21 @@ Optionally displays a launchable set of favourites. > Type: `launcher` -| | Type | Default | Description | -|--------------|------------|---------|-----------------------------------------------------------------------------------------------------| -| `favorites` | `string[]` | `[]` | List of app IDs (or classes) to always show at the start of the launcher | -| `show_names` | `boolean` | `false` | Whether to show app names on the button label. Names will still show on tooltips when set to false. | -| `show_icons` | `boolean` | `true` | Whether to show app icons on the button. | -| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | -| `reversed` | `boolean` | `false` | Whether to reverse the order of favorites/items | +| | Type | Default | Description | +|-----------------------------|---------------------------------------------|----------|--------------------------------------------------------------------------------------------------------------------------| +| `favorites` | `string[]` | `[]` | List of app IDs (or classes) to always show at the start of the launcher | +| `show_names` | `boolean` | `false` | Whether to show app names on the button label. Names will still show on tooltips when set to false. | +| `show_icons` | `boolean` | `true` | Whether to show app icons on the button. | +| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | +| `reversed` | `boolean` | `false` | Whether to reverse the order of favorites/items | +| `truncate.mode` | `'start'` or `'middle'` or `'end'` or `off` | `end` | The location of the ellipses and where to truncate text from. Applies to application names when `show_names` is enabled. | +| `truncate.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. | +| `truncate.max_length` | `integer` | `null` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. | +| `truncate_popup.mode` | `'start'` or `'middle'` or `'end'` or `off` | `middle` | The location of the ellipses and where to truncate text from. Applies to window names within a group popup. | +| `truncate_popup.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. | +| `truncate_popup.max_length` | `integer` | `25` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. | + +
JSON diff --git a/docs/modules/Music.md b/docs/modules/Music.md index 5c5bc7d..bdde681 100644 --- a/docs/modules/Music.md +++ b/docs/modules/Music.md @@ -11,27 +11,27 @@ in MPRIS mode, the widget will listen to all players and automatically detect/di > Type: `music` -| | Type | Default | Description | -|-----------------------|---------------------------------------------|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------| -| `player_type` | `'mpris'` or `'mpd'` | `mpris` | Whether to connect to MPRIS players or an MPD server. | -| `format` | `string` | `{title} / {artist}` | Format string for the widget. More info below. | -| `truncate` | `'start'` or `'middle'` or `'end'` or `Map` | `null` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. Use the long-hand `Map` version if specifying a length. | -| `truncate.mode` | `'start'` or `'middle'` or `'end'` | `null` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. | -| `truncate.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. | -| `truncate.max_length` | `integer` | `null` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. | -| `icons.play` | `string` or [image](images) | `` | Icon to show when playing. | -| `icons.pause` | `string` or [image](images) | `` | Icon to show when paused. | -| `icons.prev` | `string` or [image](images) | `󰒮` | Icon to show on previous button. | -| `icons.next` | `string` or [image](images) | `󰒭` | Icon to show on next button. | -| `icons.volume` | `string` or [image](images) | `󰕾` | Icon to show under popup volume slider. | -| `icons.track` | `string` or [image](images) | `󰎈` | Icon to show next to track title. | -| `icons.album` | `string` or [image](images) | `󰀥` | Icon to show next to album name. | -| `icons.artist` | `string` or [image](images) | `󰠃` | Icon to show next to artist name. | -| `show_status_icon` | `boolean` | `true` | Whether to show the play/pause icon on the widget. | -| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | -| `cover_image_size` | `integer` | `128` | Size to render album art image at inside popup. | -| `host` | `string` | `localhost:6600` | [MPD Only] TCP or Unix socket for the MPD server. | -| `music_dir` | `string` | `$HOME/Music` | [MPD Only] Path to MPD server's music directory on disc. Required for album art. | +| | Type | Default | Description | +|-----------------------|------------------------------------------------------|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------| +| `player_type` | `'mpris'` or `'mpd'` | `mpris` | Whether to connect to MPRIS players or an MPD server. | +| `format` | `string` | `{title} / {artist}` | Format string for the widget. More info below. | +| `truncate` | `'start'` or `'middle'` or `'end'` or `off` or `Map` | `off` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. Use the long-hand `Map` version if specifying a length. | +| `truncate.mode` | `'start'` or `'middle'` or `'end'` or `off` | `off` | The location of the ellipses and where to truncate text from. Leave null to avoid truncating. | +| `truncate.length` | `integer` | `null` | The fixed width (in chars) of the widget. Leave blank to let GTK automatically handle. | +| `truncate.max_length` | `integer` | `null` | The maximum number of characters before truncating. Leave blank to let GTK automatically handle. | +| `icons.play` | `string` or [image](images) | `` | Icon to show when playing. | +| `icons.pause` | `string` or [image](images) | `` | Icon to show when paused. | +| `icons.prev` | `string` or [image](images) | `󰒮` | Icon to show on previous button. | +| `icons.next` | `string` or [image](images) | `󰒭` | Icon to show on next button. | +| `icons.volume` | `string` or [image](images) | `󰕾` | Icon to show under popup volume slider. | +| `icons.track` | `string` or [image](images) | `󰎈` | Icon to show next to track title. | +| `icons.album` | `string` or [image](images) | `󰀥` | Icon to show next to album name. | +| `icons.artist` | `string` or [image](images) | `󰠃` | Icon to show next to artist name. | +| `show_status_icon` | `boolean` | `true` | Whether to show the play/pause icon on the widget. | +| `icon_size` | `integer` | `32` | Size to render icon at (image icons only). | +| `cover_image_size` | `integer` | `128` | Size to render album art image at inside popup. | +| `host` | `string` | `localhost:6600` | [MPD Only] TCP or Unix socket for the MPD server. | +| `music_dir` | `string` | `$HOME/Music` | [MPD Only] Path to MPD server's music directory on disc. Required for album art. | See [here](images) for information on images. diff --git a/src/config/mod.rs b/src/config/mod.rs index 0c3ece6..16191f5 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -44,7 +44,7 @@ use std::collections::HashMap; use schemars::JsonSchema; pub use self::common::{CommonConfig, ModuleOrientation, TransitionType}; -pub use self::truncate::TruncateMode; +pub use self::truncate::{EllipsizeMode, TruncateMode}; #[derive(Debug, Deserialize, Clone)] #[serde(tag = "type", rename_all = "snake_case")] diff --git a/src/config/truncate.rs b/src/config/truncate.rs index 09966cd..b21ddf7 100644 --- a/src/config/truncate.rs +++ b/src/config/truncate.rs @@ -1,19 +1,21 @@ use gtk::pango::EllipsizeMode as GtkEllipsizeMode; -use gtk::prelude::*; use serde::Deserialize; -#[derive(Debug, Deserialize, Clone, Copy)] +#[derive(Debug, Deserialize, Clone, Copy, Default)] #[serde(rename_all = "snake_case")] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub enum EllipsizeMode { + None, Start, Middle, + #[default] End, } impl From for GtkEllipsizeMode { fn from(value: EllipsizeMode) -> Self { match value { + EllipsizeMode::None => Self::None, EllipsizeMode::Start => Self::Start, EllipsizeMode::Middle => Self::Middle, EllipsizeMode::End => Self::End, @@ -27,10 +29,23 @@ impl From for GtkEllipsizeMode { /// /// The option can be configured in one of two modes. /// +/// **Default**: `Auto (end)` +/// #[derive(Debug, Deserialize, Clone, Copy)] #[serde(untagged)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub enum TruncateMode { + /// Do not truncate content. + /// + /// Setting this option may cause excessively long content to overflow other widgets, + /// shifting them off-screen. + /// + /// # Example + /// + /// ```corn + /// { truncate = "off" } + Off, + /// Auto mode lets GTK decide when to ellipsize. /// /// To use this mode, set the truncate option to a string @@ -44,7 +59,7 @@ pub enum TruncateMode { /// /// **Valid options**: `start`, `middle`, `end` ///
- /// **Default**: `null` + /// **Default**: `end` Auto(EllipsizeMode), /// Length mode defines a fixed point at which to ellipsize. @@ -88,36 +103,34 @@ pub enum TruncateMode { }, } -impl TruncateMode { - const fn mode(&self) -> EllipsizeMode { - match self { - Self::Length { mode, .. } | Self::Auto(mode) => *mode, - } +impl Default for TruncateMode { + fn default() -> Self { + Self::Auto(EllipsizeMode::default()) } +} - const fn length(&self) -> Option { +impl TruncateMode { + pub const fn length(&self) -> Option { match self { - Self::Auto(_) => None, + Self::Auto(_) | Self::Off => None, Self::Length { length, .. } => *length, } } - const fn max_length(&self) -> Option { + pub const fn max_length(&self) -> Option { match self { - Self::Auto(_) => None, + Self::Auto(_) | Self::Off => None, Self::Length { max_length, .. } => *max_length, } } +} - pub fn truncate_label(&self, label: >k::Label) { - label.set_ellipsize(self.mode().into()); - - if let Some(length) = self.length() { - label.set_width_chars(length); - } - - if let Some(length) = self.max_length() { - label.set_max_width_chars(length); - } +impl From for GtkEllipsizeMode { + fn from(value: TruncateMode) -> Self { + let mode = match value { + TruncateMode::Off => EllipsizeMode::None, + TruncateMode::Length { mode, .. } | TruncateMode::Auto(mode) => mode, + }; + mode.into() } } diff --git a/src/gtk_helpers.rs b/src/gtk_helpers.rs index 628ac3a..1b5052b 100644 --- a/src/gtk_helpers.rs +++ b/src/gtk_helpers.rs @@ -1,6 +1,8 @@ +use crate::config::TruncateMode; use glib::{markup_escape_text, IsA}; +use gtk::pango::EllipsizeMode; use gtk::prelude::*; -use gtk::{Orientation, Widget}; +use gtk::{Label, Orientation, Widget}; /// Represents a widget's size /// and location relative to the bar's start edge. @@ -83,9 +85,11 @@ pub trait IronbarLabelExt { /// the text is escaped to avoid issues with special characters (ie `&`). /// Otherwise, the text is used verbatim, and it is up to the user to escape. fn set_label_escaped(&self, label: &str); + + fn truncate(&self, mode: TruncateMode); } -impl IronbarLabelExt for gtk::Label { +impl IronbarLabelExt for Label { fn set_label_escaped(&self, label: &str) { if !label.contains(">::into(mode)); + + if let Some(length) = mode.length() { + self.set_width_chars(length); + } + + if let Some(length) = mode.max_length() { + self.set_max_width_chars(length); + } + } } diff --git a/src/image/gtk.rs b/src/image/gtk.rs index bf80bcd..8c17791 100644 --- a/src/image/gtk.rs +++ b/src/image/gtk.rs @@ -13,7 +13,7 @@ pub fn new_icon_button(input: &str, icon_theme: &IconTheme, size: i32) -> Button image.add_class("icon"); match ImageProvider::parse(input, icon_theme, false, size) - .map(|provider| provider.load_into_image(image.clone())) + .map(|provider| provider.load_into_image(&image)) { Some(_) => { button.set_image(Some(&image)); @@ -42,7 +42,7 @@ pub fn new_icon_label(input: &str, icon_theme: &IconTheme, size: i32) -> gtk::Bo container.add(&image); ImageProvider::parse(input, icon_theme, false, size) - .map(|provider| provider.load_into_image(image)); + .map(|provider| provider.load_into_image(&image)); } else { let label = Label::builder().use_markup(true).label(input).build(); label.add_class("icon"); diff --git a/src/image/provider.rs b/src/image/provider.rs index eaf2222..5004c37 100644 --- a/src/image/provider.rs +++ b/src/image/provider.rs @@ -141,7 +141,7 @@ impl<'a> ImageProvider<'a> { /// Attempts to fetch the image from the location /// and load it into the provided `GTK::Image` widget. - pub fn load_into_image(&self, image: gtk::Image) -> Result<()> { + pub fn load_into_image(&self, image: >k::Image) -> Result<()> { // handle remote locations async to avoid blocking UI thread while downloading #[cfg(feature = "http")] if let ImageLocation::Remote(url) = &self.location { @@ -157,6 +157,7 @@ impl<'a> ImageProvider<'a> { { let size = self.size; + let image = image.clone(); glib_recv_mpsc!(rx, bytes => { let stream = MemoryInputStream::from_bytes(&bytes); @@ -181,11 +182,11 @@ impl<'a> ImageProvider<'a> { }); } } else { - self.load_into_image_sync(&image)?; + self.load_into_image_sync(image)?; }; #[cfg(not(feature = "http"))] - self.load_into_image_sync(&image)?; + self.load_into_image_sync(image)?; Ok(()) } diff --git a/src/modules/clipboard.rs b/src/modules/clipboard.rs index aea0c32..9dbd68c 100644 --- a/src/modules/clipboard.rs +++ b/src/modules/clipboard.rs @@ -1,6 +1,7 @@ use crate::clients::clipboard::{self, ClipboardEvent}; use crate::clients::wayland::{ClipboardItem, ClipboardValue}; use crate::config::{CommonConfig, TruncateMode}; +use crate::gtk_helpers::IronbarLabelExt; use crate::image::new_icon_button; use crate::modules::{ Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, PopupButton, WidgetContext, @@ -195,7 +196,7 @@ impl Module