variables
This commit is contained in:
parent
f7021201ca
commit
43b431c2dc
5 changed files with 348 additions and 91 deletions
45
.vscode/launch.json
vendored
Normal file
45
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug executable 'eww'",
|
||||||
|
"cargo": {
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"--bin=eww",
|
||||||
|
"--package=eww"
|
||||||
|
],
|
||||||
|
"filter": {
|
||||||
|
"name": "eww",
|
||||||
|
"kind": "bin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug unit tests in executable 'eww'",
|
||||||
|
"cargo": {
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"--no-run",
|
||||||
|
"--bin=eww",
|
||||||
|
"--package=eww"
|
||||||
|
],
|
||||||
|
"filter": {
|
||||||
|
"name": "eww",
|
||||||
|
"kind": "bin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
69
Cargo.lock
generated
69
Cargo.lock
generated
|
@ -24,6 +24,15 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.32"
|
version = "1.0.32"
|
||||||
|
@ -120,6 +129,22 @@ version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctor"
|
||||||
|
version = "0.1.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "39858aa5bac06462d4dd4b9164848eb81ffc4aa5c479746393598fd193afa227"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "difference"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -200,6 +225,7 @@ dependencies = [
|
||||||
"glib",
|
"glib",
|
||||||
"gtk",
|
"gtk",
|
||||||
"hocon",
|
"hocon",
|
||||||
|
"pretty_assertions",
|
||||||
"regex",
|
"regex",
|
||||||
"try_match",
|
"try_match",
|
||||||
]
|
]
|
||||||
|
@ -630,6 +656,15 @@ version = "1.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
|
checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "output_vt100"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango"
|
name = "pango"
|
||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
|
@ -695,6 +730,18 @@ version = "0.2.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
|
checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pretty_assertions"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"ctor",
|
||||||
|
"difference",
|
||||||
|
"output_vt100",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
@ -996,3 +1043,25 @@ name = "wasi"
|
||||||
version = "0.9.0+wasi-snapshot-preview1"
|
version = "0.9.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
|
@ -23,3 +23,4 @@ anyhow = "1.0"
|
||||||
#thiserror = "1.0"
|
#thiserror = "1.0"
|
||||||
|
|
||||||
|
|
||||||
|
pretty_assertions = "0.6.1"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
use glib::{types, value};
|
|
||||||
use hocon::*;
|
use hocon::*;
|
||||||
use hocon_ext::HoconExt;
|
use hocon_ext::HoconExt;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use try_match::try_match;
|
use try_match::try_match;
|
||||||
|
|
||||||
pub mod hocon_ext;
|
pub mod hocon_ext;
|
||||||
|
@ -11,6 +11,7 @@ pub mod hocon_ext;
|
||||||
pub struct EwwConfig {
|
pub struct EwwConfig {
|
||||||
widgets: HashMap<String, WidgetDefinition>,
|
widgets: HashMap<String, WidgetDefinition>,
|
||||||
windows: HashMap<String, EwwWindowDefinition>,
|
windows: HashMap<String, EwwWindowDefinition>,
|
||||||
|
default_vars: HashMap<String, AttrValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EwwConfig {
|
impl EwwConfig {
|
||||||
|
@ -36,15 +37,26 @@ impl EwwConfig {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, def)| Ok((name.clone(), EwwWindowDefinition::from_hocon(def)?)))
|
.map(|(name, def)| Ok((name.clone(), EwwWindowDefinition::from_hocon(def)?)))
|
||||||
.collect::<Result<HashMap<String, EwwWindowDefinition>>>()?,
|
.collect::<Result<HashMap<String, EwwWindowDefinition>>>()?,
|
||||||
|
default_vars: data
|
||||||
|
.get("default_vars")
|
||||||
|
.unwrap_or(&Hocon::Hash(HashMap::new()))
|
||||||
|
.as_hash()
|
||||||
|
.context("default_vars needs to be a map")?
|
||||||
|
.iter()
|
||||||
|
.map(|(name, def)| Ok((name.clone(), AttrValue::try_from(def)?)))
|
||||||
|
.collect::<Result<HashMap<_, _>>>()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn widgets(&self) -> &HashMap<String, WidgetDefinition> {
|
pub fn get_widgets(&self) -> &HashMap<String, WidgetDefinition> {
|
||||||
&self.widgets
|
&self.widgets
|
||||||
}
|
}
|
||||||
pub fn windows(&self) -> &HashMap<String, EwwWindowDefinition> {
|
pub fn get_windows(&self) -> &HashMap<String, EwwWindowDefinition> {
|
||||||
&self.windows
|
&self.windows
|
||||||
}
|
}
|
||||||
|
pub fn get_default_vars(&self) -> &HashMap<String, AttrValue> {
|
||||||
|
&self.default_vars
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -106,6 +118,22 @@ impl AttrValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::convert::TryFrom<&Hocon> for AttrValue {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
fn try_from(value: &Hocon) -> Result<Self> {
|
||||||
|
Ok(match value {
|
||||||
|
Hocon::String(s) if s.starts_with("$$") => {
|
||||||
|
AttrValue::VarRef(s.trim_start_matches("$$").to_string())
|
||||||
|
}
|
||||||
|
Hocon::String(s) => AttrValue::String(s.to_string()),
|
||||||
|
Hocon::Integer(n) => AttrValue::Number(*n as f64),
|
||||||
|
Hocon::Real(n) => AttrValue::Number(*n as f64),
|
||||||
|
Hocon::Boolean(b) => AttrValue::Boolean(*b),
|
||||||
|
_ => return Err(anyhow!("cannot convert {} to config::AttrValue")),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct WidgetDefinition {
|
pub struct WidgetDefinition {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
@ -193,19 +221,7 @@ pub fn parse_widget_use(data: HashMap<String, Hocon>) -> Result<WidgetUse> {
|
||||||
|
|
||||||
let attrs: HashMap<String, AttrValue> = widget_config
|
let attrs: HashMap<String, AttrValue> = widget_config
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(key, value)| {
|
.filter_map(|(key, value)| Some((key.to_lowercase(), AttrValue::try_from(value).ok()?)))
|
||||||
Some((
|
|
||||||
key.to_lowercase(),
|
|
||||||
match value {
|
|
||||||
Hocon::String(s) if s.starts_with("$$") => AttrValue::String(s.to_string()),
|
|
||||||
Hocon::String(s) => AttrValue::String(s.to_string()),
|
|
||||||
Hocon::Integer(n) => AttrValue::Number(*n as f64),
|
|
||||||
Hocon::Real(n) => AttrValue::Number(*n as f64),
|
|
||||||
Hocon::Boolean(b) => AttrValue::Boolean(*b),
|
|
||||||
_ => return None,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(WidgetUse {
|
Ok(WidgetUse {
|
||||||
|
|
250
src/main.rs
250
src/main.rs
|
@ -23,13 +23,17 @@ const EXAMPLE_CONFIG: &str = r#"{
|
||||||
children: [
|
children: [
|
||||||
"hi",
|
"hi",
|
||||||
{ button: { children: "click me you" } }
|
{ button: { children: "click me you" } }
|
||||||
{ slider: { value: 12, min: 0, max: 50, 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' {}" } }
|
||||||
"hu"
|
"hu"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
default_vars: {
|
||||||
|
ree: 12
|
||||||
|
}
|
||||||
windows: {
|
windows: {
|
||||||
main_window: {
|
main_window: {
|
||||||
pos.x: 200
|
pos.x: 200
|
||||||
|
@ -37,20 +41,35 @@ const EXAMPLE_CONFIG: &str = r#"{
|
||||||
size.x: 500
|
size.x: 500
|
||||||
size.y: 50
|
size.y: 50
|
||||||
widget: {
|
widget: {
|
||||||
some_widget: {}
|
some_widget: {
|
||||||
|
some_value: "$$ree"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
|
macro_rules! build {
|
||||||
|
($var_name:ident = $value:expr ; $code:block) => {{
|
||||||
|
let mut $var_name = $value;
|
||||||
|
$code;
|
||||||
|
$var_name
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum MuhhMsg {
|
||||||
|
UpdateValue(String, config::AttrValue),
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let eww_config = config::EwwConfig::from_hocon(&config::parse_hocon(EXAMPLE_CONFIG)?)?;
|
let eww_config = config::EwwConfig::from_hocon(&config::parse_hocon(EXAMPLE_CONFIG)?)?;
|
||||||
|
dbg!(&eww_config);
|
||||||
|
|
||||||
let application = Application::new(Some("de.elkowar.eww"), gio::ApplicationFlags::FLAGS_NONE)
|
let application = Application::new(Some("de.elkowar.eww"), gio::ApplicationFlags::FLAGS_NONE)
|
||||||
.expect("failed to initialize GTK application");
|
.expect("failed to initialize GTK application ");
|
||||||
|
|
||||||
let window_def = eww_config.windows()["main_window"].clone();
|
let window_def = eww_config.get_windows()["main_window"].clone();
|
||||||
|
|
||||||
application.connect_activate(move |app| {
|
application.connect_activate(move |app| {
|
||||||
let app_window = ApplicationWindow::new(app);
|
let app_window = ApplicationWindow::new(app);
|
||||||
|
@ -76,17 +95,33 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
app_window.fullscreen();
|
app_window.fullscreen();
|
||||||
|
|
||||||
let widget_state = WidgetState(HashMap::new());
|
let mut eww_state = EwwState::from_default_vars(eww_config.get_default_vars().clone());
|
||||||
|
let empty_local_state = HashMap::new();
|
||||||
|
|
||||||
app_window.add(
|
app_window.add(
|
||||||
&element_to_gtk_widget(&eww_config.widgets(), &widget_state, &window_def.widget)
|
&element_to_gtk_thing(
|
||||||
|
&eww_config.get_widgets(),
|
||||||
|
&mut eww_state,
|
||||||
|
&empty_local_state,
|
||||||
|
&window_def.widget,
|
||||||
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
app_window.show_all();
|
app_window.show_all();
|
||||||
|
|
||||||
let window = app_window.get_window().unwrap();
|
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||||
|
std::thread::spawn(move || event_loop(tx));
|
||||||
|
|
||||||
|
rx.attach(None, move |msg| {
|
||||||
|
match msg {
|
||||||
|
MuhhMsg::UpdateValue(key, value) => eww_state.update_value(key, value),
|
||||||
|
}
|
||||||
|
|
||||||
|
glib::Continue(true)
|
||||||
|
});
|
||||||
|
|
||||||
|
let window = app_window.get_window().unwrap();
|
||||||
window.set_override_redirect(true);
|
window.set_override_redirect(true);
|
||||||
window.move_(window_def.position.0, window_def.position.1);
|
window.move_(window_def.position.0, window_def.position.1);
|
||||||
window.show();
|
window.show();
|
||||||
|
@ -94,21 +129,52 @@ fn main() -> Result<()> {
|
||||||
});
|
});
|
||||||
|
|
||||||
application.run(&[]);
|
application.run(&[]);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn element_to_gtk_widget(
|
fn event_loop(sender: glib::Sender<MuhhMsg>) {
|
||||||
|
let mut x = 0;
|
||||||
|
loop {
|
||||||
|
x += 1;
|
||||||
|
std::thread::sleep_ms(1000);
|
||||||
|
sender
|
||||||
|
.send(MuhhMsg::UpdateValue(
|
||||||
|
"ree".to_string(),
|
||||||
|
config::AttrValue::Number(x as f64 * 10.0),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn element_to_gtk_thing(
|
||||||
widget_definitions: &HashMap<String, config::WidgetDefinition>,
|
widget_definitions: &HashMap<String, config::WidgetDefinition>,
|
||||||
widget_state: &WidgetState,
|
eww_state: &mut EwwState,
|
||||||
|
local_environment: &HashMap<String, config::AttrValue>,
|
||||||
element: &config::ElementUse,
|
element: &config::ElementUse,
|
||||||
) -> Option<gtk::Widget> {
|
) -> Option<gtk::Widget> {
|
||||||
match element {
|
match element {
|
||||||
config::ElementUse::Text(text) => Some(gtk::Label::new(Some(&text)).upcast()),
|
config::ElementUse::Text(text) => Some(gtk::Label::new(Some(&text)).upcast()),
|
||||||
config::ElementUse::Widget(widget) => {
|
config::ElementUse::Widget(widget) => {
|
||||||
|
widget_use_to_gtk_thing(widget_definitions, eww_state, local_environment, widget)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn widget_use_to_gtk_thing(
|
||||||
|
widget_definitions: &HashMap<String, config::WidgetDefinition>,
|
||||||
|
eww_state: &mut EwwState,
|
||||||
|
local_environment: &HashMap<String, config::AttrValue>,
|
||||||
|
widget: &config::WidgetUse,
|
||||||
|
) -> Option<gtk::Widget> {
|
||||||
let gtk_widget =
|
let gtk_widget =
|
||||||
widget_use_to_gtk_container(widget_definitions, widget_state, &widget).or(
|
widget_use_to_gtk_container(widget_definitions, eww_state, &local_environment, &widget)
|
||||||
widget_use_to_gtk_widget(widget_definitions, widget_state, &widget),
|
.or(widget_use_to_gtk_widget(
|
||||||
)?;
|
widget_definitions,
|
||||||
|
eww_state,
|
||||||
|
&local_environment,
|
||||||
|
&widget,
|
||||||
|
))?;
|
||||||
if let Some(css_class) = widget
|
if let Some(css_class) = widget
|
||||||
.attrs
|
.attrs
|
||||||
.get("class")
|
.get("class")
|
||||||
|
@ -118,13 +184,12 @@ fn element_to_gtk_widget(
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(gtk_widget)
|
Some(gtk_widget)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn widget_use_to_gtk_container(
|
fn widget_use_to_gtk_container(
|
||||||
widget_definitions: &HashMap<String, config::WidgetDefinition>,
|
widget_definitions: &HashMap<String, config::WidgetDefinition>,
|
||||||
widget_state: &WidgetState,
|
eww_state: &mut EwwState,
|
||||||
|
local_environment: &HashMap<String, config::AttrValue>,
|
||||||
widget: &config::WidgetUse,
|
widget: &config::WidgetUse,
|
||||||
) -> Option<gtk::Widget> {
|
) -> Option<gtk::Widget> {
|
||||||
let container_widget: gtk::Container = match widget.name.as_str() {
|
let container_widget: gtk::Container = match widget.name.as_str() {
|
||||||
|
@ -134,9 +199,10 @@ fn widget_use_to_gtk_container(
|
||||||
};
|
};
|
||||||
|
|
||||||
for child in &widget.children {
|
for child in &widget.children {
|
||||||
container_widget.add(&element_to_gtk_widget(
|
container_widget.add(&element_to_gtk_thing(
|
||||||
widget_definitions,
|
widget_definitions,
|
||||||
widget_state,
|
eww_state,
|
||||||
|
local_environment,
|
||||||
child,
|
child,
|
||||||
)?);
|
)?);
|
||||||
}
|
}
|
||||||
|
@ -145,68 +211,136 @@ fn widget_use_to_gtk_container(
|
||||||
|
|
||||||
fn widget_use_to_gtk_widget(
|
fn widget_use_to_gtk_widget(
|
||||||
widget_definitions: &HashMap<String, config::WidgetDefinition>,
|
widget_definitions: &HashMap<String, config::WidgetDefinition>,
|
||||||
state: &WidgetState,
|
eww_state: &mut EwwState,
|
||||||
|
local_env: &HashMap<String, config::AttrValue>,
|
||||||
widget: &config::WidgetUse,
|
widget: &config::WidgetUse,
|
||||||
) -> Option<gtk::Widget> {
|
) -> Option<gtk::Widget> {
|
||||||
let new_widget: gtk::Widget = match widget.name.as_str() {
|
let new_widget: gtk::Widget = match widget.name.as_str() {
|
||||||
"slider" => {
|
"slider" => {
|
||||||
let slider_value: f64 = state.resolve(widget.attrs.get("value")?)?.as_f64()?;
|
|
||||||
let slider_min: Option<f64> =
|
|
||||||
try { state.resolve(widget.attrs.get("min")?)?.as_f64()? };
|
|
||||||
let slider_min = slider_min.unwrap_or(0f64);
|
|
||||||
let slider_max: Option<f64> =
|
|
||||||
try { state.resolve(widget.attrs.get("max")?)?.as_f64()? };
|
|
||||||
let slider_max = slider_max.unwrap_or(100f64);
|
|
||||||
|
|
||||||
let on_change: Option<String> = try {
|
|
||||||
state
|
|
||||||
.resolve(widget.attrs.get("onchange")?)?
|
|
||||||
.as_string()?
|
|
||||||
.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
let scale = gtk::Scale::new(
|
let scale = gtk::Scale::new(
|
||||||
gtk::Orientation::Horizontal,
|
gtk::Orientation::Horizontal,
|
||||||
Some(>k::Adjustment::new(
|
Some(>k::Adjustment::new(0.0, 0.0, 100.0, 1.0, 1.0, 1.0)),
|
||||||
slider_value,
|
|
||||||
slider_min,
|
|
||||||
slider_max,
|
|
||||||
1.0,
|
|
||||||
1.0,
|
|
||||||
1.0,
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
scale.set_property("draw-value", &false.to_value()).ok()?;
|
eww_state.resolve_f64(local_env, widget.attrs.get("value")?, {
|
||||||
|
let scale = scale.clone();
|
||||||
if let Some(on_change) = on_change {
|
move |value| scale.set_value(value)
|
||||||
|
});
|
||||||
|
eww_state.resolve_f64(local_env, widget.attrs.get("min")?, {
|
||||||
|
let scale = scale.clone();
|
||||||
|
move |value| scale.get_adjustment().set_lower(value)
|
||||||
|
});
|
||||||
|
eww_state.resolve_f64(local_env, widget.attrs.get("max")?, {
|
||||||
|
let scale = scale.clone();
|
||||||
|
move |value| scale.get_adjustment().set_upper(value)
|
||||||
|
});
|
||||||
|
eww_state.resolve_string(local_env, widget.attrs.get("onchange")?, {
|
||||||
|
let scale = scale.clone();
|
||||||
|
move |on_change| {
|
||||||
scale.connect_value_changed(move |scale| {
|
scale.connect_value_changed(move |scale| {
|
||||||
run_command(&on_change, scale.get_value());
|
run_command(&on_change, scale.get_value());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//scale.set_property("draw-value", &false.to_value()).ok()?;
|
||||||
scale.upcast()
|
scale.upcast()
|
||||||
}
|
}
|
||||||
|
|
||||||
name if widget_definitions.contains_key(name) => {
|
name if widget_definitions.contains_key(name) => {
|
||||||
let def = &widget_definitions[name];
|
let def = &widget_definitions[name];
|
||||||
element_to_gtk_widget(widget_definitions, state, &def.structure)?
|
let local_environment = build!(env = local_env.clone(); {
|
||||||
|
env.extend(widget.attrs.clone());
|
||||||
|
});
|
||||||
|
|
||||||
|
element_to_gtk_thing(
|
||||||
|
widget_definitions,
|
||||||
|
eww_state,
|
||||||
|
&local_environment,
|
||||||
|
&def.structure,
|
||||||
|
)?
|
||||||
}
|
}
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some(new_widget)
|
Some(new_widget)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WidgetState(HashMap<String, config::AttrValue>);
|
#[derive(Default)]
|
||||||
|
struct EwwState {
|
||||||
|
on_change_handlers: HashMap<String, Vec<Box<dyn Fn(config::AttrValue) + 'static>>>,
|
||||||
|
state: HashMap<String, config::AttrValue>,
|
||||||
|
}
|
||||||
|
|
||||||
impl WidgetState {
|
impl EwwState {
|
||||||
pub fn resolve(&self, value: &config::AttrValue) -> Option<config::AttrValue> {
|
pub fn from_default_vars(defaults: HashMap<String, config::AttrValue>) -> Self {
|
||||||
if let config::AttrValue::VarRef(name) = value {
|
EwwState {
|
||||||
// TODO REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
|
state: defaults,
|
||||||
self.0.get(name).cloned()
|
..EwwState::default()
|
||||||
} else {
|
|
||||||
Some(value.clone())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn update_value(&mut self, key: String, value: config::AttrValue) {
|
||||||
|
if let Some(handlers) = self.on_change_handlers.get(&key) {
|
||||||
|
for on_change in handlers {
|
||||||
|
on_change(value.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.state.insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve<F: Fn(config::AttrValue) + 'static + Clone>(
|
||||||
|
&mut self,
|
||||||
|
local_env: &HashMap<String, config::AttrValue>,
|
||||||
|
value: &config::AttrValue,
|
||||||
|
set_value: F,
|
||||||
|
) -> bool {
|
||||||
|
dbg!("resolve: ", value);
|
||||||
|
if let config::AttrValue::VarRef(name) = value {
|
||||||
|
if let Some(value) = self.state.get(name).cloned() {
|
||||||
|
self.on_change_handlers
|
||||||
|
.entry(name.to_string())
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(Box::new(set_value.clone()));
|
||||||
|
self.resolve(local_env, &value, set_value)
|
||||||
|
} else if let Some(value) = local_env.get(name).cloned() {
|
||||||
|
self.resolve(local_env, &value, set_value)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
set_value(value.clone());
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_f64<F: Fn(f64) + 'static + Clone>(
|
||||||
|
&mut self,
|
||||||
|
local_env: &HashMap<String, config::AttrValue>,
|
||||||
|
value: &config::AttrValue,
|
||||||
|
set_value: F,
|
||||||
|
) -> bool {
|
||||||
|
self.resolve(local_env, value, move |x| {
|
||||||
|
x.as_f64().map(|v| set_value(v));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn resolve_bool<F: Fn(bool) + 'static + Clone>(
|
||||||
|
&mut self,
|
||||||
|
local_env: &HashMap<String, config::AttrValue>,
|
||||||
|
value: &config::AttrValue,
|
||||||
|
set_value: F,
|
||||||
|
) -> bool {
|
||||||
|
self.resolve(local_env, value, move |x| {
|
||||||
|
x.as_bool().map(|v| set_value(v));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn resolve_string<F: Fn(String) + 'static + Clone>(
|
||||||
|
&mut self,
|
||||||
|
local_env: &HashMap<String, config::AttrValue>,
|
||||||
|
value: &config::AttrValue,
|
||||||
|
set_value: F,
|
||||||
|
) -> bool {
|
||||||
|
self.resolve(local_env, value, move |x| {
|
||||||
|
x.as_string().map(|s| set_value(s.clone()));
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_command<T: std::fmt::Display>(cmd: &str, arg: T) {
|
fn run_command<T: std::fmt::Display>(cmd: &str, arg: T) {
|
||||||
|
@ -215,11 +349,3 @@ fn run_command<T: std::fmt::Display>(cmd: &str, arg: T) {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// macro_rules! build {
|
|
||||||
// ($var_name:ident = $value:expr ; $code:block) => {{
|
|
||||||
// let mut $var_name = $value;
|
|
||||||
// $code;
|
|
||||||
// $var_name
|
|
||||||
// }};
|
|
||||||
// }
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue