refactoring of render and grouping, widget spacing WIP

This commit is contained in:
Csaba
2024-11-13 22:08:58 +01:00
parent c18e5f4dbe
commit cba2b2f7ac
14 changed files with 168 additions and 166 deletions

View File

@@ -1,16 +1,16 @@
use crate::config::Color32Ext;
use crate::config::KomobarConfig; use crate::config::KomobarConfig;
use crate::config::KomobarTheme; use crate::config::KomobarTheme;
use crate::config::Position; use crate::config::Position;
use crate::config::PositionConfig; use crate::config::PositionConfig;
use crate::group::Grouping;
use crate::komorebi::Komorebi; use crate::komorebi::Komorebi;
use crate::komorebi::KomorebiNotificationState; use crate::komorebi::KomorebiNotificationState;
use crate::process_hwnd; use crate::process_hwnd;
use crate::render::Color32Ext;
use crate::render::Grouping;
use crate::render::RenderConfig;
use crate::render::RenderExt;
use crate::widget::BarWidget; use crate::widget::BarWidget;
use crate::widget::RenderConfig;
use crate::widget::WidgetConfig; use crate::widget::WidgetConfig;
use crate::BACKGROUND_COLOR;
use crate::BAR_HEIGHT; use crate::BAR_HEIGHT;
use crate::MAX_LABEL_WIDTH; use crate::MAX_LABEL_WIDTH;
use crate::MONITOR_LEFT; use crate::MONITOR_LEFT;
@@ -260,11 +260,10 @@ impl Komobar {
} }
} }
self.render_config.replace(config.into());
let theme_color = *self.bg_color.borrow(); let theme_color = *self.bg_color.borrow();
BACKGROUND_COLOR.store(theme_color.to_u32(), Ordering::SeqCst); self.render_config
.replace(config.new_renderconfig(theme_color));
self.bg_color self.bg_color
.replace(theme_color.try_apply_alpha(self.config.transparency_alpha)); .replace(theme_color.try_apply_alpha(self.config.transparency_alpha));
@@ -351,7 +350,9 @@ impl Komobar {
render_config: Rc::new(RefCell::new(RenderConfig { render_config: Rc::new(RefCell::new(RenderConfig {
spacing: 0.0, spacing: 0.0,
grouping: Grouping::None, grouping: Grouping::None,
background_color: Color32::BLACK,
alignment: None, alignment: None,
no_spacing: None,
})), })),
komorebi_notification_state: None, komorebi_notification_state: None,
left_widgets: vec![], left_widgets: vec![],
@@ -472,16 +473,21 @@ impl eframe::App for Komobar {
CentralPanel::default().frame(frame).show(ctx, |ui| { CentralPanel::default().frame(frame).show(ctx, |ui| {
// Apply grouping logic for the bar as a whole // Apply grouping logic for the bar as a whole
render_config.grouping.clone().apply_on_bar(ui, |ui| { render_config.clone().apply_on_bar(ui, |ui| {
ui.horizontal_centered(|ui| { ui.horizontal_centered(|ui| {
// Left-aligned widgets layout // Left-aligned widgets layout
ui.with_layout(Layout::left_to_right(Align::Center), |ui| { ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
let mut render_conf = *render_config; let mut render_conf = *render_config;
render_conf.alignment = Some(Alignment::Left); render_conf.alignment = Some(Alignment::Left);
render_config.grouping.apply_on_alignment(ui, |ui| { render_config.apply_on_alignment(ui, |ui| {
for w in &mut self.left_widgets { if let Some((last, rest)) = self.left_widgets.split_last_mut() {
w.render(ctx, ui, render_conf); for w in rest.iter_mut() {
w.render(ctx, ui, render_conf);
}
render_conf.no_spacing = Some(true);
last.render(ctx, ui, render_conf);
} }
}); });
}); });
@@ -491,9 +497,14 @@ impl eframe::App for Komobar {
let mut render_conf = *render_config; let mut render_conf = *render_config;
render_conf.alignment = Some(Alignment::Right); render_conf.alignment = Some(Alignment::Right);
render_config.grouping.apply_on_alignment(ui, |ui| { render_config.apply_on_alignment(ui, |ui| {
for w in &mut self.right_widgets { if let Some((last, rest)) = self.right_widgets.split_last_mut() {
w.render(ctx, ui, render_conf); for w in rest.iter_mut() {
w.render(ctx, ui, render_conf);
}
render_conf.no_spacing = Some(true);
last.render(ctx, ui, render_conf);
} }
}); });
}) })

View File

@@ -1,6 +1,6 @@
use crate::config::LabelPrefix; use crate::config::LabelPrefix;
use crate::render::RenderConfig;
use crate::widget::BarWidget; use crate::widget::BarWidget;
use crate::widget::RenderConfig;
use eframe::egui::text::LayoutJob; use eframe::egui::text::LayoutJob;
use eframe::egui::Context; use eframe::egui::Context;
use eframe::egui::FontId; use eframe::egui::FontId;
@@ -147,7 +147,7 @@ impl BarWidget for Battery {
TextFormat::simple(font_id, ctx.style().visuals.text_color()), TextFormat::simple(font_id, ctx.style().visuals.text_color()),
); );
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
ui.add( ui.add(
Label::new(layout_job) Label::new(layout_job)
.selectable(false) .selectable(false)

View File

@@ -1,7 +1,5 @@
use crate::group::Grouping; use crate::render::Grouping;
use crate::widget::RenderConfig;
use crate::widget::WidgetConfig; use crate::widget::WidgetConfig;
use eframe::egui::Color32;
use eframe::egui::Pos2; use eframe::egui::Pos2;
use eframe::egui::TextBuffer; use eframe::egui::TextBuffer;
use eframe::egui::Vec2; use eframe::egui::Vec2;
@@ -33,7 +31,7 @@ pub struct KomobarConfig {
pub theme: Option<KomobarTheme>, pub theme: Option<KomobarTheme>,
/// Alpha value for the color transparency [[0-255]] (default: 200) /// Alpha value for the color transparency [[0-255]] (default: 200)
pub transparency_alpha: Option<u8>, pub transparency_alpha: Option<u8>,
/// Spacing between widgets /// Spacing between widgets (default: 10.0)
pub widget_spacing: Option<f32>, pub widget_spacing: Option<f32>,
/// Visual grouping for widgets /// Visual grouping for widgets
pub grouping: Option<Grouping>, pub grouping: Option<Grouping>,
@@ -72,16 +70,6 @@ impl KomobarConfig {
} }
} }
impl From<&KomobarConfig> for RenderConfig {
fn from(value: &KomobarConfig) -> Self {
RenderConfig {
spacing: value.widget_spacing.unwrap_or(10.0),
grouping: value.grouping.unwrap_or(Grouping::None),
alignment: None,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
pub struct PositionConfig { pub struct PositionConfig {
/// The desired starting position of the bar (0,0 = top left of the screen) /// The desired starting position of the bar (0,0 = top left of the screen)
@@ -197,37 +185,3 @@ pub enum LabelPrefix {
/// Show an icon and text /// Show an icon and text
IconAndText, IconAndText,
} }
pub trait Color32Ext {
fn to_u32(&self) -> u32;
fn from_u32(color: u32) -> Self;
fn try_apply_alpha(self, transparency_alpha: Option<u8>) -> Self;
}
impl Color32Ext for Color32 {
/// Converts Color32 to u32 (ARGB format)
fn to_u32(&self) -> u32 {
((self.a() as u32) << 24)
| ((self.r() as u32) << 16)
| ((self.g() as u32) << 8)
| (self.b() as u32)
}
/// Converts u32 back to Color32 (ARGB format)
fn from_u32(color: u32) -> Self {
let a = ((color >> 24) & 0xFF) as u8;
let r = ((color >> 16) & 0xFF) as u8;
let g = ((color >> 8) & 0xFF) as u8;
let b = (color & 0xFF) as u8;
Color32::from_rgba_premultiplied(r, g, b, a)
}
/// Tries to apply the alpha value to the Color32
fn try_apply_alpha(self, transparency_alpha: Option<u8>) -> Self {
if let Some(alpha) = transparency_alpha {
return Color32::from_rgba_unmultiplied(self.r(), self.g(), self.b(), alpha);
}
self
}
}

View File

@@ -1,6 +1,6 @@
use crate::config::LabelPrefix; use crate::config::LabelPrefix;
use crate::render::RenderConfig;
use crate::widget::BarWidget; use crate::widget::BarWidget;
use crate::widget::RenderConfig;
use eframe::egui::text::LayoutJob; use eframe::egui::text::LayoutJob;
use eframe::egui::Context; use eframe::egui::Context;
use eframe::egui::FontId; use eframe::egui::FontId;
@@ -99,7 +99,7 @@ impl BarWidget for Cpu {
TextFormat::simple(font_id, ctx.style().visuals.text_color()), TextFormat::simple(font_id, ctx.style().visuals.text_color()),
); );
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
if ui if ui
.add( .add(
Label::new(layout_job) Label::new(layout_job)

View File

@@ -1,6 +1,6 @@
use crate::config::LabelPrefix; use crate::config::LabelPrefix;
use crate::render::RenderConfig;
use crate::widget::BarWidget; use crate::widget::BarWidget;
use crate::widget::RenderConfig;
use eframe::egui::text::LayoutJob; use eframe::egui::text::LayoutJob;
use eframe::egui::Context; use eframe::egui::Context;
use eframe::egui::FontId; use eframe::egui::FontId;
@@ -119,7 +119,7 @@ impl BarWidget for Date {
TextFormat::simple(font_id, ctx.style().visuals.text_color()), TextFormat::simple(font_id, ctx.style().visuals.text_color()),
); );
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
if ui if ui
.add( .add(
Label::new(WidgetText::LayoutJob(layout_job.clone())) Label::new(WidgetText::LayoutJob(layout_job.clone()))

View File

@@ -1,8 +1,8 @@
use crate::bar::apply_theme; use crate::bar::apply_theme;
use crate::config::KomobarTheme; use crate::config::KomobarTheme;
use crate::render::RenderConfig;
use crate::ui::CustomUi; use crate::ui::CustomUi;
use crate::widget::BarWidget; use crate::widget::BarWidget;
use crate::widget::RenderConfig;
use crate::MAX_LABEL_WIDTH; use crate::MAX_LABEL_WIDTH;
use crossbeam_channel::Receiver; use crossbeam_channel::Receiver;
use crossbeam_channel::TryRecvError; use crossbeam_channel::TryRecvError;
@@ -129,7 +129,7 @@ impl BarWidget for Komorebi {
let mut update = None; let mut update = None;
// NOTE: There should always be at least one workspace. // NOTE: There should always be at least one workspace.
config.grouping.apply_on_widget(false, config, ui, |ui| { config.apply_on_widget(false, ui, |ui| {
for (i, (ws, should_show)) in for (i, (ws, should_show)) in
komorebi_notification_state.workspaces.iter().enumerate() komorebi_notification_state.workspaces.iter().enumerate()
{ {
@@ -196,7 +196,7 @@ impl BarWidget for Komorebi {
if let Some(layout) = self.layout { if let Some(layout) = self.layout {
if layout.enable { if layout.enable {
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
if ui if ui
.add( .add(
Label::new(komorebi_notification_state.layout.to_string()) Label::new(komorebi_notification_state.layout.to_string())
@@ -247,7 +247,7 @@ impl BarWidget for Komorebi {
for (name, location) in configuration_switcher.configurations.iter() { for (name, location) in configuration_switcher.configurations.iter() {
let path = PathBuf::from(location); let path = PathBuf::from(location);
if path.is_file() { if path.is_file() {
config.grouping.apply_on_widget(true, config, ui,|ui|{ config.apply_on_widget(true, ui,|ui|{
if ui if ui
.add(Label::new(name).selectable(false).sense(Sense::click())) .add(Label::new(name).selectable(false).sense(Sense::click()))
.clicked() .clicked()
@@ -305,7 +305,7 @@ impl BarWidget for Komorebi {
let titles = &komorebi_notification_state.focused_container_information.0; let titles = &komorebi_notification_state.focused_container_information.0;
if !titles.is_empty() { if !titles.is_empty() {
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
let icons = &komorebi_notification_state.focused_container_information.1; let icons = &komorebi_notification_state.focused_container_information.1;
let focused_window_idx = let focused_window_idx =
komorebi_notification_state.focused_container_information.2; komorebi_notification_state.focused_container_information.2;

View File

@@ -3,11 +3,11 @@ mod battery;
mod config; mod config;
mod cpu; mod cpu;
mod date; mod date;
mod group;
mod komorebi; mod komorebi;
mod media; mod media;
mod memory; mod memory;
mod network; mod network;
mod render;
mod storage; mod storage;
mod time; mod time;
mod ui; mod ui;
@@ -29,7 +29,6 @@ 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::atomic::AtomicI32;
use std::sync::atomic::AtomicU32;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
@@ -44,7 +43,6 @@ use windows::Win32::UI::HiDpi::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
use windows::Win32::UI::WindowsAndMessaging::EnumThreadWindows; use windows::Win32::UI::WindowsAndMessaging::EnumThreadWindows;
use windows::Win32::UI::WindowsAndMessaging::GetWindowThreadProcessId; use windows::Win32::UI::WindowsAndMessaging::GetWindowThreadProcessId;
pub static BACKGROUND_COLOR: AtomicU32 = AtomicU32::new(0);
pub static MAX_LABEL_WIDTH: AtomicI32 = AtomicI32::new(400); pub static MAX_LABEL_WIDTH: AtomicI32 = AtomicI32::new(400);
pub static MONITOR_LEFT: AtomicI32 = AtomicI32::new(0); pub static MONITOR_LEFT: AtomicI32 = AtomicI32::new(0);
pub static MONITOR_TOP: AtomicI32 = AtomicI32::new(0); pub static MONITOR_TOP: AtomicI32 = AtomicI32::new(0);

View File

@@ -1,6 +1,6 @@
use crate::render::RenderConfig;
use crate::ui::CustomUi; use crate::ui::CustomUi;
use crate::widget::BarWidget; use crate::widget::BarWidget;
use crate::widget::RenderConfig;
use crate::MAX_LABEL_WIDTH; use crate::MAX_LABEL_WIDTH;
use eframe::egui::text::LayoutJob; use eframe::egui::text::LayoutJob;
use eframe::egui::Context; use eframe::egui::Context;
@@ -102,7 +102,7 @@ impl BarWidget for Media {
TextFormat::simple(font_id, ctx.style().visuals.text_color()), TextFormat::simple(font_id, ctx.style().visuals.text_color()),
); );
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
let available_height = ui.available_height(); let available_height = ui.available_height();
let mut custom_ui = CustomUi(ui); let mut custom_ui = CustomUi(ui);

View File

@@ -1,6 +1,6 @@
use crate::config::LabelPrefix; use crate::config::LabelPrefix;
use crate::render::RenderConfig;
use crate::widget::BarWidget; use crate::widget::BarWidget;
use crate::widget::RenderConfig;
use eframe::egui::text::LayoutJob; use eframe::egui::text::LayoutJob;
use eframe::egui::Context; use eframe::egui::Context;
use eframe::egui::FontId; use eframe::egui::FontId;
@@ -102,7 +102,7 @@ impl BarWidget for Memory {
TextFormat::simple(font_id, ctx.style().visuals.text_color()), TextFormat::simple(font_id, ctx.style().visuals.text_color()),
); );
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
if ui if ui
.add( .add(
Label::new(layout_job) Label::new(layout_job)

View File

@@ -1,6 +1,6 @@
use crate::config::LabelPrefix; use crate::config::LabelPrefix;
use crate::render::RenderConfig;
use crate::widget::BarWidget; use crate::widget::BarWidget;
use crate::widget::RenderConfig;
use eframe::egui::text::LayoutJob; use eframe::egui::text::LayoutJob;
use eframe::egui::Context; use eframe::egui::Context;
use eframe::egui::FontId; use eframe::egui::FontId;
@@ -320,7 +320,7 @@ impl BarWidget for Network {
fn render(&mut self, ctx: &Context, ui: &mut Ui, mut config: RenderConfig) { fn render(&mut self, ctx: &Context, ui: &mut Ui, mut config: RenderConfig) {
if self.show_total_data_transmitted { if self.show_total_data_transmitted {
for output in self.total_data_transmitted() { for output in self.total_data_transmitted() {
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
ui.add(Label::new(output).selectable(false)); ui.add(Label::new(output).selectable(false));
}); });
} }
@@ -328,7 +328,7 @@ impl BarWidget for Network {
if self.show_network_activity { if self.show_network_activity {
for output in self.network_activity() { for output in self.network_activity() {
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
ui.add(Label::new(output).selectable(false)); ui.add(Label::new(output).selectable(false));
}); });
} }
@@ -367,7 +367,7 @@ impl BarWidget for Network {
TextFormat::simple(font_id, ctx.style().visuals.text_color()), TextFormat::simple(font_id, ctx.style().visuals.text_color()),
); );
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
if ui if ui
.add( .add(
Label::new(layout_job) Label::new(layout_job)

View File

@@ -1,7 +1,5 @@
use crate::bar::Alignment; use crate::bar::Alignment;
use crate::config::Color32Ext; use crate::config::KomobarConfig;
use crate::widget::RenderConfig;
use crate::BACKGROUND_COLOR;
use eframe::egui::Color32; use eframe::egui::Color32;
use eframe::egui::Frame; use eframe::egui::Frame;
use eframe::egui::InnerResponse; use eframe::egui::InnerResponse;
@@ -13,7 +11,6 @@ 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;
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)] #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind")] #[serde(tag = "kind")]
@@ -28,18 +25,49 @@ pub enum Grouping {
Widget(GroupingConfig), Widget(GroupingConfig),
} }
impl Grouping { #[derive(Copy, Clone)]
pub struct RenderConfig {
/// Spacing between widgets
pub spacing: f32,
/// Sets how widgets are grouped
pub grouping: Grouping,
/// Background color
pub background_color: Color32,
/// Alignment of the widgets
pub alignment: Option<Alignment>,
/// Remove spacing if true
pub no_spacing: Option<bool>,
}
pub trait RenderExt {
fn new_renderconfig(&self, background_color: Color32) -> RenderConfig;
}
impl RenderExt for &KomobarConfig {
fn new_renderconfig(&self, background_color: Color32) -> RenderConfig {
RenderConfig {
spacing: self.widget_spacing.unwrap_or(10.0),
grouping: self.grouping.unwrap_or(Grouping::None),
background_color,
alignment: None,
no_spacing: None,
}
}
}
impl RenderConfig {
pub fn apply_on_bar<R>( pub fn apply_on_bar<R>(
&mut self, &mut self,
ui: &mut Ui, ui: &mut Ui,
add_contents: impl FnOnce(&mut Ui) -> R, add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> { ) -> InnerResponse<R> {
match self { self.alignment = None;
Self::Bar(config) => Self::define_group(false, None, ui, add_contents, config),
Self::Alignment(_) => Self::no_group(ui, add_contents), if let Grouping::Bar(config) = self.grouping {
Self::Widget(_) => Self::no_group(ui, add_contents), return self.define_group(false, config, ui, add_contents);
Self::None => Self::no_group(ui, add_contents),
} }
Self::fallback_group(ui, add_contents)
} }
pub fn apply_on_alignment<R>( pub fn apply_on_alignment<R>(
@@ -47,42 +75,65 @@ impl Grouping {
ui: &mut Ui, ui: &mut Ui,
add_contents: impl FnOnce(&mut Ui) -> R, add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> { ) -> InnerResponse<R> {
match self { self.alignment = None;
Self::Bar(_) => Self::no_group(ui, add_contents),
Self::Alignment(config) => Self::define_group(false, None, ui, add_contents, config), if let Grouping::Alignment(config) = self.grouping {
Self::Widget(_) => Self::no_group(ui, add_contents), return self.define_group(false, config, ui, add_contents);
Self::None => Self::no_group(ui, add_contents),
} }
Self::fallback_group(ui, add_contents)
} }
pub fn apply_on_widget<R>( pub fn apply_on_widget<R>(
&mut self, &mut self,
use_spacing: bool, use_spacing: bool,
render_config: RenderConfig, // TODO: this should remove the margin on the last widget on the left side and the first widget on the right side
// This is complex, since the last/first widget can have multiple "sections", like komorebi, network, ...
// This and the same setting on RenderConfig needs to be combined.
//_first_or_last: Option<bool>,
ui: &mut Ui, ui: &mut Ui,
add_contents: impl FnOnce(&mut Ui) -> R, add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> { ) -> InnerResponse<R> {
match self { if let Grouping::Widget(config) = self.grouping {
Self::Bar(_) => Self::widget_group(use_spacing, render_config, ui, add_contents), return self.define_group(use_spacing, config, ui, add_contents);
Self::Alignment(_) => Self::widget_group(use_spacing, render_config, ui, add_contents), }
Self::Widget(config) => {
Self::define_group(use_spacing, Some(render_config), ui, add_contents, config) self.fallback_widget_group(use_spacing, ui, add_contents)
} }
Self::None => Self::widget_group(use_spacing, render_config, ui, add_contents),
fn fallback_group<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
InnerResponse {
inner: add_contents(ui),
response: ui.response().clone(),
} }
} }
fn define_group<R>( fn fallback_widget_group<R>(
&mut self,
use_spacing: bool, use_spacing: bool,
render_config: Option<RenderConfig>,
ui: &mut Ui, ui: &mut Ui,
add_contents: impl FnOnce(&mut Ui) -> R, add_contents: impl FnOnce(&mut Ui) -> R,
config: &mut GroupingConfig,
) -> InnerResponse<R> { ) -> InnerResponse<R> {
Frame::none() Frame::none()
.outer_margin(Self::widget_outer_margin(render_config)) .outer_margin(self.widget_outer_margin())
.inner_margin(match use_spacing { .inner_margin(match use_spacing {
true => Margin::symmetric(5.0 + 3.0, 3.0), true => Margin::symmetric(5.0, 0.0),
false => Margin::same(0.0),
})
.show(ui, add_contents)
}
fn define_group<R>(
&mut self,
use_spacing: bool,
config: GroupingConfig,
ui: &mut Ui,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> {
Frame::none()
.outer_margin(self.widget_outer_margin())
.inner_margin(match use_spacing {
true => Margin::symmetric(8.0, 3.0),
false => Margin::symmetric(3.0, 3.0), false => Margin::symmetric(3.0, 3.0),
}) })
.stroke(ui.style().visuals.widgets.noninteractive.bg_stroke) .stroke(ui.style().visuals.widgets.noninteractive.bg_stroke)
@@ -91,7 +142,7 @@ impl Grouping {
None => ui.style().visuals.widgets.noninteractive.rounding, None => ui.style().visuals.widgets.noninteractive.rounding,
}) })
.fill( .fill(
Color32::from_u32(BACKGROUND_COLOR.load(Ordering::SeqCst)) self.background_color
.try_apply_alpha(config.transparency_alpha), .try_apply_alpha(config.transparency_alpha),
) )
.shadow(match config.style { .shadow(match config.style {
@@ -110,47 +161,31 @@ impl Grouping {
.show(ui, add_contents) .show(ui, add_contents)
} }
fn widget_group<R>( fn widget_outer_margin(&self) -> Margin {
use_spacing: bool,
render_config: RenderConfig,
ui: &mut Ui,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> {
Frame::none()
.outer_margin(Self::widget_outer_margin(Some(render_config)))
.inner_margin(match use_spacing {
true => Margin::symmetric(5.0, 0.0),
false => Margin::same(0.0),
})
.show(ui, add_contents)
}
fn no_group<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
InnerResponse {
inner: add_contents(ui),
response: ui.response().clone(),
}
}
fn widget_outer_margin(render_config: Option<RenderConfig>) -> Margin {
Margin { Margin {
left: match render_config { left: match self.alignment {
Some(config) => match config.alignment { Some(align) => match align {
Some(align) => match align { Alignment::Left => 0.0,
Alignment::Left => 0.0, Alignment::Right => {
Alignment::Right => config.spacing, if self.no_spacing.is_some_and(|v| v) {
}, 0.0
None => 0.0, } else {
self.spacing
}
}
}, },
None => 0.0, None => 0.0,
}, },
right: match render_config { right: match self.alignment {
Some(config) => match config.alignment { Some(align) => match align {
Some(align) => match align { Alignment::Left => {
Alignment::Left => config.spacing, if self.no_spacing.is_some_and(|v| v) {
Alignment::Right => 0.0, 0.0
}, } else {
None => 0.0, self.spacing
}
}
Alignment::Right => 0.0,
}, },
None => 0.0, None => 0.0,
}, },
@@ -195,3 +230,18 @@ impl From<RoundingConfig> for Rounding {
} }
} }
} }
pub trait Color32Ext {
fn try_apply_alpha(self, transparency_alpha: Option<u8>) -> Self;
}
impl Color32Ext for Color32 {
/// Tries to apply the alpha value to the Color32
fn try_apply_alpha(self, transparency_alpha: Option<u8>) -> Self {
if let Some(alpha) = transparency_alpha {
return Color32::from_rgba_unmultiplied(self.r(), self.g(), self.b(), alpha);
}
self
}
}

View File

@@ -1,6 +1,6 @@
use crate::config::LabelPrefix; use crate::config::LabelPrefix;
use crate::render::RenderConfig;
use crate::widget::BarWidget; use crate::widget::BarWidget;
use crate::widget::RenderConfig;
use eframe::egui::text::LayoutJob; use eframe::egui::text::LayoutJob;
use eframe::egui::Context; use eframe::egui::Context;
use eframe::egui::FontId; use eframe::egui::FontId;
@@ -107,7 +107,7 @@ impl BarWidget for Storage {
TextFormat::simple(font_id.clone(), ctx.style().visuals.text_color()), TextFormat::simple(font_id.clone(), ctx.style().visuals.text_color()),
); );
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
if ui if ui
.add( .add(
Label::new(layout_job) Label::new(layout_job)

View File

@@ -1,6 +1,6 @@
use crate::config::LabelPrefix; use crate::config::LabelPrefix;
use crate::render::RenderConfig;
use crate::widget::BarWidget; use crate::widget::BarWidget;
use crate::widget::RenderConfig;
use eframe::egui::text::LayoutJob; use eframe::egui::text::LayoutJob;
use eframe::egui::Context; use eframe::egui::Context;
use eframe::egui::FontId; use eframe::egui::FontId;
@@ -110,7 +110,7 @@ impl BarWidget for Time {
TextFormat::simple(font_id, ctx.style().visuals.text_color()), TextFormat::simple(font_id, ctx.style().visuals.text_color()),
); );
config.grouping.apply_on_widget(true, config, ui, |ui| { config.apply_on_widget(true, ui, |ui| {
if ui if ui
.add( .add(
Label::new(layout_job) Label::new(layout_job)

View File

@@ -1,11 +1,9 @@
use crate::bar::Alignment;
use crate::battery::Battery; use crate::battery::Battery;
use crate::battery::BatteryConfig; use crate::battery::BatteryConfig;
use crate::cpu::Cpu; use crate::cpu::Cpu;
use crate::cpu::CpuConfig; use crate::cpu::CpuConfig;
use crate::date::Date; use crate::date::Date;
use crate::date::DateConfig; use crate::date::DateConfig;
use crate::group::Grouping;
use crate::komorebi::Komorebi; use crate::komorebi::Komorebi;
use crate::komorebi::KomorebiConfig; use crate::komorebi::KomorebiConfig;
use crate::media::Media; use crate::media::Media;
@@ -14,6 +12,7 @@ use crate::memory::Memory;
use crate::memory::MemoryConfig; use crate::memory::MemoryConfig;
use crate::network::Network; use crate::network::Network;
use crate::network::NetworkConfig; use crate::network::NetworkConfig;
use crate::render::RenderConfig;
use crate::storage::Storage; use crate::storage::Storage;
use crate::storage::StorageConfig; use crate::storage::StorageConfig;
use crate::time::Time; use crate::time::Time;
@@ -28,16 +27,6 @@ pub trait BarWidget {
fn render(&mut self, ctx: &Context, ui: &mut Ui, config: RenderConfig); fn render(&mut self, ctx: &Context, ui: &mut Ui, config: RenderConfig);
} }
#[derive(Copy, Clone)]
pub struct RenderConfig {
/// Spacing between widgets
pub spacing: f32,
/// Sets how widgets are grouped
pub grouping: Grouping,
/// Alignment of the widgets
pub alignment: Option<Alignment>,
}
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
pub enum WidgetConfig { pub enum WidgetConfig {
Battery(BatteryConfig), Battery(BatteryConfig),