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::collections::HashMap;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use crate::value::{AttrValue, PrimitiveValue};
|
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>(
|
pub fn resolve_f64<F: Fn(f64) + 'static + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
local_env: &HashMap<String, AttrValue>,
|
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,
|
&mut self,
|
||||||
local_env: &HashMap<String, AttrValue>,
|
local_env: &HashMap<String, AttrValue>,
|
||||||
value: &AttrValue,
|
value: &AttrValue,
|
||||||
|
|
|
@ -37,8 +37,9 @@ const EXAMPLE_CONFIG: &str = r#"{
|
||||||
"hi",
|
"hi",
|
||||||
{ button: { children: "click me you" } }
|
{ 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", min: 0, max: 100, onchange: "notify-send 'changed' {}" } }
|
{ slider: { value: "$$some_value", orientation: "vertical" } }
|
||||||
"hu"
|
"hu"
|
||||||
|
{ image: { path: "/home/leon/Bilder/ElCoward.png" } }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
src/value.rs
34
src/value.rs
|
@ -1,17 +1,43 @@
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
use derive_more::*;
|
use derive_more;
|
||||||
use hocon::Hocon;
|
use hocon::Hocon;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use try_match::try_match;
|
use try_match::try_match;
|
||||||
|
|
||||||
// TODO implement TryFrom for the types properly
|
#[derive(Clone, Debug, PartialEq, derive_more::From)]
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, From)]
|
|
||||||
pub enum PrimitiveValue {
|
pub enum PrimitiveValue {
|
||||||
String(String),
|
String(String),
|
||||||
Number(f64),
|
Number(f64),
|
||||||
Boolean(bool),
|
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 {
|
impl From<&str> for PrimitiveValue {
|
||||||
fn from(s: &str) -> Self {
|
fn from(s: &str) -> Self {
|
||||||
PrimitiveValue::String(s.to_string())
|
PrimitiveValue::String(s.to_string())
|
||||||
|
|
|
@ -3,14 +3,35 @@ use crate::eww_state::*;
|
||||||
use crate::value::{AttrValue, PrimitiveValue};
|
use crate::value::{AttrValue, PrimitiveValue};
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
use gtk::ImageExt;
|
||||||
|
use std::path::Path;
|
||||||
use std::{collections::HashMap, process::Command};
|
use std::{collections::HashMap, process::Command};
|
||||||
|
|
||||||
const CMD_STRING_PLACEHODLER: &str = "{}";
|
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 {
|
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, {
|
($args:ident, $gtk_widget:ident, {
|
||||||
$($func: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; }
|
move |$arg| { $body; }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_command<T: std::fmt::Display>(cmd: &str, arg: T) {
|
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)
|
&element_to_gtk_thing(widget_definitions, eww_state, local_env, child)
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
"error while building child '{:?}' of '{:?}'",
|
"error while building child '{:?}' of '{}'",
|
||||||
&child,
|
&child,
|
||||||
>k_widget.get_widget_name()
|
>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>> {
|
fn build_gtk_widget(builder_args: &mut BuilderArgs) -> Result<Option<gtk::Widget>> {
|
||||||
let gtk_widget = match builder_args.widget.name.as_str() {
|
let gtk_widget = match builder_args.widget.name.as_str() {
|
||||||
"slider" => build_gtk_scale(builder_args)?.upcast(),
|
"slider" => build_gtk_scale(builder_args)?.upcast(),
|
||||||
|
"image" => build_gtk_image(builder_args)?.upcast(),
|
||||||
_ => return Ok(None),
|
_ => return Ok(None),
|
||||||
};
|
};
|
||||||
Ok(Some(gtk_widget))
|
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!(builder_args, gtk_widget, {
|
||||||
resolve_f64 => {
|
resolve_f64 => {
|
||||||
"value" req => |v| gtk_widget.set_value(v),
|
"value" = req => |v| gtk_widget.set_value(v),
|
||||||
"min" => |v| gtk_widget.get_adjustment().set_lower(v),
|
"min" => |v| gtk_widget.get_adjustment().set_lower(v),
|
||||||
"max" => |v| gtk_widget.get_adjustment().set_upper(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| {
|
"onchange" => |cmd| {
|
||||||
gtk_widget.connect_value_changed(move |gtk_widget| {
|
gtk_widget.connect_value_changed(move |gtk_widget| {
|
||||||
run_command(&cmd, gtk_widget.get_value());
|
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> {
|
fn build_gtk_button(builder_args: &mut BuilderArgs) -> Result<gtk::Button> {
|
||||||
let gtk_widget = gtk::Button::new();
|
let gtk_widget = gtk::Button::new();
|
||||||
resolve!(builder_args, gtk_widget, {
|
resolve!(builder_args, gtk_widget, {
|
||||||
resolve_bool => {
|
resolve_bool => "active" = true => |v| gtk_widget.set_sensitive(v),
|
||||||
"active" [true] => |v| gtk_widget.set_sensitive(v)
|
resolve_str => "onclick" => |v| gtk_widget.connect_clicked(move |_| run_command(&v, ""))
|
||||||
},
|
|
||||||
resolve_string => {
|
});
|
||||||
"onclick" => |cmd| gtk_widget.connect_clicked(move |_| run_command(&cmd, ""))
|
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)
|
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> {
|
fn build_gtk_layout(builder_args: &mut BuilderArgs) -> Result<gtk::Box> {
|
||||||
let gtk_widget = gtk::Box::new(gtk::Orientation::Horizontal, 0);
|
let gtk_widget = gtk::Box::new(gtk::Orientation::Horizontal, 0);
|
||||||
resolve!(builder_args, gtk_widget, {
|
resolve!(builder_args, gtk_widget, {
|
||||||
resolve_f64 => {
|
resolve_f64 => "spacing" = 10.0 => |v| gtk_widget.set_spacing(v as i32),
|
||||||
"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)
|
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