mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-03 03:31:03 +02:00
Merge pull request #106 from JakeStanger/feat/custom-dynamic-image
Custom image dynamic src support
This commit is contained in:
commit
2815cef440
6 changed files with 47 additions and 36 deletions
|
@ -62,8 +62,8 @@ An image or icon from disk or http.
|
||||||
> Type `image`
|
> Type `image`
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
|--------|-----------|---------|-------------------------------------------------------------|
|
|--------|-----------|---------|---------------------------------------------------------------------------------------------|
|
||||||
| `src` | `image` | `null` | Image source. See [here](images) for information on images. |
|
| `src` | `image` | `null` | Image source. See [here](images) for information on images. Embedded scripts are supported. |
|
||||||
| `size` | `integer` | `null` | Width/height of the image. Aspect ratio is preserved. |
|
| `size` | `integer` | `null` | Width/height of the image. Aspect ratio is preserved. |
|
||||||
|
|
||||||
#### Slider
|
#### Slider
|
||||||
|
@ -130,7 +130,7 @@ $progress = {
|
||||||
bar = [
|
bar = [
|
||||||
{
|
{
|
||||||
type = "progress"
|
type = "progress"
|
||||||
value = "500:mpc | sed -n 2p | awk '{ print $4 }' | grep -Eo '[0-9]+'"
|
value = "500:mpc | sed -n 2p | awk '{ print $4 }' | grep -Eo '[0-9]+' || echo 0"
|
||||||
label = "{{500:mpc | sed -n 2p | awk '{ print $3 }'}} elapsed"
|
label = "{{500:mpc | sed -n 2p | awk '{ print $3 }'}} elapsed"
|
||||||
length = 200
|
length = 200
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,16 @@ impl<'a> ImageProvider<'a> {
|
||||||
/// Attempts to get `Bytes` from an HTTP resource asynchronously.
|
/// Attempts to get `Bytes` from an HTTP resource asynchronously.
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
async fn get_bytes_from_http(url: reqwest::Url) -> Result<glib::Bytes> {
|
async fn get_bytes_from_http(url: reqwest::Url) -> Result<glib::Bytes> {
|
||||||
let bytes = reqwest::get(url).await?.bytes().await?;
|
let res = reqwest::get(url).await?;
|
||||||
|
|
||||||
|
let status = res.status();
|
||||||
|
if status.is_success() {
|
||||||
|
let bytes = res.bytes().await?;
|
||||||
Ok(glib::Bytes::from_owned(bytes))
|
Ok(glib::Bytes::from_owned(bytes))
|
||||||
|
} else {
|
||||||
|
Err(Report::msg(format!(
|
||||||
|
"Received non-success HTTP code ({status})"
|
||||||
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ impl CustomWidget for BoxWidget {
|
||||||
if let Some(orientation) = self.orientation {
|
if let Some(orientation) = self.orientation {
|
||||||
container.set_orientation(
|
container.set_orientation(
|
||||||
try_get_orientation(&orientation).unwrap_or(Orientation::Horizontal),
|
try_get_orientation(&orientation).unwrap_or(Orientation::Horizontal),
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(widgets) = self.widgets {
|
if let Some(widgets) = self.widgets {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::{CustomWidget, CustomWidgetContext};
|
use super::{CustomWidget, CustomWidgetContext};
|
||||||
use crate::build;
|
use crate::build;
|
||||||
|
use crate::dynamic_string::DynamicString;
|
||||||
use crate::image::ImageProvider;
|
use crate::image::ImageProvider;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Image;
|
use gtk::Image;
|
||||||
|
@ -10,8 +11,13 @@ use tracing::error;
|
||||||
pub struct ImageWidget {
|
pub struct ImageWidget {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
class: Option<String>,
|
class: Option<String>,
|
||||||
src: Option<String>,
|
src: String,
|
||||||
size: Option<i32>,
|
#[serde(default = "default_size")]
|
||||||
|
size: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn default_size() -> i32 {
|
||||||
|
32
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomWidget for ImageWidget {
|
impl CustomWidget for ImageWidget {
|
||||||
|
@ -20,13 +26,20 @@ impl CustomWidget for ImageWidget {
|
||||||
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
fn into_widget(self, context: CustomWidgetContext) -> Self::Widget {
|
||||||
let gtk_image = build!(self, Self::Widget);
|
let gtk_image = build!(self, Self::Widget);
|
||||||
|
|
||||||
if let Some(src) = self.src {
|
|
||||||
let size = self.size.unwrap_or(32);
|
|
||||||
if let Err(err) = ImageProvider::parse(&src, context.icon_theme, size)
|
|
||||||
.and_then(|image| image.load_into_image(gtk_image.clone()))
|
|
||||||
{
|
{
|
||||||
|
let gtk_image = gtk_image.clone();
|
||||||
|
let icon_theme = context.icon_theme.clone();
|
||||||
|
|
||||||
|
DynamicString::new(&self.src, move |src| {
|
||||||
|
let res = ImageProvider::parse(&src, &icon_theme, self.size)
|
||||||
|
.and_then(|image| image.load_into_image(gtk_image.clone()));
|
||||||
|
|
||||||
|
if let Err(err) = res {
|
||||||
error!("{err:?}");
|
error!("{err:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Continue(true)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_image
|
gtk_image
|
||||||
|
|
|
@ -109,12 +109,12 @@ 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) {
|
||||||
match self {
|
match self {
|
||||||
Widget::Box(widget) => parent.add(&widget.into_widget(context)),
|
Self::Box(widget) => parent.add(&widget.into_widget(context)),
|
||||||
Widget::Label(widget) => parent.add(&widget.into_widget(context)),
|
Self::Label(widget) => parent.add(&widget.into_widget(context)),
|
||||||
Widget::Button(widget) => parent.add(&widget.into_widget(context)),
|
Self::Button(widget) => parent.add(&widget.into_widget(context)),
|
||||||
Widget::Image(widget) => parent.add(&widget.into_widget(context)),
|
Self::Image(widget) => parent.add(&widget.into_widget(context)),
|
||||||
Widget::Slider(widget) => parent.add(&widget.into_widget(context)),
|
Self::Slider(widget) => parent.add(&widget.into_widget(context)),
|
||||||
Widget::Progress(widget) => parent.add(&widget.into_widget(context)),
|
Self::Progress(widget) => parent.add(&widget.into_widget(context)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ impl Module<gtk::Box> for CustomModule {
|
||||||
|
|
||||||
debug!("executing command: '{}'", script.cmd);
|
debug!("executing command: '{}'", script.cmd);
|
||||||
|
|
||||||
let args = event.args.unwrap_or(vec![]);
|
let args = event.args.unwrap_or_default();
|
||||||
|
|
||||||
if let Err(err) = script.get_output(Some(&args)).await {
|
if let Err(err) = script.get_output(Some(&args)).await {
|
||||||
error!("{err:?}");
|
error!("{err:?}");
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl CustomWidget for SliderWidget {
|
||||||
|
|
||||||
scale.connect_change_value(move |scale, _, val| {
|
scale.connect_change_value(move |scale, _, val| {
|
||||||
// GTK will send values outside min/max range
|
// GTK will send values outside min/max range
|
||||||
let val = clamp(val, min, max);
|
let val = val.clamp(min, max);
|
||||||
|
|
||||||
if val != prev_value.get() {
|
if val != prev_value.get() {
|
||||||
try_send!(
|
try_send!(
|
||||||
|
@ -106,14 +106,3 @@ impl CustomWidget for SliderWidget {
|
||||||
scale
|
scale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensures `num` is between `min` and `max` (inclusive).
|
|
||||||
fn clamp(num: f64, min: f64, max: f64) -> f64 {
|
|
||||||
if num < min {
|
|
||||||
min
|
|
||||||
} else if num > max {
|
|
||||||
max
|
|
||||||
} else {
|
|
||||||
num
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue