mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-01 18:51:04 +02:00
refactor(custom): reduce a lot of repeated code
This commit is contained in:
parent
a9d1233909
commit
3613aef5c5
8 changed files with 85 additions and 97 deletions
|
@ -19,6 +19,15 @@ pub struct DynamicString;
|
||||||
impl DynamicString {
|
impl DynamicString {
|
||||||
/// Creates a new dynamic string, based off the input template.
|
/// Creates a new dynamic string, based off the input template.
|
||||||
/// Runs `f` with the compiled string each time one of the scripts updates.
|
/// Runs `f` with the compiled string each time one of the scripts updates.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rs
|
||||||
|
/// DynamicString::new(&text, move |string| {
|
||||||
|
/// label.set_markup(&string);
|
||||||
|
/// Continue(true)
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
pub fn new<F>(input: &str, f: F) -> Self
|
pub fn new<F>(input: &str, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: FnMut(String) -> Continue + 'static,
|
F: FnMut(String) -> Continue + 'static,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext, Widget};
|
use super::{try_get_orientation, CustomWidget, CustomWidgetContext, Widget};
|
||||||
|
use crate::build;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Orientation;
|
use gtk::Orientation;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -15,21 +16,12 @@ impl CustomWidget for BoxWidget {
|
||||||
type Widget = gtk::Box;
|
type Widget = gtk::Box;
|
||||||
|
|
||||||
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
||||||
let mut builder = gtk::Box::builder();
|
let container = build!(self, Self::Widget);
|
||||||
|
|
||||||
if let Some(name) = self.name {
|
|
||||||
builder = builder.name(&name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(orientation) = self.orientation {
|
if let Some(orientation) = self.orientation {
|
||||||
builder = builder
|
container.set_orientation(
|
||||||
.orientation(try_get_orientation(&orientation).unwrap_or(Orientation::Horizontal));
|
try_get_orientation(&orientation).unwrap_or(Orientation::Horizontal),
|
||||||
}
|
)
|
||||||
|
|
||||||
let container = builder.build();
|
|
||||||
|
|
||||||
if let Some(class) = self.class {
|
|
||||||
container.style_context().add_class(&class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(widgets) = self.widgets {
|
if let Some(widgets) = self.widgets {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use super::{CustomWidget, CustomWidgetContext, ExecEvent};
|
use super::{CustomWidget, CustomWidgetContext, ExecEvent};
|
||||||
|
use crate::dynamic_string::DynamicString;
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
use crate::try_send;
|
use crate::{build, try_send};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Button, Label};
|
use gtk::{Button, Label};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -17,13 +18,7 @@ impl CustomWidget for ButtonWidget {
|
||||||
type Widget = Button;
|
type Widget = Button;
|
||||||
|
|
||||||
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
||||||
let mut builder = Button::builder();
|
let button = build!(self, Self::Widget);
|
||||||
|
|
||||||
if let Some(name) = self.name {
|
|
||||||
builder = builder.name(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
let button = builder.build();
|
|
||||||
|
|
||||||
if let Some(text) = self.label {
|
if let Some(text) = self.label {
|
||||||
let label = Label::new(None);
|
let label = Label::new(None);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::{CustomWidget, CustomWidgetContext};
|
use super::{CustomWidget, CustomWidgetContext};
|
||||||
|
use crate::build;
|
||||||
use crate::image::ImageProvider;
|
use crate::image::ImageProvider;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Image;
|
use gtk::Image;
|
||||||
|
@ -17,13 +18,7 @@ impl CustomWidget for ImageWidget {
|
||||||
type Widget = Image;
|
type Widget = Image;
|
||||||
|
|
||||||
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
||||||
let mut builder = Image::builder();
|
let gtk_image = build!(self, Self::Widget);
|
||||||
|
|
||||||
if let Some(name) = self.name {
|
|
||||||
builder = builder.name(&name);
|
|
||||||
}
|
|
||||||
|
|
||||||
let gtk_image = builder.build();
|
|
||||||
|
|
||||||
if let Some(src) = self.src {
|
if let Some(src) = self.src {
|
||||||
let size = self.size.unwrap_or(32);
|
let size = self.size.unwrap_or(32);
|
||||||
|
@ -34,10 +29,6 @@ impl CustomWidget for ImageWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(class) = self.class {
|
|
||||||
gtk_image.style_context().add_class(&class);
|
|
||||||
}
|
|
||||||
|
|
||||||
gtk_image
|
gtk_image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::{CustomWidget, CustomWidgetContext};
|
use super::{CustomWidget, CustomWidgetContext};
|
||||||
|
use crate::build;
|
||||||
use crate::dynamic_string::DynamicString;
|
use crate::dynamic_string::DynamicString;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Label;
|
use gtk::Label;
|
||||||
|
@ -8,31 +9,21 @@ use serde::Deserialize;
|
||||||
pub struct LabelWidget {
|
pub struct LabelWidget {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
class: Option<String>,
|
class: Option<String>,
|
||||||
label: Option<String>,
|
label: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomWidget for LabelWidget {
|
impl CustomWidget for LabelWidget {
|
||||||
type Widget = Label;
|
type Widget = Label;
|
||||||
|
|
||||||
fn into_widget(self, _context: CustomWidgetContext) -> Self::Widget {
|
fn into_widget(self, _context: CustomWidgetContext) -> Self::Widget {
|
||||||
let mut builder = Label::builder().use_markup(true);
|
let label = build!(self, Self::Widget);
|
||||||
|
|
||||||
if let Some(name) = self.name {
|
label.set_use_markup(true);
|
||||||
builder = builder.name(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
let label = builder.build();
|
|
||||||
|
|
||||||
if let Some(class) = self.class {
|
|
||||||
label.style_context().add_class(&class);
|
|
||||||
}
|
|
||||||
|
|
||||||
let text = self.label.map_or_else(String::new, |text| text);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let label = label.clone();
|
let label = label.clone();
|
||||||
DynamicString::new(&text, move |string| {
|
DynamicString::new(&self.label, move |string| {
|
||||||
label.set_label(&string);
|
label.set_markup(&string);
|
||||||
Continue(true)
|
Continue(true)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,15 +37,6 @@ pub struct CustomModule {
|
||||||
pub common: Option<CommonConfig>,
|
pub common: Option<CommonConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to parse an `Orientation` from `String`
|
|
||||||
fn try_get_orientation(orientation: &str) -> Result<Orientation> {
|
|
||||||
match orientation.to_lowercase().as_str() {
|
|
||||||
"horizontal" | "h" => Ok(Orientation::Horizontal),
|
|
||||||
"vertical" | "v" => Ok(Orientation::Vertical),
|
|
||||||
_ => Err(Report::msg("Invalid orientation string in config")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
#[serde(tag = "type", rename_all = "snake_case")]
|
#[serde(tag = "type", rename_all = "snake_case")]
|
||||||
pub enum Widget {
|
pub enum Widget {
|
||||||
|
@ -70,6 +61,50 @@ trait CustomWidget {
|
||||||
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget;
|
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new widget of type `ty`,
|
||||||
|
/// setting its name and class based on
|
||||||
|
/// the values available on `self`.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! build {
|
||||||
|
($self:ident, $ty:ty) => {{
|
||||||
|
let mut builder = <$ty>::builder();
|
||||||
|
|
||||||
|
if let Some(name) = &$self.name {
|
||||||
|
builder = builder.name(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
let widget = builder.build();
|
||||||
|
|
||||||
|
if let Some(class) = &$self.class {
|
||||||
|
widget.style_context().add_class(class);
|
||||||
|
}
|
||||||
|
|
||||||
|
widget
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the widget length,
|
||||||
|
/// using either a width or height request
|
||||||
|
/// based on the bar's orientation.
|
||||||
|
pub fn set_length<W: WidgetExt>(widget: &W, length: i32, bar_orientation: Orientation) {
|
||||||
|
match bar_orientation {
|
||||||
|
Orientation::Horizontal => widget.set_width_request(length),
|
||||||
|
Orientation::Vertical => widget.set_height_request(length),
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempts to parse an `Orientation` from `String`.
|
||||||
|
/// Will accept `horizontal`, `vertical`, `h` or `v`.
|
||||||
|
/// Ignores case.
|
||||||
|
fn try_get_orientation(orientation: &str) -> Result<Orientation> {
|
||||||
|
match orientation.to_lowercase().as_str() {
|
||||||
|
"horizontal" | "h" => Ok(Orientation::Horizontal),
|
||||||
|
"vertical" | "v" => Ok(Orientation::Vertical),
|
||||||
|
_ => Err(Report::msg("Invalid orientation string in config")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Widget {
|
impl Widget {
|
||||||
/// Creates this widget and adds it to the parent container
|
/// Creates this widget and adds it to the parent container
|
||||||
fn add_to(self, parent: >k::Box, context: CustomWidgetContext) {
|
fn add_to(self, parent: >k::Box, context: CustomWidgetContext) {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext};
|
use super::{try_get_orientation, CustomWidget, CustomWidgetContext};
|
||||||
use crate::dynamic_string::DynamicString;
|
use crate::dynamic_string::DynamicString;
|
||||||
|
use crate::modules::custom::set_length;
|
||||||
use crate::script::{OutputStream, Script, ScriptInput};
|
use crate::script::{OutputStream, Script, ScriptInput};
|
||||||
use crate::send;
|
use crate::{build, send};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Orientation, ProgressBar};
|
use gtk::ProgressBar;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
@ -24,34 +25,20 @@ const fn default_max() -> f64 {
|
||||||
100.0
|
100.0
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Reduce duplication with slider, other widgets.
|
|
||||||
impl CustomWidget for ProgressWidget {
|
impl CustomWidget for ProgressWidget {
|
||||||
type Widget = ProgressBar;
|
type Widget = ProgressBar;
|
||||||
|
|
||||||
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
||||||
let mut builder = ProgressBar::builder();
|
let progress = build!(self, Self::Widget);
|
||||||
|
|
||||||
if let Some(name) = self.name {
|
|
||||||
builder = builder.name(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(orientation) = self.orientation {
|
if let Some(orientation) = self.orientation {
|
||||||
builder = builder
|
progress.set_orientation(
|
||||||
.orientation(try_get_orientation(&orientation).unwrap_or(context.bar_orientation));
|
try_get_orientation(&orientation).unwrap_or(context.bar_orientation),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(length) = self.length {
|
if let Some(length) = self.length {
|
||||||
builder = match context.bar_orientation {
|
set_length(&progress, length, context.bar_orientation);
|
||||||
Orientation::Horizontal => builder.width_request(length),
|
|
||||||
Orientation::Vertical => builder.height_request(length),
|
|
||||||
_ => builder,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let progress = builder.build();
|
|
||||||
|
|
||||||
if let Some(class) = self.class {
|
|
||||||
progress.style_context().add_class(&class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(value) = self.value {
|
if let Some(value) = self.value {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext, ExecEvent};
|
use super::{try_get_orientation, CustomWidget, CustomWidgetContext, ExecEvent};
|
||||||
|
use crate::modules::custom::set_length;
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
use crate::script::{OutputStream, Script, ScriptInput};
|
use crate::script::{OutputStream, Script, ScriptInput};
|
||||||
use crate::{send, try_send};
|
use crate::{build, send, try_send};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Orientation, Scale};
|
use gtk::Scale;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
|
@ -35,33 +36,20 @@ impl CustomWidget for SliderWidget {
|
||||||
type Widget = Scale;
|
type Widget = Scale;
|
||||||
|
|
||||||
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
||||||
let mut builder = Scale::builder();
|
let scale = build!(self, Self::Widget);
|
||||||
|
|
||||||
if let Some(name) = self.name {
|
|
||||||
builder = builder.name(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(orientation) = self.orientation {
|
if let Some(orientation) = self.orientation {
|
||||||
builder = builder
|
scale.set_orientation(
|
||||||
.orientation(try_get_orientation(&orientation).unwrap_or(context.bar_orientation));
|
try_get_orientation(&orientation).unwrap_or(context.bar_orientation),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(length) = self.length {
|
if let Some(length) = self.length {
|
||||||
builder = match context.bar_orientation {
|
set_length(&scale, length, context.bar_orientation);
|
||||||
Orientation::Horizontal => builder.width_request(length),
|
|
||||||
Orientation::Vertical => builder.height_request(length),
|
|
||||||
_ => builder,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let scale = builder.build();
|
|
||||||
|
|
||||||
scale.set_range(self.min, self.max);
|
scale.set_range(self.min, self.max);
|
||||||
|
|
||||||
if let Some(class) = self.class {
|
|
||||||
scale.style_context().add_class(&class);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(on_change) = self.on_change {
|
if let Some(on_change) = self.on_change {
|
||||||
let min = self.min;
|
let min = self.min;
|
||||||
let max = self.max;
|
let max = self.max;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue