more cleanup

This commit is contained in:
elkowar 2020-09-22 00:30:13 +02:00
parent 8ed820787a
commit 988b9b5085
4 changed files with 101 additions and 22 deletions

View file

@ -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,

View file

@ -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" } }
]
}
}

View file

@ -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())

View file

@ -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,
&gtk_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,
}
}