mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-04-25 10:08:33 +02:00
fix(bar): use truncated labels for titles
This commit introduces a new wrapper, CustomUi, which is used to implement custom methods on top of eframe::egui::Ui. The default ui::add_sized method always has the text in a label centered, which is not desirable for a status bar where the layout should be ltr. A new function CustomUi::add_sized_left_to_right has been added to ensure that labels can be truncated with a custom width (which requires allocate_ui_with_layout), while also retaining the ability for the text to be aligned to the left rather than the center of the allocated layout.
This commit is contained in:
@@ -4,6 +4,7 @@ use crate::komorebi::Komorebi;
|
|||||||
use crate::komorebi::KomorebiNotificationState;
|
use crate::komorebi::KomorebiNotificationState;
|
||||||
use crate::widget::BarWidget;
|
use crate::widget::BarWidget;
|
||||||
use crate::widget::WidgetConfig;
|
use crate::widget::WidgetConfig;
|
||||||
|
use crate::MAX_LABEL_WIDTH;
|
||||||
use crossbeam_channel::Receiver;
|
use crossbeam_channel::Receiver;
|
||||||
use eframe::egui::Align;
|
use eframe::egui::Align;
|
||||||
use eframe::egui::CentralPanel;
|
use eframe::egui::CentralPanel;
|
||||||
@@ -30,6 +31,7 @@ use komorebi_themes::CatppuccinValue;
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct Komobar {
|
pub struct Komobar {
|
||||||
@@ -132,6 +134,11 @@ impl Komobar {
|
|||||||
config: &KomobarConfig,
|
config: &KomobarConfig,
|
||||||
previous_notification_state: Option<Rc<RefCell<KomorebiNotificationState>>>,
|
previous_notification_state: Option<Rc<RefCell<KomorebiNotificationState>>>,
|
||||||
) {
|
) {
|
||||||
|
MAX_LABEL_WIDTH.store(
|
||||||
|
config.max_label_width.unwrap_or(400.0) as i32,
|
||||||
|
Ordering::SeqCst,
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(font_family) = &config.font_family {
|
if let Some(font_family) = &config.font_family {
|
||||||
tracing::info!("attempting to add custom font family: {font_family}");
|
tracing::info!("attempting to add custom font family: {font_family}");
|
||||||
Self::add_custom_font(ctx, font_family);
|
Self::add_custom_font(ctx, font_family);
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ pub struct KomobarConfig {
|
|||||||
pub font_family: Option<String>,
|
pub font_family: Option<String>,
|
||||||
/// Font size (default: 12.5)
|
/// Font size (default: 12.5)
|
||||||
pub font_size: Option<f32>,
|
pub font_size: Option<f32>,
|
||||||
|
/// Max label width before text truncation (default: 400.0)
|
||||||
|
pub max_label_width: Option<f32>,
|
||||||
/// Theme
|
/// Theme
|
||||||
pub theme: Option<KomobarTheme>,
|
pub theme: Option<KomobarTheme>,
|
||||||
/// Left side widgets (ordered left-to-right)
|
/// Left side widgets (ordered left-to-right)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::bar::apply_theme;
|
use crate::bar::apply_theme;
|
||||||
use crate::config::KomobarTheme;
|
use crate::config::KomobarTheme;
|
||||||
|
use crate::ui::CustomUi;
|
||||||
use crate::widget::BarWidget;
|
use crate::widget::BarWidget;
|
||||||
|
use crate::MAX_LABEL_WIDTH;
|
||||||
use crate::WIDGET_SPACING;
|
use crate::WIDGET_SPACING;
|
||||||
use crossbeam_channel::Receiver;
|
use crossbeam_channel::Receiver;
|
||||||
use eframe::egui::text::LayoutJob;
|
use eframe::egui::text::LayoutJob;
|
||||||
@@ -16,6 +18,7 @@ use eframe::egui::TextStyle;
|
|||||||
use eframe::egui::TextureHandle;
|
use eframe::egui::TextureHandle;
|
||||||
use eframe::egui::TextureOptions;
|
use eframe::egui::TextureOptions;
|
||||||
use eframe::egui::Ui;
|
use eframe::egui::Ui;
|
||||||
|
use eframe::egui::Vec2;
|
||||||
use image::RgbaImage;
|
use image::RgbaImage;
|
||||||
use komorebi_client::CycleDirection;
|
use komorebi_client::CycleDirection;
|
||||||
use komorebi_client::NotificationEvent;
|
use komorebi_client::NotificationEvent;
|
||||||
@@ -28,6 +31,7 @@ use std::cell::RefCell;
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct KomorebiConfig {
|
pub struct KomorebiConfig {
|
||||||
@@ -295,36 +299,70 @@ impl BarWidget for Komorebi {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if titles.len() > 1 {
|
if titles.len() > 1 {
|
||||||
ui.add(Label::new(layout_job).selectable(false));
|
let available_height = ui.available_height();
|
||||||
|
let mut custom_ui = CustomUi(ui);
|
||||||
|
custom_ui.add_sized_left_to_right(
|
||||||
|
Vec2::new(
|
||||||
|
MAX_LABEL_WIDTH.load(Ordering::SeqCst) as f32,
|
||||||
|
available_height,
|
||||||
|
),
|
||||||
|
Label::new(layout_job).selectable(false).truncate(),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
ui.add(Label::new(title).selectable(false));
|
let available_height = ui.available_height();
|
||||||
}
|
let mut custom_ui = CustomUi(ui);
|
||||||
} else if ui
|
custom_ui.add_sized_left_to_right(
|
||||||
.add(Label::new(title).selectable(false).sense(Sense::click()))
|
Vec2::new(
|
||||||
.clicked()
|
MAX_LABEL_WIDTH.load(Ordering::SeqCst) as f32,
|
||||||
{
|
available_height,
|
||||||
if komorebi_client::send_message(&SocketMessage::MouseFollowsFocus(false))
|
),
|
||||||
.is_err()
|
Label::new(title).selectable(false).truncate(),
|
||||||
{
|
|
||||||
tracing::error!(
|
|
||||||
"could not send message to komorebi: MouseFollowsFocus"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let available_height = ui.available_height();
|
||||||
|
let mut custom_ui = CustomUi(ui);
|
||||||
|
|
||||||
if komorebi_client::send_message(&SocketMessage::FocusStackWindow(i))
|
if custom_ui
|
||||||
|
.add_sized_left_to_right(
|
||||||
|
Vec2::new(
|
||||||
|
MAX_LABEL_WIDTH.load(Ordering::SeqCst) as f32,
|
||||||
|
available_height,
|
||||||
|
),
|
||||||
|
Label::new(title)
|
||||||
|
.selectable(false)
|
||||||
|
.sense(Sense::click())
|
||||||
|
.truncate(),
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
|
{
|
||||||
|
if komorebi_client::send_message(&SocketMessage::MouseFollowsFocus(
|
||||||
|
false,
|
||||||
|
))
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
tracing::error!("could not send message to komorebi: FocusStackWindow");
|
tracing::error!(
|
||||||
}
|
"could not send message to komorebi: MouseFollowsFocus"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if komorebi_client::send_message(&SocketMessage::MouseFollowsFocus(
|
if komorebi_client::send_message(&SocketMessage::FocusStackWindow(i))
|
||||||
komorebi_notification_state.mouse_follows_focus,
|
.is_err()
|
||||||
))
|
{
|
||||||
.is_err()
|
tracing::error!(
|
||||||
{
|
"could not send message to komorebi: FocusStackWindow"
|
||||||
tracing::error!(
|
);
|
||||||
"could not send message to komorebi: MouseFollowsFocus"
|
}
|
||||||
);
|
|
||||||
|
if komorebi_client::send_message(&SocketMessage::MouseFollowsFocus(
|
||||||
|
komorebi_notification_state.mouse_follows_focus,
|
||||||
|
))
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
tracing::error!(
|
||||||
|
"could not send message to komorebi: MouseFollowsFocus"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ mod memory;
|
|||||||
mod network;
|
mod network;
|
||||||
mod storage;
|
mod storage;
|
||||||
mod time;
|
mod time;
|
||||||
|
mod ui;
|
||||||
mod widget;
|
mod widget;
|
||||||
|
|
||||||
use crate::bar::Komobar;
|
use crate::bar::Komobar;
|
||||||
@@ -24,11 +25,13 @@ use schemars::gen::SchemaSettings;
|
|||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::atomic::AtomicI32;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
pub static WIDGET_SPACING: f32 = 10.0;
|
pub static WIDGET_SPACING: f32 = 10.0;
|
||||||
|
pub static MAX_LABEL_WIDTH: AtomicI32 = AtomicI32::new(400);
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[clap(author, about, version)]
|
#[clap(author, about, version)]
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
use crate::ui::CustomUi;
|
||||||
use crate::widget::BarWidget;
|
use crate::widget::BarWidget;
|
||||||
|
use crate::MAX_LABEL_WIDTH;
|
||||||
use crate::WIDGET_SPACING;
|
use crate::WIDGET_SPACING;
|
||||||
use eframe::egui::text::LayoutJob;
|
use eframe::egui::text::LayoutJob;
|
||||||
use eframe::egui::Context;
|
use eframe::egui::Context;
|
||||||
@@ -8,9 +10,11 @@ use eframe::egui::Sense;
|
|||||||
use eframe::egui::TextFormat;
|
use eframe::egui::TextFormat;
|
||||||
use eframe::egui::TextStyle;
|
use eframe::egui::TextStyle;
|
||||||
use eframe::egui::Ui;
|
use eframe::egui::Ui;
|
||||||
|
use eframe::egui::Vec2;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
use windows::Media::Control::GlobalSystemMediaTransportControlsSessionManager;
|
use windows::Media::Control::GlobalSystemMediaTransportControlsSessionManager;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
@@ -98,8 +102,15 @@ impl BarWidget for Media {
|
|||||||
TextFormat::simple(font_id, ctx.style().visuals.text_color()),
|
TextFormat::simple(font_id, ctx.style().visuals.text_color()),
|
||||||
);
|
);
|
||||||
|
|
||||||
if ui
|
let available_height = ui.available_height();
|
||||||
.add(
|
let mut custom_ui = CustomUi(ui);
|
||||||
|
|
||||||
|
if custom_ui
|
||||||
|
.add_sized_left_to_right(
|
||||||
|
Vec2::new(
|
||||||
|
MAX_LABEL_WIDTH.load(Ordering::SeqCst) as f32,
|
||||||
|
available_height,
|
||||||
|
),
|
||||||
Label::new(layout_job)
|
Label::new(layout_job)
|
||||||
.selectable(false)
|
.selectable(false)
|
||||||
.sense(Sense::click())
|
.sense(Sense::click())
|
||||||
|
|||||||
22
komorebi-bar/src/ui.rs
Normal file
22
komorebi-bar/src/ui.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
use eframe::egui::Align;
|
||||||
|
use eframe::egui::Layout;
|
||||||
|
use eframe::egui::Response;
|
||||||
|
use eframe::egui::Ui;
|
||||||
|
use eframe::egui::Vec2;
|
||||||
|
use eframe::egui::Widget;
|
||||||
|
|
||||||
|
pub struct CustomUi<'ui>(pub &'ui mut Ui);
|
||||||
|
|
||||||
|
impl CustomUi<'_> {
|
||||||
|
pub fn add_sized_left_to_right(
|
||||||
|
&mut self,
|
||||||
|
max_size: impl Into<Vec2>,
|
||||||
|
widget: impl Widget,
|
||||||
|
) -> Response {
|
||||||
|
let layout =
|
||||||
|
Layout::from_main_dir_and_cross_align(self.0.layout().main_dir(), Align::Center);
|
||||||
|
self.0
|
||||||
|
.allocate_ui_with_layout(max_size.into(), layout, |ui| ui.add(widget))
|
||||||
|
.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -408,6 +408,11 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"max_label_width": {
|
||||||
|
"description": "Max label width before text truncation (default: 400.0)",
|
||||||
|
"type": "number",
|
||||||
|
"format": "float"
|
||||||
|
},
|
||||||
"monitor": {
|
"monitor": {
|
||||||
"description": "Monitor options",
|
"description": "Monitor options",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|||||||
Reference in New Issue
Block a user