more cleanup
This commit is contained in:
parent
8ed820787a
commit
988b9b5085
4 changed files with 101 additions and 22 deletions
|
@ -1,4 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use crate::value::{AttrValue, PrimitiveValue};
|
||||
|
||||
|
@ -51,6 +53,22 @@ impl EwwState {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn resolve_into<
|
||||
TE: std::fmt::Debug,
|
||||
V: TryFrom<PrimitiveValue, Error = TE>,
|
||||
F: Fn(V) + 'static + Clone,
|
||||
>(
|
||||
&mut self,
|
||||
local_env: &HashMap<String, AttrValue>,
|
||||
value: &AttrValue,
|
||||
set_value: F,
|
||||
) -> bool {
|
||||
self.resolve(local_env, value, move |x| {
|
||||
if let Err(e) = x.try_into().map(|v| set_value(v)) {
|
||||
eprintln!("error while resolving value: {:?}", e);
|
||||
};
|
||||
})
|
||||
}
|
||||
pub fn resolve_f64<F: Fn(f64) + 'static + Clone>(
|
||||
&mut self,
|
||||
local_env: &HashMap<String, AttrValue>,
|
||||
|
@ -77,7 +95,7 @@ impl EwwState {
|
|||
};
|
||||
})
|
||||
}
|
||||
pub fn resolve_string<F: Fn(String) + 'static + Clone>(
|
||||
pub fn resolve_str<F: Fn(String) + 'static + Clone>(
|
||||
&mut self,
|
||||
local_env: &HashMap<String, AttrValue>,
|
||||
value: &AttrValue,
|
||||
|
|
|
@ -37,8 +37,9 @@ const EXAMPLE_CONFIG: &str = r#"{
|
|||
"hi",
|
||||
{ button: { children: "click me you" } }
|
||||
{ slider: { value: "$$some_value", min: 0, max: 100, onchange: "notify-send 'changed' {}" } }
|
||||
{ slider: { value: "$$some_value", min: 0, max: 100, onchange: "notify-send 'changed' {}" } }
|
||||
{ slider: { value: "$$some_value", orientation: "vertical" } }
|
||||
"hu"
|
||||
{ image: { path: "/home/leon/Bilder/ElCoward.png" } }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
34
src/value.rs
34
src/value.rs
|
@ -1,17 +1,43 @@
|
|||
use anyhow::*;
|
||||
use derive_more::*;
|
||||
use derive_more;
|
||||
use hocon::Hocon;
|
||||
use std::convert::TryFrom;
|
||||
use try_match::try_match;
|
||||
|
||||
// TODO implement TryFrom for the types properly
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, From)]
|
||||
#[derive(Clone, Debug, PartialEq, derive_more::From)]
|
||||
pub enum PrimitiveValue {
|
||||
String(String),
|
||||
Number(f64),
|
||||
Boolean(bool),
|
||||
}
|
||||
|
||||
impl TryFrom<PrimitiveValue> for String {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(x: PrimitiveValue) -> Result<Self> {
|
||||
match x {
|
||||
PrimitiveValue::String(x) => Ok(x),
|
||||
_ => return Err(anyhow!("'{:?}' is not a string", x.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl TryFrom<PrimitiveValue> for f64 {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(x: PrimitiveValue) -> Result<Self> {
|
||||
try_match!(PrimitiveValue::Number(x) = &x)
|
||||
.map_err(|_| anyhow!("'{:?}' is not a number", &x))
|
||||
.map(|&x| x)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PrimitiveValue> for bool {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(x: PrimitiveValue) -> Result<Self> {
|
||||
try_match!(PrimitiveValue::Boolean(x) = &x)
|
||||
.map_err(|_| anyhow!("'{:?}' is not a bool", &x))
|
||||
.map(|&x| x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for PrimitiveValue {
|
||||
fn from(s: &str) -> Self {
|
||||
PrimitiveValue::String(s.to_string())
|
||||
|
|
|
@ -3,14 +3,35 @@ use crate::eww_state::*;
|
|||
use crate::value::{AttrValue, PrimitiveValue};
|
||||
use anyhow::*;
|
||||
use gtk::prelude::*;
|
||||
use gtk::ImageExt;
|
||||
use std::path::Path;
|
||||
use std::{collections::HashMap, process::Command};
|
||||
|
||||
const CMD_STRING_PLACEHODLER: &str = "{}";
|
||||
|
||||
macro_rules! log_errors {
|
||||
($body:expr) => {{
|
||||
let result = try { $body };
|
||||
if let Err(e) = result {
|
||||
eprintln!("WARN: {}", e);
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! resolve {
|
||||
($args:ident, $gtk_widget:ident, {
|
||||
$(
|
||||
$func:ident => $attr:literal $( = $default:literal)? $( = req $(@$required:tt)?)? => |$arg:ident| $body:expr
|
||||
),+ $(,)?
|
||||
}) => {
|
||||
$(
|
||||
resolve!($args, $gtk_widget, $func => $attr $( [ $default ] )* $($($required)*)* => |$arg| $body);
|
||||
)+
|
||||
};
|
||||
|
||||
($args:ident, $gtk_widget:ident, {
|
||||
$($func:ident => {
|
||||
$($attr:literal $([$default:literal])? $(req $(@$required:tt)?)? => |$arg:ident| $body:expr),+ $(,)?
|
||||
$($attr:literal $(= $default:literal)? $(= req $(@$required:tt)?)? => |$arg:ident| $body:expr),+ $(,)?
|
||||
}),+ $(,)?
|
||||
}) => {
|
||||
$($(
|
||||
|
@ -43,7 +64,6 @@ macro_rules! resolve {
|
|||
move |$arg| { $body; }
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
fn run_command<T: std::fmt::Display>(cmd: &str, arg: T) {
|
||||
|
@ -110,7 +130,7 @@ pub fn build_gtk_widget_or_container(
|
|||
&element_to_gtk_thing(widget_definitions, eww_state, local_env, child)
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"error while building child '{:?}' of '{:?}'",
|
||||
"error while building child '{:?}' of '{}'",
|
||||
&child,
|
||||
>k_widget.get_widget_name()
|
||||
)
|
||||
|
@ -128,6 +148,7 @@ pub fn build_gtk_widget_or_container(
|
|||
fn build_gtk_widget(builder_args: &mut BuilderArgs) -> Result<Option<gtk::Widget>> {
|
||||
let gtk_widget = match builder_args.widget.name.as_str() {
|
||||
"slider" => build_gtk_scale(builder_args)?.upcast(),
|
||||
"image" => build_gtk_image(builder_args)?.upcast(),
|
||||
_ => return Ok(None),
|
||||
};
|
||||
Ok(Some(gtk_widget))
|
||||
|
@ -152,11 +173,12 @@ fn build_gtk_scale(builder_args: &mut BuilderArgs) -> Result<gtk::Scale> {
|
|||
|
||||
resolve!(builder_args, gtk_widget, {
|
||||
resolve_f64 => {
|
||||
"value" req => |v| gtk_widget.set_value(v),
|
||||
"min" => |v| gtk_widget.get_adjustment().set_lower(v),
|
||||
"max" => |v| gtk_widget.get_adjustment().set_upper(v)
|
||||
"value" = req => |v| gtk_widget.set_value(v),
|
||||
"min" => |v| gtk_widget.get_adjustment().set_lower(v),
|
||||
"max" => |v| gtk_widget.get_adjustment().set_upper(v),
|
||||
},
|
||||
resolve_string => {
|
||||
resolve_str => {
|
||||
"orientation" => |v| gtk_widget.set_orientation(parse_orientation(&v)),
|
||||
"onchange" => |cmd| {
|
||||
gtk_widget.connect_value_changed(move |gtk_widget| {
|
||||
run_command(&cmd, gtk_widget.get_value());
|
||||
|
@ -170,12 +192,17 @@ fn build_gtk_scale(builder_args: &mut BuilderArgs) -> Result<gtk::Scale> {
|
|||
fn build_gtk_button(builder_args: &mut BuilderArgs) -> Result<gtk::Button> {
|
||||
let gtk_widget = gtk::Button::new();
|
||||
resolve!(builder_args, gtk_widget, {
|
||||
resolve_bool => {
|
||||
"active" [true] => |v| gtk_widget.set_sensitive(v)
|
||||
},
|
||||
resolve_string => {
|
||||
"onclick" => |cmd| gtk_widget.connect_clicked(move |_| run_command(&cmd, ""))
|
||||
}
|
||||
resolve_bool => "active" = true => |v| gtk_widget.set_sensitive(v),
|
||||
resolve_str => "onclick" => |v| gtk_widget.connect_clicked(move |_| run_command(&v, ""))
|
||||
|
||||
});
|
||||
Ok(gtk_widget)
|
||||
}
|
||||
|
||||
fn build_gtk_image(builder_args: &mut BuilderArgs) -> Result<gtk::Image> {
|
||||
let gtk_widget = gtk::Image::new();
|
||||
resolve!(builder_args, gtk_widget, {
|
||||
resolve_str => "path" = req => |v| gtk_widget.set_from_file(Path::new(&v))
|
||||
});
|
||||
Ok(gtk_widget)
|
||||
}
|
||||
|
@ -183,9 +210,16 @@ fn build_gtk_button(builder_args: &mut BuilderArgs) -> Result<gtk::Button> {
|
|||
fn build_gtk_layout(builder_args: &mut BuilderArgs) -> Result<gtk::Box> {
|
||||
let gtk_widget = gtk::Box::new(gtk::Orientation::Horizontal, 0);
|
||||
resolve!(builder_args, gtk_widget, {
|
||||
resolve_f64 => {
|
||||
"spacing" [10.0] => |v| gtk_widget.set_spacing(v as i32)
|
||||
}
|
||||
resolve_f64 => "spacing" = 10.0 => |v| gtk_widget.set_spacing(v as i32),
|
||||
resolve_str => "orientation" => |v| gtk_widget.set_orientation(parse_orientation(&v)),
|
||||
|
||||
});
|
||||
Ok(gtk_widget)
|
||||
}
|
||||
|
||||
fn parse_orientation(o: &str) -> gtk::Orientation {
|
||||
match o {
|
||||
"vertical" => gtk::Orientation::Vertical,
|
||||
_ => gtk::Orientation::Horizontal,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue