1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-07-03 19:51:03 +02:00

Major module refactor (#19)

* refactor: major module restructuring

Modules now implement a "controller", which allows for separation of logic from UI code and enforces a tighter structure around how modules should be written. The introduction of this change required major refactoring or even rewriting of all modules.

This also better integrates the popup into modules, making it easier for data to be passed around without fetching the same thing twice

The refactor also improves some client code, switching from `ksway` to the much more stable `swayipc-async`. Partial multi-monitor for the tray module has been added.

BREAKING CHANGE: The `mpd` module config has changed, moving the icons to their own object.
This commit is contained in:
Jake Stanger 2022-09-25 22:49:00 +01:00 committed by GitHub
parent daafa0943e
commit 720ba7bfb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 2381 additions and 1846 deletions

View file

@ -1,12 +1,16 @@
use std::collections::HashMap;
use crate::config::BarPosition;
use crate::modules::ModuleInfo;
use gtk::gdk::Monitor;
use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, Button, Orientation};
use gtk::{ApplicationWindow, Button};
use tracing::debug;
#[derive(Debug, Clone)]
pub struct Popup {
pub window: ApplicationWindow,
pub container: gtk::Box,
pub cache: HashMap<usize, gtk::Box>,
monitor: Monitor,
}
@ -14,14 +18,11 @@ impl Popup {
/// Creates a new popup window.
/// This includes setting up gtk-layer-shell
/// and an empty `gtk::Box` container.
pub fn new(
name: &str,
app: &Application,
monitor: &Monitor,
orientation: Orientation,
bar_position: &BarPosition,
) -> Self {
let win = ApplicationWindow::builder().application(app).build();
pub fn new(module_info: &ModuleInfo) -> Self {
let pos = module_info.bar_position;
let win = ApplicationWindow::builder()
.application(module_info.app)
.build();
gtk_layer_shell::init_for_window(&win);
gtk_layer_shell::set_layer(&win, gtk_layer_shell::Layer::Overlay);
@ -29,48 +30,25 @@ impl Popup {
gtk_layer_shell::set_margin(
&win,
gtk_layer_shell::Edge::Top,
if bar_position == &BarPosition::Top {
5
} else {
0
},
if pos == &BarPosition::Top { 5 } else { 0 },
);
gtk_layer_shell::set_margin(
&win,
gtk_layer_shell::Edge::Bottom,
if bar_position == &BarPosition::Bottom {
5
} else {
0
},
if pos == &BarPosition::Bottom { 5 } else { 0 },
);
gtk_layer_shell::set_margin(&win, gtk_layer_shell::Edge::Left, 0);
gtk_layer_shell::set_margin(&win, gtk_layer_shell::Edge::Right, 0);
gtk_layer_shell::set_anchor(
&win,
gtk_layer_shell::Edge::Top,
bar_position == &BarPosition::Top,
);
gtk_layer_shell::set_anchor(&win, gtk_layer_shell::Edge::Top, pos == &BarPosition::Top);
gtk_layer_shell::set_anchor(
&win,
gtk_layer_shell::Edge::Bottom,
bar_position == &BarPosition::Bottom,
pos == &BarPosition::Bottom,
);
gtk_layer_shell::set_anchor(&win, gtk_layer_shell::Edge::Left, true);
gtk_layer_shell::set_anchor(&win, gtk_layer_shell::Edge::Right, false);
let content = gtk::Box::builder()
.orientation(orientation)
.spacing(0)
.hexpand(false)
.name(name)
.build();
content.style_context().add_class("popup");
win.add(&content);
win.connect_leave_notify_event(|win, ev| {
const THRESHOLD: f64 = 3.0;
@ -88,15 +66,36 @@ impl Popup {
Self {
window: win,
container: content,
monitor: monitor.clone(),
cache: HashMap::new(),
monitor: module_info.monitor.clone(),
}
}
pub fn register_content(&mut self, key: usize, content: gtk::Box) {
debug!("Registered popup content for #{}", key);
self.cache.insert(key, content);
}
pub fn show_content(&self, key: usize) {
self.clear_window();
if let Some(content) = self.cache.get(&key) {
content.style_context().add_class("popup");
self.window.add(content);
}
}
fn clear_window(&self) {
let children = self.window.children();
for child in children {
self.window.remove(&child);
}
}
/// Shows the popover
pub fn show(&self, button: &Button) {
pub fn show(&self, button_x: i32, button_width: i32) {
self.window.show_all();
self.set_pos(button);
self.set_pos(button_x, button_width);
}
/// Hides the popover
@ -104,18 +103,17 @@ impl Popup {
self.window.hide();
}
/// Checks if the popup is currently visible
pub fn is_visible(&self) -> bool {
self.window.is_visible()
}
/// Sets the popover's X position relative to the left border of the screen
fn set_pos(&self, button: &Button) {
let widget_width = button.allocation().width();
fn set_pos(&self, button_x: i32, button_width: i32) {
let screen_width = self.monitor.workarea().width();
let popup_width = self.window.allocated_width();
let top_level = button.toplevel().expect("Failed to get top-level widget");
let (widget_x, _) = button
.translate_coordinates(&top_level, 0, 0)
.unwrap_or((0, 0));
let widget_center = f64::from(widget_x) + f64::from(widget_width) / 2.0;
let widget_center = f64::from(button_x) + f64::from(button_width) / 2.0;
let mut offset = (widget_center - (f64::from(popup_width) / 2.0)).round();
@ -127,4 +125,17 @@ impl Popup {
gtk_layer_shell::set_margin(&self.window, gtk_layer_shell::Edge::Left, offset as i32);
}
/// Gets the absolute X position of the button
/// and its width.
pub fn button_pos(button: &Button) -> (i32, i32) {
let button_width = button.allocation().width();
let top_level = button.toplevel().expect("Failed to get top-level widget");
let (button_x, _) = button
.translate_coordinates(&top_level, 0, 0)
.unwrap_or((0, 0));
(button_x, button_width)
}
}