mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-03 19:51:03 +02:00
feat(ipc): commands for opening/closing popups
Also includes some refactoring around related GTK helper code
This commit is contained in:
parent
c582bc3390
commit
b7ee794bfc
30 changed files with 747 additions and 345 deletions
|
@ -27,7 +27,7 @@ impl CustomWidget for BoxWidget {
|
|||
|
||||
if let Some(widgets) = self.widgets {
|
||||
for widget in widgets {
|
||||
widget.widget.add_to(&container, context, widget.common);
|
||||
widget.widget.add_to(&container, &context, widget.common);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use super::{CustomWidget, CustomWidgetContext, ExecEvent};
|
||||
use crate::dynamic_value::dynamic_string;
|
||||
use crate::popup::Popup;
|
||||
use crate::{build, try_send};
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Button, Label};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::dynamic_value::dynamic_string;
|
||||
use crate::modules::PopupButton;
|
||||
use crate::{build, try_send};
|
||||
|
||||
use super::{CustomWidget, CustomWidgetContext, ExecEvent};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct ButtonWidget {
|
||||
name: Option<String>,
|
||||
|
@ -19,6 +21,7 @@ impl CustomWidget for ButtonWidget {
|
|||
|
||||
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
||||
let button = build!(self, Self::Widget);
|
||||
context.popup_buttons.borrow_mut().push(button.clone());
|
||||
|
||||
if let Some(text) = self.label {
|
||||
let label = Label::new(None);
|
||||
|
@ -32,7 +35,6 @@ impl CustomWidget for ButtonWidget {
|
|||
}
|
||||
|
||||
if let Some(exec) = self.on_click {
|
||||
let bar_orientation = context.bar_orientation;
|
||||
let tx = context.tx.clone();
|
||||
|
||||
button.connect_clicked(move |button| {
|
||||
|
@ -41,7 +43,7 @@ impl CustomWidget for ButtonWidget {
|
|||
ExecEvent {
|
||||
cmd: exec.clone(),
|
||||
args: None,
|
||||
geometry: Popup::widget_geometry(button, bar_orientation),
|
||||
id: button.popup_id(),
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use super::{CustomWidget, CustomWidgetContext};
|
||||
use crate::build;
|
||||
use crate::dynamic_value::dynamic_string;
|
||||
use crate::image::ImageProvider;
|
||||
use gtk::prelude::*;
|
||||
use gtk::Image;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::build;
|
||||
use crate::dynamic_value::dynamic_string;
|
||||
use crate::image::ImageProvider;
|
||||
|
||||
use super::{CustomWidget, CustomWidgetContext};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct ImageWidget {
|
||||
name: Option<String>,
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use super::{CustomWidget, CustomWidgetContext};
|
||||
use crate::build;
|
||||
use crate::dynamic_value::dynamic_string;
|
||||
use gtk::prelude::*;
|
||||
use gtk::Label;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::build;
|
||||
use crate::dynamic_value::dynamic_string;
|
||||
|
||||
use super::{CustomWidget, CustomWidgetContext};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct LabelWidget {
|
||||
name: Option<String>,
|
||||
|
|
|
@ -13,15 +13,16 @@ use crate::config::CommonConfig;
|
|||
use crate::modules::custom::button::ButtonWidget;
|
||||
use crate::modules::custom::progress::ProgressWidget;
|
||||
use crate::modules::{
|
||||
wrap_widget, Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext,
|
||||
wrap_widget, Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||
};
|
||||
use crate::popup::WidgetGeometry;
|
||||
use crate::script::Script;
|
||||
use crate::send_async;
|
||||
use color_eyre::{Report, Result};
|
||||
use gtk::prelude::*;
|
||||
use gtk::{IconTheme, Orientation};
|
||||
use gtk::{Button, IconTheme, Orientation};
|
||||
use serde::Deserialize;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tracing::{debug, error};
|
||||
|
@ -56,11 +57,12 @@ pub enum Widget {
|
|||
Progress(ProgressWidget),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone)]
|
||||
struct CustomWidgetContext<'a> {
|
||||
tx: &'a Sender<ExecEvent>,
|
||||
bar_orientation: Orientation,
|
||||
icon_theme: &'a IconTheme,
|
||||
popup_buttons: Rc<RefCell<Vec<Button>>>,
|
||||
}
|
||||
|
||||
trait CustomWidget {
|
||||
|
@ -115,11 +117,11 @@ fn try_get_orientation(orientation: &str) -> Result<Orientation> {
|
|||
|
||||
impl Widget {
|
||||
/// Creates this widget and adds it to the parent container
|
||||
fn add_to(self, parent: >k::Box, context: CustomWidgetContext, common: CommonConfig) {
|
||||
fn add_to(self, parent: >k::Box, context: &CustomWidgetContext, common: CommonConfig) {
|
||||
macro_rules! create {
|
||||
($widget:expr) => {
|
||||
wrap_widget(
|
||||
&$widget.into_widget(context),
|
||||
&$widget.into_widget(context.clone()),
|
||||
common,
|
||||
context.bar_orientation,
|
||||
)
|
||||
|
@ -143,7 +145,7 @@ impl Widget {
|
|||
pub struct ExecEvent {
|
||||
cmd: String,
|
||||
args: Option<Vec<String>>,
|
||||
geometry: WidgetGeometry,
|
||||
id: usize,
|
||||
}
|
||||
|
||||
impl Module<gtk::Box> for CustomModule {
|
||||
|
@ -173,9 +175,9 @@ impl Module<gtk::Box> for CustomModule {
|
|||
error!("{err:?}");
|
||||
}
|
||||
} else if event.cmd == "popup:toggle" {
|
||||
send_async!(tx, ModuleUpdateEvent::TogglePopup(event.geometry));
|
||||
send_async!(tx, ModuleUpdateEvent::TogglePopup(event.id));
|
||||
} else if event.cmd == "popup:open" {
|
||||
send_async!(tx, ModuleUpdateEvent::OpenPopup(event.geometry));
|
||||
send_async!(tx, ModuleUpdateEvent::OpenPopup(event.id));
|
||||
} else if event.cmd == "popup:close" {
|
||||
send_async!(tx, ModuleUpdateEvent::ClosePopup);
|
||||
} else {
|
||||
|
@ -191,25 +193,30 @@ impl Module<gtk::Box> for CustomModule {
|
|||
self,
|
||||
context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
|
||||
info: &ModuleInfo,
|
||||
) -> Result<ModuleWidget<gtk::Box>> {
|
||||
) -> Result<ModuleParts<gtk::Box>> {
|
||||
let orientation = info.bar_position.get_orientation();
|
||||
let container = gtk::Box::builder().orientation(orientation).build();
|
||||
|
||||
let popup_buttons = Rc::new(RefCell::new(Vec::new()));
|
||||
|
||||
let custom_context = CustomWidgetContext {
|
||||
tx: &context.controller_tx,
|
||||
bar_orientation: orientation,
|
||||
icon_theme: info.icon_theme,
|
||||
popup_buttons: popup_buttons.clone(),
|
||||
};
|
||||
|
||||
self.bar.clone().into_iter().for_each(|widget| {
|
||||
widget
|
||||
.widget
|
||||
.add_to(&container, custom_context, widget.common);
|
||||
.add_to(&container, &custom_context, widget.common);
|
||||
});
|
||||
|
||||
let popup = self.into_popup(context.controller_tx, context.popup_rx, info);
|
||||
let popup = self
|
||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
||||
.into_popup_parts_owned(popup_buttons.take());
|
||||
|
||||
Ok(ModuleWidget {
|
||||
Ok(ModuleParts {
|
||||
widget: container,
|
||||
popup,
|
||||
})
|
||||
|
@ -231,12 +238,13 @@ impl Module<gtk::Box> for CustomModule {
|
|||
tx: &tx,
|
||||
bar_orientation: info.bar_position.get_orientation(),
|
||||
icon_theme: info.icon_theme,
|
||||
popup_buttons: Rc::new(RefCell::new(vec![])),
|
||||
};
|
||||
|
||||
for widget in popup {
|
||||
widget
|
||||
.widget
|
||||
.add_to(&container, custom_context, widget.common);
|
||||
.add_to(&container, &custom_context, widget.common);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext};
|
||||
use crate::dynamic_value::dynamic_string;
|
||||
use crate::modules::custom::set_length;
|
||||
use crate::script::{OutputStream, Script, ScriptInput};
|
||||
use crate::{build, send};
|
||||
use gtk::prelude::*;
|
||||
use gtk::ProgressBar;
|
||||
use serde::Deserialize;
|
||||
use tokio::spawn;
|
||||
use tracing::error;
|
||||
|
||||
use crate::dynamic_value::dynamic_string;
|
||||
use crate::modules::custom::set_length;
|
||||
use crate::script::{OutputStream, Script, ScriptInput};
|
||||
use crate::{build, send};
|
||||
|
||||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct ProgressWidget {
|
||||
name: Option<String>,
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext, ExecEvent};
|
||||
use crate::modules::custom::set_length;
|
||||
use crate::popup::Popup;
|
||||
use crate::script::{OutputStream, Script, ScriptInput};
|
||||
use crate::{build, send, try_send};
|
||||
use std::cell::Cell;
|
||||
use std::ops::Neg;
|
||||
|
||||
use gtk::prelude::*;
|
||||
use gtk::Scale;
|
||||
use serde::Deserialize;
|
||||
use std::cell::Cell;
|
||||
use std::ops::Neg;
|
||||
use tokio::spawn;
|
||||
use tracing::error;
|
||||
|
||||
use crate::modules::custom::set_length;
|
||||
use crate::script::{OutputStream, Script, ScriptInput};
|
||||
use crate::{build, send, try_send};
|
||||
|
||||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext, ExecEvent};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct SliderWidget {
|
||||
name: Option<String>,
|
||||
|
@ -78,7 +80,7 @@ impl CustomWidget for SliderWidget {
|
|||
Inhibit(false)
|
||||
});
|
||||
|
||||
scale.connect_change_value(move |scale, _, val| {
|
||||
scale.connect_change_value(move |_, _, val| {
|
||||
// GTK will send values outside min/max range
|
||||
let val = val.clamp(min, max);
|
||||
|
||||
|
@ -88,7 +90,7 @@ impl CustomWidget for SliderWidget {
|
|||
ExecEvent {
|
||||
cmd: on_change.clone(),
|
||||
args: Some(vec![val.to_string()]),
|
||||
geometry: Popup::widget_geometry(scale, context.bar_orientation),
|
||||
id: usize::MAX // ignored
|
||||
}
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue