mirror of
https://github.com/JakeStanger/ironbar.git
synced 2024-11-27 12:42:46 +03:00
parent
910945306c
commit
72b14b6c4e
@ -17,11 +17,11 @@ You can think of these like HTML elements and their attributes.
|
|||||||
|
|
||||||
Every widget has the following options available; `type` is mandatory.
|
Every widget has the following options available; `type` is mandatory.
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
|---------|-----------------------------------------------------|---------|-------------------------------|
|
|---------|-------------------------------------------------------------------|---------|-------------------------------|
|
||||||
| `type` | `box` or `label` or `button` or `image` or `slider` | `null` | Type of GTK widget to create. |
|
| `type` | `box` or `label` or `button` or `image` or `slider` or `progress` | `null` | Type of GTK widget to create. |
|
||||||
| `name` | `string` | `null` | Widget name. |
|
| `name` | `string` | `null` | Widget name. |
|
||||||
| `class` | `string` | `null` | Widget class name. |
|
| `class` | `string` | `null` | Widget class name. |
|
||||||
|
|
||||||
#### Box
|
#### Box
|
||||||
|
|
||||||
@ -86,9 +86,6 @@ If your input program requires an integer, you will need to round it.
|
|||||||
| `max` | `float` | `100` | Maximum slider value. |
|
| `max` | `float` | `100` | Maximum slider value. |
|
||||||
| `length` | `integer` | `null` | Slider length. GTK will automatically size if left unset. |
|
| `length` | `integer` | `null` | Slider length. GTK will automatically size if left unset. |
|
||||||
|
|
||||||
Note that `on_change` will provide the **floating point** value as an argument.
|
|
||||||
If your input program requires an integer, you will need to round it.
|
|
||||||
|
|
||||||
The example slider widget below shows a volume control for MPC,
|
The example slider widget below shows a volume control for MPC,
|
||||||
which updates the server when changed, and polls the server for volume changes to keep the slider in sync.
|
which updates the server when changed, and polls the server for volume changes to keep the slider in sync.
|
||||||
|
|
||||||
@ -107,6 +104,40 @@ $slider = {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Progress
|
||||||
|
|
||||||
|
A progress bar.
|
||||||
|
|
||||||
|
> Type: `progress`
|
||||||
|
|
||||||
|
Note that `value` expects a numeric value **between 0-`max`** as output.
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
|---------------|----------------------------------------------------|--------------|---------------------------------------------------------------------------------|
|
||||||
|
| `src` | `image` | `null` | Image source. See [here](images) for information on images. |
|
||||||
|
| `size` | `integer` | `null` | Width/height of the image. Aspect ratio is preserved. |
|
||||||
|
| `orientation` | `horizontal` or `vertical` (shorthand: `h` or `v`) | `horizontal` | Orientation of the slider. |
|
||||||
|
| `value` | `Script` | `null` | Script to run to get the progress bar value. Output must be a valid percentage. |
|
||||||
|
| `max` | `float` | `100` | Maximum progress bar value. |
|
||||||
|
| `length` | `integer` | `null` | Slider length. GTK will automatically size if left unset. |
|
||||||
|
|
||||||
|
The example below shows progress for the current playing song in MPD,
|
||||||
|
and displays the elapsed/length timestamps as a label above:
|
||||||
|
|
||||||
|
```corn
|
||||||
|
$progress = {
|
||||||
|
type = "custom"
|
||||||
|
bar = [
|
||||||
|
{
|
||||||
|
type = "progress"
|
||||||
|
value = "500:mpc | sed -n 2p | awk '{ print $4 }' | grep -Eo '[0-9]+'"
|
||||||
|
label = "{{500:mpc | sed -n 2p | awk '{ print $3 }'}} elapsed"
|
||||||
|
length = 200
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Label Attributes
|
### Label Attributes
|
||||||
|
|
||||||
> ℹ This is different to the `label` widget, although applies to it.
|
> ℹ This is different to the `label` widget, although applies to it.
|
||||||
|
@ -2,6 +2,7 @@ mod r#box;
|
|||||||
mod button;
|
mod button;
|
||||||
mod image;
|
mod image;
|
||||||
mod label;
|
mod label;
|
||||||
|
mod progress;
|
||||||
mod slider;
|
mod slider;
|
||||||
|
|
||||||
use self::image::ImageWidget;
|
use self::image::ImageWidget;
|
||||||
@ -10,6 +11,7 @@ use self::r#box::BoxWidget;
|
|||||||
use self::slider::SliderWidget;
|
use self::slider::SliderWidget;
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::modules::custom::button::ButtonWidget;
|
use crate::modules::custom::button::ButtonWidget;
|
||||||
|
use crate::modules::custom::progress::ProgressWidget;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||||
use crate::popup::WidgetGeometry;
|
use crate::popup::WidgetGeometry;
|
||||||
use crate::script::Script;
|
use crate::script::Script;
|
||||||
@ -52,6 +54,7 @@ pub enum Widget {
|
|||||||
Button(ButtonWidget),
|
Button(ButtonWidget),
|
||||||
Image(ImageWidget),
|
Image(ImageWidget),
|
||||||
Slider(SliderWidget),
|
Slider(SliderWidget),
|
||||||
|
Progress(ProgressWidget),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -76,6 +79,7 @@ impl Widget {
|
|||||||
Widget::Button(widget) => parent.add(&widget.into_widget(context)),
|
Widget::Button(widget) => parent.add(&widget.into_widget(context)),
|
||||||
Widget::Image(widget) => parent.add(&widget.into_widget(context)),
|
Widget::Image(widget) => parent.add(&widget.into_widget(context)),
|
||||||
Widget::Slider(widget) => parent.add(&widget.into_widget(context)),
|
Widget::Slider(widget) => parent.add(&widget.into_widget(context)),
|
||||||
|
Widget::Progress(widget) => parent.add(&widget.into_widget(context)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
93
src/modules/custom/progress.rs
Normal file
93
src/modules/custom/progress.rs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
use super::{try_get_orientation, CustomWidget, CustomWidgetContext};
|
||||||
|
use crate::dynamic_string::DynamicString;
|
||||||
|
use crate::script::{OutputStream, Script, ScriptInput};
|
||||||
|
use crate::send;
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use gtk::{Orientation, ProgressBar};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tokio::spawn;
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
pub struct ProgressWidget {
|
||||||
|
name: Option<String>,
|
||||||
|
class: Option<String>,
|
||||||
|
orientation: Option<String>,
|
||||||
|
label: Option<String>,
|
||||||
|
value: Option<ScriptInput>,
|
||||||
|
#[serde(default = "default_max")]
|
||||||
|
max: f64,
|
||||||
|
length: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn default_max() -> f64 {
|
||||||
|
100.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Reduce duplication with slider, other widgets.
|
||||||
|
impl CustomWidget for ProgressWidget {
|
||||||
|
type Widget = ProgressBar;
|
||||||
|
|
||||||
|
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
||||||
|
let mut builder = ProgressBar::builder();
|
||||||
|
|
||||||
|
if let Some(name) = self.name {
|
||||||
|
builder = builder.name(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(orientation) = self.orientation {
|
||||||
|
builder = builder
|
||||||
|
.orientation(try_get_orientation(&orientation).unwrap_or(context.bar_orientation));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(length) = self.length {
|
||||||
|
builder = match 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 {
|
||||||
|
let script = Script::from(value);
|
||||||
|
let progress = progress.clone();
|
||||||
|
|
||||||
|
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||||
|
|
||||||
|
spawn(async move {
|
||||||
|
script
|
||||||
|
.run(None, move |stream, _success| match stream {
|
||||||
|
OutputStream::Stdout(out) => match out.parse::<f64>() {
|
||||||
|
Ok(value) => send!(tx, value),
|
||||||
|
Err(err) => error!("{err:?}"),
|
||||||
|
},
|
||||||
|
OutputStream::Stderr(err) => error!("{err:?}"),
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
|
||||||
|
rx.attach(None, move |value| {
|
||||||
|
progress.set_fraction(value / self.max);
|
||||||
|
Continue(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(text) = self.label {
|
||||||
|
let progress = progress.clone();
|
||||||
|
progress.set_show_text(true);
|
||||||
|
|
||||||
|
DynamicString::new(&text, move |string| {
|
||||||
|
progress.set_text(Some(&string));
|
||||||
|
Continue(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
progress
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use crate::modules::custom::{try_get_orientation, CustomWidget, CustomWidgetContext, ExecEvent};
|
use super::{try_get_orientation, CustomWidget, CustomWidgetContext, ExecEvent};
|
||||||
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::{send, try_send};
|
||||||
|
Loading…
Reference in New Issue
Block a user