Skip to content

Commit

Permalink
fix(bar): simplify komorebi-bar config
Browse files Browse the repository at this point in the history
This interactively rebased commit is comprised of the subsequent
individual commits listed further below.

At a high level:

- work_area_offset is now automatically calculated by default
- monitor can now take an index in addition to the previous object
- position can largely be replaced by margin and padding for bars that
  are positioned at the top of the screen
- frame can now largely be replaced by margin and padding for bars that
  are positioned at the top of the screen
- height is now a more intuitive configuration option for setting the
  height of the bar

Detailed explainations and examples are included in the body of PR #1224
on GitHub: #1224

fix(bar): add simplified config for bar

This commit creates a few new config options for the bar that should
make it a lot simpler for new users to configure the bar.

- Remove the need for `position`: if a position is given the bar will
  still use it with priority over the new config. Instead of position
  you can now use the following:
  - `height`: defines the height of the bar (50 by default)
  - `horizontal_margin`: defines the left and right offset of the bar, it
  is the same as setting a `position.start.x` and then remove the same
  amount on `position.end.x`.
  - `vertical_margin`: defines the top and bottom offset of the bar, it is
  the same as setting a `position.start.y` and then add a correct amount
  on the `work_area_offset`.

- Remove the need for `frame`: some new configs were added that take
  priority over the old `frame`. These are:
  - `horizontal_padding`: defines the left and right padding of the bar.
    Similar to `frame.inner_margin.x`.
  - `vertical_padding`: defines the top and bottom padding of the bar.
    Similar to `frame.inner_margin.y`.

- Remove the need for `work_area_offset`: if a `work_area_offset` is
  given then it will take priority, if not, then it will calculate the
  necessary `work_area_offset` using the bar height, position and
  horizontal and vertical margins.

feat(bar): set margin/padding as one or two values

This commit changes the `horizontal_margin`, `vertical_margin`,
`horizontal_padding` and `vertical_padding` to now take a
`SpacingAxisConfig` which can take a single value or two values.

For example, you can set the vertical margin of the bar to add some
spacing above and below like this:

```json
"vertical_margin": 10
```

Which will add a spacing of 10 above and below the bar. Or you can set
it like this:

```json
"vertical_margin": [10, 0]
```

Which will add a spacing of 10 above the bar but no spacing below. You
can even set something like this:

```json
"vertical_margin": [0, -10]
```

To make no spacing above and a negative spacing below to make it so the
tiled windows show right next to the bar. This will basically be
removing the workspace and container padding between the tiled windows
and the bar.

fix(bar): use a right_to_left layout on right side

This commit changes the right area with the right widgets to have a
different layout that is still right_to_left as previously but behaves
much better in regards to its height.

fix(bar): use default bar height

When there is no `work_area_offset` and no `height` on the config it was
using the `BAR_HEIGHT` as default, however the automatica
work_area_offset calculation wasn't being done properly. Now it is!

feat(bar): monitor can be `MonitorConfig` or index

This commit allows the `"monitor":` config to take a `MonitorConfig`
object like it used to or simply a number (index).

docs(schema): update all json schemas

fix(bar): update example bar config

fix(bar): correct work_area_offset on secondary monitors

feat(bar): add multiple options for margin/padding

This commit removes the previous `horizontal_margin`, `vertical_margin`,
`horizontal_padding` and `vertical_padding`, replacing them all with
just `margin` and `padding`.

These new options can be set either with a single value that sets that
spacing on all sides, with an object specifying each individual side or
with an object specifying some "vertical" and/or "horizontal" spacing
which can have a single value, resulting on a symmetric spacing for that
specific axis or two values to define each side of the axis individually.
  • Loading branch information
alex-ds13 authored and LGUG2Z committed Jan 23, 2025
1 parent d09d16d commit 3e1fc61
Show file tree
Hide file tree
Showing 6 changed files with 577 additions and 106 deletions.
10 changes: 1 addition & 9 deletions docs/komorebi.bar.example.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.33/schema.bar.json",
"monitor": {
"index": 0,
"work_area_offset": {
"left": 0,
"top": 40,
"right": 0,
"bottom": 40
}
},
"monitor": 0,
"font_family": "JetBrains Mono",
"theme": {
"palette": "Base16",
Expand Down
208 changes: 169 additions & 39 deletions komorebi-bar/src/bar.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::config::get_individual_spacing;
use crate::config::KomobarConfig;
use crate::config::KomobarTheme;
use crate::config::MonitorConfigOrIndex;
use crate::config::Position;
use crate::config::PositionConfig;
use crate::komorebi::Komorebi;
Expand All @@ -12,6 +14,7 @@ use crate::render::RenderExt;
use crate::widget::BarWidget;
use crate::widget::WidgetConfig;
use crate::BAR_HEIGHT;
use crate::DEFAULT_PADDING;
use crate::MAX_LABEL_WIDTH;
use crate::MONITOR_LEFT;
use crate::MONITOR_RIGHT;
Expand All @@ -34,6 +37,7 @@ use eframe::egui::Margin;
use eframe::egui::Rgba;
use eframe::egui::Style;
use eframe::egui::TextStyle;
use eframe::egui::Vec2;
use eframe::egui::Visuals;
use font_loader::system_fonts;
use font_loader::system_fonts::FontPropertyBuilder;
Expand All @@ -52,6 +56,7 @@ use std::sync::Arc;

pub struct Komobar {
pub hwnd: Option<isize>,
pub monitor_index: usize,
pub config: Arc<KomobarConfig>,
pub render_config: Rc<RefCell<RenderConfig>>,
pub komorebi_notification_state: Option<Rc<RefCell<KomorebiNotificationState>>>,
Expand All @@ -64,6 +69,7 @@ pub struct Komobar {
pub bg_color_with_alpha: Rc<RefCell<Color32>>,
pub scale_factor: f32,
pub size_rect: komorebi_client::Rect,
pub work_area_offset: komorebi_client::Rect,
applied_theme_on_first_frame: bool,
}

Expand Down Expand Up @@ -199,7 +205,7 @@ impl Komobar {

// Update the `size_rect` so that the bar position can be changed on the EGUI update
// function
self.update_size_rect(config.position.clone());
self.update_size_rect(config);

self.try_apply_theme(config, ctx);

Expand Down Expand Up @@ -295,23 +301,64 @@ impl Komobar {
self.center_widgets = center_widgets;
self.right_widgets = right_widgets;

if let (Some(prev_rect), Some(new_rect)) = (
&self.config.monitor.work_area_offset,
&config.monitor.work_area_offset,
) {
let (monitor_index, config_work_area_offset) = match &config.monitor {
MonitorConfigOrIndex::MonitorConfig(monitor_config) => {
(monitor_config.index, monitor_config.work_area_offset)
}
MonitorConfigOrIndex::Index(idx) => (*idx, None),
};
self.monitor_index = monitor_index;

if let (prev_rect, Some(new_rect)) = (&self.work_area_offset, &config_work_area_offset) {
if new_rect != prev_rect {
self.work_area_offset = *new_rect;
if let Err(error) = komorebi_client::send_message(
&SocketMessage::MonitorWorkAreaOffset(self.monitor_index, *new_rect),
) {
tracing::error!(
"error applying work area offset to monitor '{}': {}",
self.monitor_index,
error,
);
} else {
tracing::info!(
"work area offset applied to monitor: {}",
self.monitor_index
);
}
}
} else if let Some(height) = config.height.or(Some(BAR_HEIGHT)) {
// We only add the `bottom_margin` to the work_area_offset since the top margin is
// already considered on the `size_rect.top`
let bottom_margin = config
.margin
.as_ref()
.map_or(0, |v| v.to_individual(0.0).bottom as i32);
let new_rect = komorebi_client::Rect {
left: 0,
top: (height as i32)
+ (self.size_rect.top - MONITOR_TOP.load(Ordering::SeqCst))
+ bottom_margin,
right: 0,
bottom: (height as i32)
+ (self.size_rect.top - MONITOR_TOP.load(Ordering::SeqCst))
+ bottom_margin,
};

if new_rect != self.work_area_offset {
self.work_area_offset = new_rect;
if let Err(error) = komorebi_client::send_message(
&SocketMessage::MonitorWorkAreaOffset(config.monitor.index, *new_rect),
&SocketMessage::MonitorWorkAreaOffset(self.monitor_index, new_rect),
) {
tracing::error!(
"error applying work area offset to monitor '{}': {}",
config.monitor.index,
self.monitor_index,
error,
);
} else {
tracing::info!(
"work area offset applied to monitor: {}",
config.monitor.index
self.monitor_index
);
}
}
Expand All @@ -325,8 +372,8 @@ impl Komobar {
}

/// Updates the `size_rect` field. Returns a bool indicating if the field was changed or not
fn update_size_rect(&mut self, position: Option<PositionConfig>) {
let position = position.unwrap_or(PositionConfig {
fn update_size_rect(&mut self, config: &KomobarConfig) {
let position = config.position.clone().unwrap_or(PositionConfig {
start: Some(Position {
x: MONITOR_LEFT.load(Ordering::SeqCst) as f32,
y: MONITOR_TOP.load(Ordering::SeqCst) as f32,
Expand All @@ -337,16 +384,26 @@ impl Komobar {
}),
});

let start = position.start.unwrap_or(Position {
let mut start = position.start.unwrap_or(Position {
x: MONITOR_LEFT.load(Ordering::SeqCst) as f32,
y: MONITOR_TOP.load(Ordering::SeqCst) as f32,
});

let end = position.end.unwrap_or(Position {
let mut end = position.end.unwrap_or(Position {
x: MONITOR_RIGHT.load(Ordering::SeqCst) as f32,
y: BAR_HEIGHT,
});

if let Some(height) = config.height {
end.y = height;
}

let margin = get_individual_spacing(0.0, &config.margin);

start.y += margin.top;
start.x += margin.left;
end.x -= margin.left + margin.right;

if end.y == 0.0 {
tracing::warn!("position.end.y is set to 0.0 which will make your bar invisible on a config reload - this is usually set to 50.0 by default")
}
Expand Down Expand Up @@ -453,6 +510,7 @@ impl Komobar {
) -> Self {
let mut komobar = Self {
hwnd: process_hwnd(),
monitor_index: 0,
config: config.clone(),
render_config: Rc::new(RefCell::new(RenderConfig::new())),
komorebi_notification_state: None,
Expand All @@ -465,6 +523,7 @@ impl Komobar {
bg_color_with_alpha: Rc::new(RefCell::new(Style::default().visuals.panel_fill)),
scale_factor: cc.egui_ctx.native_pixels_per_point().unwrap_or(1.0),
size_rect: komorebi_client::Rect::default(),
work_area_offset: komorebi_client::Rect::default(),
applied_theme_on_first_frame: false,
};

Expand Down Expand Up @@ -578,7 +637,7 @@ impl eframe::App for Komobar {
.borrow_mut()
.handle_notification(
ctx,
self.config.monitor.index,
self.monitor_index,
self.rx_gui.clone(),
self.bg_color.clone(),
self.bg_color_with_alpha.clone(),
Expand Down Expand Up @@ -619,40 +678,78 @@ impl eframe::App for Komobar {
}
}

let frame = if let Some(frame) = &self.config.frame {
Frame::none()
.inner_margin(Margin::symmetric(
frame.inner_margin.x,
frame.inner_margin.y,
))
.fill(*self.bg_color_with_alpha.borrow())
} else {
Frame::none().fill(*self.bg_color_with_alpha.borrow())
let frame = match &self.config.padding {
None => {
if let Some(frame) = &self.config.frame {
Frame::none()
.inner_margin(Margin::symmetric(
frame.inner_margin.x,
frame.inner_margin.y,
))
.fill(*self.bg_color_with_alpha.borrow())
} else {
Frame::none()
.inner_margin(Margin::same(0.0))
.fill(*self.bg_color_with_alpha.borrow())
}
}
Some(padding) => {
let padding = padding.to_individual(DEFAULT_PADDING);
Frame::none()
.inner_margin(Margin {
top: padding.top,
bottom: padding.bottom,
left: padding.left,
right: padding.right,
})
.fill(*self.bg_color_with_alpha.borrow())
}
};

let mut render_config = self.render_config.borrow_mut();

let frame = render_config.change_frame_on_bar(frame, &ctx.style());

CentralPanel::default().frame(frame).show(ctx, |_| {
CentralPanel::default().frame(frame).show(ctx, |ui| {
// Apply grouping logic for the bar as a whole
let area_frame = if let Some(frame) = &self.config.frame {
Frame::none().inner_margin(Margin::symmetric(0.0, frame.inner_margin.y))
Frame::none()
.inner_margin(Margin::symmetric(0.0, frame.inner_margin.y))
.outer_margin(Margin::same(0.0))
} else {
Frame::none()
.inner_margin(Margin::same(0.0))
.outer_margin(Margin::same(0.0))
};

let available_height = ui.max_rect().max.y;
ctx.style_mut(|style| {
style.spacing.interact_size.y = available_height;
});

if !self.left_widgets.is_empty() {
// Left-aligned widgets layout
Area::new(Id::new("left_panel"))
.anchor(Align2::LEFT_CENTER, [0.0, 0.0]) // Align in the left center of the window
.show(ctx, |ui| {
let mut left_area_frame = area_frame;
if let Some(frame) = &self.config.frame {
if let Some(padding) = self
.config
.padding
.as_ref()
.map(|s| s.to_individual(DEFAULT_PADDING))
{
left_area_frame.inner_margin.left = padding.left;
left_area_frame.inner_margin.top = padding.top;
left_area_frame.inner_margin.bottom = padding.bottom;
} else if let Some(frame) = &self.config.frame {
left_area_frame.inner_margin.left = frame.inner_margin.x;
left_area_frame.inner_margin.top = frame.inner_margin.y;
left_area_frame.inner_margin.bottom = frame.inner_margin.y;
}

left_area_frame.show(ui, |ui| {
ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
ui.horizontal(|ui| {
let mut render_conf = render_config.clone();
render_conf.alignment = Some(Alignment::Left);

Expand All @@ -672,20 +769,40 @@ impl eframe::App for Komobar {
.anchor(Align2::RIGHT_CENTER, [0.0, 0.0]) // Align in the right center of the window
.show(ctx, |ui| {
let mut right_area_frame = area_frame;
if let Some(frame) = &self.config.frame {
if let Some(padding) = self
.config
.padding
.as_ref()
.map(|s| s.to_individual(DEFAULT_PADDING))
{
right_area_frame.inner_margin.right = padding.right;
right_area_frame.inner_margin.top = padding.top;
right_area_frame.inner_margin.bottom = padding.bottom;
} else if let Some(frame) = &self.config.frame {
right_area_frame.inner_margin.right = frame.inner_margin.x;
right_area_frame.inner_margin.top = frame.inner_margin.y;
right_area_frame.inner_margin.bottom = frame.inner_margin.y;
}
right_area_frame.show(ui, |ui| {
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
let mut render_conf = render_config.clone();
render_conf.alignment = Some(Alignment::Right);

render_config.apply_on_alignment(ui, |ui| {
for w in &mut self.right_widgets {
w.render(ctx, ui, &mut render_conf);
}
});
});
right_area_frame.show(ui, |ui| {
let initial_size = Vec2 {
x: ui.available_size_before_wrap().x,
y: ui.spacing().interact_size.y,
};
ui.allocate_ui_with_layout(
initial_size,
Layout::right_to_left(Align::Center),
|ui| {
let mut render_conf = render_config.clone();
render_conf.alignment = Some(Alignment::Right);

render_config.apply_on_alignment(ui, |ui| {
for w in &mut self.right_widgets {
w.render(ctx, ui, &mut render_conf);
}
});
},
);
});
});
}
Expand All @@ -695,9 +812,22 @@ impl eframe::App for Komobar {
Area::new(Id::new("center_panel"))
.anchor(Align2::CENTER_CENTER, [0.0, 0.0]) // Align in the center of the window
.show(ctx, |ui| {
let center_area_frame = area_frame;
let mut center_area_frame = area_frame;
if let Some(padding) = self
.config
.padding
.as_ref()
.map(|s| s.to_individual(DEFAULT_PADDING))
{
center_area_frame.inner_margin.top = padding.top;
center_area_frame.inner_margin.bottom = padding.bottom;
} else if let Some(frame) = &self.config.frame {
center_area_frame.inner_margin.top = frame.inner_margin.y;
center_area_frame.inner_margin.bottom = frame.inner_margin.y;
}

center_area_frame.show(ui, |ui| {
ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
ui.horizontal(|ui| {
let mut render_conf = render_config.clone();
render_conf.alignment = Some(Alignment::Center);

Expand Down
Loading

0 comments on commit 3e1fc61

Please sign in to comment.