1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-08-17 23:01:04 +02:00

feat: ability to add custom modules instead native modules

Resolves #131
This commit is contained in:
Jake Stanger 2024-03-14 22:35:33 +00:00
parent 42ae915645
commit 994f4a4a12
No known key found for this signature in database
GPG key ID: C51FC8F9CB0BEA61
21 changed files with 497 additions and 252 deletions

View file

@ -9,14 +9,15 @@ use self::image::ImageWidget;
use self::label::LabelWidget;
use self::r#box::BoxWidget;
use self::slider::SliderWidget;
use crate::config::CommonConfig;
use crate::config::{CommonConfig, ModuleConfig};
use crate::modules::custom::button::ButtonWidget;
use crate::modules::custom::progress::ProgressWidget;
use crate::modules::{
wrap_widget, Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
wrap_widget, AnyModuleFactory, BarModuleFactory, Module, ModuleInfo, ModuleParts, ModulePopup,
ModuleUpdateEvent, PopupButton, PopupModuleFactory, WidgetContext,
};
use crate::script::Script;
use crate::{send_async, spawn};
use crate::{module_impl, send_async, spawn};
use color_eyre::{Report, Result};
use gtk::prelude::*;
use gtk::{Button, IconTheme, Orientation};
@ -40,11 +41,18 @@ pub struct CustomModule {
#[derive(Debug, Deserialize, Clone)]
pub struct WidgetConfig {
#[serde(flatten)]
widget: Widget,
widget: WidgetOrModule,
#[serde(flatten)]
common: CommonConfig,
}
#[derive(Debug, Deserialize, Clone)]
#[serde(untagged)]
pub enum WidgetOrModule {
Widget(Widget),
Module(ModuleConfig),
}
#[derive(Debug, Deserialize, Clone)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Widget {
@ -58,10 +66,12 @@ pub enum Widget {
#[derive(Clone)]
struct CustomWidgetContext<'a> {
info: &'a ModuleInfo<'a>,
tx: &'a mpsc::Sender<ExecEvent>,
bar_orientation: Orientation,
icon_theme: &'a IconTheme,
popup_buttons: Rc<RefCell<Vec<Button>>>,
module_factory: AnyModuleFactory,
}
trait CustomWidget {
@ -114,6 +124,19 @@ fn try_get_orientation(orientation: &str) -> Result<Orientation> {
}
}
impl WidgetOrModule {
fn add_to(self, parent: &gtk::Box, context: &CustomWidgetContext, common: CommonConfig) {
match self {
WidgetOrModule::Widget(widget) => widget.add_to(parent, context, common),
WidgetOrModule::Module(config) => {
if let Err(err) = config.create(&context.module_factory, parent, context.info) {
error!("{err:?}");
}
}
}
}
}
impl Widget {
/// Creates this widget and adds it to the parent container
fn add_to(self, parent: &gtk::Box, context: &CustomWidgetContext, common: CommonConfig) {
@ -151,9 +174,7 @@ impl Module<gtk::Box> for CustomModule {
type SendMessage = ();
type ReceiveMessage = ExecEvent;
fn name() -> &'static str {
"custom"
}
module_impl!("custom");
fn spawn_controller(
&self,
@ -191,7 +212,7 @@ impl Module<gtk::Box> for CustomModule {
fn into_widget(
self,
context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
mut context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
info: &ModuleInfo,
) -> Result<ModuleParts<gtk::Box>> {
let orientation = info.bar_position.orientation();
@ -200,10 +221,13 @@ impl Module<gtk::Box> for CustomModule {
let popup_buttons = Rc::new(RefCell::new(Vec::new()));
let custom_context = CustomWidgetContext {
info,
tx: &context.controller_tx,
bar_orientation: orientation,
icon_theme: info.icon_theme,
popup_buttons: popup_buttons.clone(),
module_factory: BarModuleFactory::new(context.ironbar.clone(), context.popup.clone())
.into(),
};
self.bar.clone().into_iter().for_each(|widget| {
@ -212,8 +236,22 @@ impl Module<gtk::Box> for CustomModule {
.add_to(&container, &custom_context, widget.common);
});
for button in popup_buttons.borrow().iter() {
button.ensure_popup_id();
}
context.button_id = popup_buttons
.borrow()
.first()
.map_or(usize::MAX, |button| button.popup_id());
let popup = self
.into_popup(context.controller_tx.clone(), context.subscribe(), info)
.into_popup(
context.controller_tx.clone(),
context.subscribe(),
context,
info,
)
.into_popup_parts_owned(popup_buttons.take());
Ok(ModuleParts {
@ -226,6 +264,7 @@ impl Module<gtk::Box> for CustomModule {
self,
tx: mpsc::Sender<Self::ReceiveMessage>,
_rx: broadcast::Receiver<Self::SendMessage>,
context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
info: &ModuleInfo,
) -> Option<gtk::Box>
where
@ -235,10 +274,17 @@ impl Module<gtk::Box> for CustomModule {
if let Some(popup) = self.popup {
let custom_context = CustomWidgetContext {
info,
tx: &tx,
bar_orientation: info.bar_position.orientation(),
icon_theme: info.icon_theme,
popup_buttons: Rc::new(RefCell::new(vec![])),
module_factory: PopupModuleFactory::new(
context.ironbar,
context.popup,
context.button_id,
)
.into(),
};
for widget in popup {