From 655e8ce4c16117f51cb115597dd73d4bff6c7c9c Mon Sep 17 00:00:00 2001 From: Csaba Date: Fri, 8 Nov 2024 23:51:00 +0100 Subject: [PATCH] AlphaColour, transparency, bar background, more grouping config options --- komorebi-bar/src/bar.rs | 21 ++++--- komorebi-bar/src/config.rs | 27 +++++++++ komorebi-bar/src/group.rs | 118 +++++++++++++++++++++++++++++-------- komorebi-bar/src/main.rs | 5 +- komorebi-bar/src/widget.rs | 2 + komorebi/src/colour.rs | 12 ++++ 6 files changed, 152 insertions(+), 33 deletions(-) diff --git a/komorebi-bar/src/bar.rs b/komorebi-bar/src/bar.rs index 5b3d14c7..f2e2f6e8 100644 --- a/komorebi-bar/src/bar.rs +++ b/komorebi-bar/src/bar.rs @@ -26,8 +26,10 @@ use eframe::egui::FontId; use eframe::egui::Frame; use eframe::egui::Layout; use eframe::egui::Margin; +use eframe::egui::Rgba; use eframe::egui::Style; use eframe::egui::TextStyle; +use eframe::egui::Visuals; use font_loader::system_fonts; use font_loader::system_fonts::FontPropertyBuilder; use komorebi_client::KomorebiTheme; @@ -320,9 +322,10 @@ impl Komobar { config: config.clone(), render_config: Rc::new(RefCell::new(RenderConfig { grouping: match config.grouping { - None => Grouping::None, Some(grouping) => grouping, + None => Grouping::None, }, + background_color: config.background.map(|value| value.into()), })), komorebi_notification_state: None, left_widgets: vec![], @@ -394,13 +397,10 @@ impl Komobar { } } impl eframe::App for Komobar { - // TODO: I think this is needed for transparency?? - // fn clear_color(&self, _visuals: &Visuals) -> [f32; 4] { - // egui::Rgba::TRANSPARENT.to_array() - // let mut background = Color32::from_gray(18).to_normalized_gamma_f32(); - // background[3] = 0.9; - // background - // } + // Needed for transparency + fn clear_color(&self, _visuals: &Visuals) -> [f32; 4] { + Rgba::TRANSPARENT.to_array() + } fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) { if self.scale_factor != ctx.native_pixels_per_point().unwrap_or(1.0) { @@ -446,6 +446,11 @@ impl eframe::App for Komobar { let mut render_config = self.render_config.borrow_mut(); let render_config_clone = *render_config; + // prefer the custom background from the config + if let Some(bg_color) = render_config.background_color { + self.bg_color.replace(bg_color); + }; + CentralPanel::default().frame(frame).show(ctx, |ui| { ui.horizontal_centered(|ui| { ui.with_layout(Layout::left_to_right(Align::Center), |ui| { diff --git a/komorebi-bar/src/config.rs b/komorebi-bar/src/config.rs index 4aa2bafe..63782916 100644 --- a/komorebi-bar/src/config.rs +++ b/komorebi-bar/src/config.rs @@ -1,8 +1,10 @@ use crate::group::Grouping; use crate::widget::WidgetConfig; +use eframe::egui::Color32; use eframe::egui::Pos2; use eframe::egui::TextBuffer; use eframe::egui::Vec2; +use komorebi_client::Colour; use komorebi_client::KomorebiTheme; use komorebi_client::Rect; use schemars::JsonSchema; @@ -29,6 +31,8 @@ pub struct KomobarConfig { pub max_label_width: Option, /// Theme pub theme: Option, + /// Background color + pub background: Option, /// Visual grouping for widgets pub grouping: Option, /// Left side widgets (ordered left-to-right) @@ -181,3 +185,26 @@ pub enum LabelPrefix { /// Show an icon and text IconAndText, } + +#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)] +pub struct AlphaColour { + /// Color + pub color: Option, + /// Alpha value for the color transparency [[0-255]] (default: 200) + pub transparency_alpha: Option, +} + +impl From for Color32 { + fn from(value: AlphaColour) -> Self { + let color = match value.color { + Some(color) => color.into(), + None => Color32::from_rgb(0, 0, 0), + }; + + if let Some(alpha) = value.transparency_alpha { + return Color32::from_rgba_premultiplied(color.r(), color.g(), color.b(), alpha); + } + + color + } +} diff --git a/komorebi-bar/src/group.rs b/komorebi-bar/src/group.rs index 01ec25ca..b572a8a2 100644 --- a/komorebi-bar/src/group.rs +++ b/komorebi-bar/src/group.rs @@ -1,9 +1,14 @@ -//use eframe::egui::Color32; +use crate::config::AlphaColour; +use eframe::egui::Color32; use eframe::egui::Frame; use eframe::egui::InnerResponse; use eframe::egui::Margin; use eframe::egui::Rounding; +use eframe::egui::Stroke; use eframe::egui::Ui; +use komorebi_client::Colour; +use komorebi_client::Rect; +use komorebi_client::Rgb; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; @@ -25,21 +30,33 @@ impl Grouping { add_contents: impl FnOnce(&mut Ui) -> R, ) -> InnerResponse { match self { - Self::None => InnerResponse { + Self::Widget(config) => Frame::none() + .fill(match config.fill { + Some(color) => color.into(), + None => Color32::TRANSPARENT, + }) + .outer_margin(match config.outer_margin { + Some(margin) => Self::rect_to_margin(margin), + None => Margin::symmetric(0.0, 0.0), + }) + .inner_margin(match config.inner_margin { + Some(margin) => Self::rect_to_margin(margin), + None => Margin::symmetric(7.0, 2.0), + }) + .rounding(match config.rounding { + Some(rounding) => rounding.into(), + None => Rounding::same(10.0), + }) + .stroke(match config.stroke { + Some(line) => line.into(), + None => ui.style().visuals.widgets.noninteractive.bg_stroke, + }) + .show(ui, add_contents), + Self::Side(_config) => InnerResponse { inner: add_contents(ui), response: ui.response().clone(), }, - Self::Widget(config) => Frame::none() - //.fill(Color32::from_black_alpha(255u8)) - .outer_margin(Margin::symmetric(0.0, 0.0)) - .inner_margin(Margin::symmetric(7.0, 2.0)) - .rounding(match config.rounding { - None => Rounding::same(15.0), - Some(rounding) => rounding.into(), - }) - .stroke(ui.style().visuals.widgets.noninteractive.bg_stroke) - .show(ui, add_contents), - Self::Side(_config) => InnerResponse { + Self::None => InnerResponse { inner: add_contents(ui), response: ui.response().clone(), }, @@ -52,31 +69,84 @@ impl Grouping { add_contents: impl FnOnce(&mut Ui) -> R, ) -> InnerResponse { match self { - Self::None => InnerResponse { - inner: add_contents(ui), - response: ui.response().clone(), - }, Self::Widget(_config) => InnerResponse { inner: add_contents(ui), response: ui.response().clone(), }, Self::Side(config) => Frame::none() - //.fill(Color32::from_black_alpha(255u8)) - .outer_margin(Margin::symmetric(0.0, 0.0)) - .inner_margin(Margin::symmetric(7.0, 2.0)) - .rounding(match config.rounding { - None => Rounding::same(15.0), - Some(rounding) => rounding.into(), + .fill(match config.fill { + Some(color) => color.into(), + None => Color32::TRANSPARENT, + }) + .outer_margin(match config.outer_margin { + Some(margin) => Self::rect_to_margin(margin), + None => Margin::symmetric(0.0, 0.0), + }) + .inner_margin(match config.inner_margin { + Some(margin) => Self::rect_to_margin(margin), + None => Margin::symmetric(7.0, 2.0), + }) + .rounding(match config.rounding { + Some(rounding) => rounding.into(), + None => Rounding::same(10.0), + }) + .stroke(match config.stroke { + Some(line) => line.into(), + None => ui.style().visuals.widgets.noninteractive.bg_stroke, }) - .stroke(ui.style().visuals.widgets.noninteractive.bg_stroke) .show(ui, add_contents), + Self::None => InnerResponse { + inner: add_contents(ui), + response: ui.response().clone(), + }, + } + } + + fn rect_to_margin(rect: Rect) -> Margin { + Margin { + left: rect.left as f32, + right: rect.right as f32, + top: rect.top as f32, + bottom: rect.bottom as f32, + } + } + + // NOTE: this is also in the komorebi_gui. Should be moved to the "komorebi colour" + pub fn colour_to_color32(colour: Option) -> Color32 { + match colour { + Some(Colour::Rgb(rgb)) => Color32::from_rgb(rgb.r as u8, rgb.g as u8, rgb.b as u8), + Some(Colour::Hex(hex)) => { + let rgb = Rgb::from(hex); + Color32::from_rgb(rgb.r as u8, rgb.g as u8, rgb.b as u8) + } + //None => Color32::from_rgb(0, 0, 0), + None => Color32::TRANSPARENT, } } } #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct GroupingConfig { + pub fill: Option, pub rounding: Option, + pub outer_margin: Option, + pub inner_margin: Option, + pub stroke: Option, +} + +#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)] +pub struct Line { + pub width: f32, + pub color: Option, +} + +impl From for Stroke { + fn from(value: Line) -> Self { + Self { + width: value.width, + color: Grouping::colour_to_color32(value.color), + } + } } #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)] diff --git a/komorebi-bar/src/main.rs b/komorebi-bar/src/main.rs index 3cba0e01..b179ac0e 100644 --- a/komorebi-bar/src/main.rs +++ b/komorebi-bar/src/main.rs @@ -267,7 +267,10 @@ fn main() -> color_eyre::Result<()> { let viewport_builder = ViewportBuilder::default() .with_decorations(false) - // .with_transparent(config.transparent) + .with_transparent(match config.background { + None => false, + Some(color) => color.transparency_alpha.is_some(), + }) .with_taskbar(false); let native_options = eframe::NativeOptions { diff --git a/komorebi-bar/src/widget.rs b/komorebi-bar/src/widget.rs index 5f9f9584..027db543 100644 --- a/komorebi-bar/src/widget.rs +++ b/komorebi-bar/src/widget.rs @@ -17,6 +17,7 @@ use crate::storage::Storage; use crate::storage::StorageConfig; use crate::time::Time; use crate::time::TimeConfig; +use eframe::egui::Color32; use eframe::egui::Context; use eframe::egui::Ui; use schemars::JsonSchema; @@ -31,6 +32,7 @@ pub trait BarWidget { pub struct RenderConfig { /// Sets how widgets are grouped pub grouping: Grouping, + pub background_color: Option, } #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] diff --git a/komorebi/src/colour.rs b/komorebi/src/colour.rs index 7e69a920..7577ccd0 100644 --- a/komorebi/src/colour.rs +++ b/komorebi/src/colour.rs @@ -39,6 +39,18 @@ impl From for Colour { } } +impl From for Color32 { + fn from(value: Colour) -> Self { + match value { + Colour::Rgb(rgb) => Color32::from_rgb(rgb.r as u8, rgb.g as u8, rgb.b as u8), + Colour::Hex(hex) => { + let rgb = Rgb::from(hex); + Color32::from_rgb(rgb.r as u8, rgb.g as u8, rgb.b as u8) + } + } + } +} + #[derive(Debug, Copy, Clone, Serialize, Deserialize)] pub struct Hex(HexColor);