mirror of
https://github.com/elkowar/eww.git
synced 2024-10-03 22:48:31 +03:00
CI/CD & Formatting (#6)
* Improve autoformatting guides, add editorconfig and add CI/CD
This commit is contained in:
parent
4d6b38f3e1
commit
c57713ca9a
8
.editorconfig
Normal file
8
.editorconfig
Normal file
@ -0,0 +1,8 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
26
.github/workflows/build.yml
vendored
Normal file
26
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set up
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
override: true
|
||||
components: rustfmt
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- name: Format
|
||||
run: cargo build
|
26
.github/workflows/fmt.yml
vendored
Normal file
26
.github/workflows/fmt.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: format
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
fmt:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set up
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
override: true
|
||||
components: rustfmt
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- name: Format
|
||||
run: cargo fmt -- --check
|
26
.github/workflows/test.yml
vendored
Normal file
26
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set up
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
override: true
|
||||
components: rustfmt
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
- name: Test
|
||||
run: cargo test --verbose
|
@ -4,8 +4,6 @@ version = "0.1.0"
|
||||
authors = ["elkowar <5300871+elkowar@users.noreply.github.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
gtk = { version = "0.9", features = [ "v3_16" ] }
|
||||
gdk = { version = "", features = ["v3_16"] }
|
||||
@ -13,7 +11,6 @@ gio = { version = "", features = ["v2_44"] }
|
||||
glib = { version = "", features = ["v2_44"] }
|
||||
gdk-pixbuf = "0.9"
|
||||
|
||||
|
||||
regex = "1"
|
||||
try_match = "0.2.2"
|
||||
anyhow = "1.0"
|
||||
@ -39,8 +36,5 @@ lazy_static = "1.4.0"
|
||||
libc = "0.2"
|
||||
ref-cast = "1.0"
|
||||
|
||||
#thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "0.6.1"
|
||||
|
||||
|
27
README.md
27
README.md
@ -1,15 +1,12 @@
|
||||
|
||||
# Table of Contents
|
||||
|
||||
* [About](#org4ab08b6)
|
||||
* [Configuration](#org581ca61)
|
||||
* [Example Config](#orgb769597)
|
||||
* [Building](#orgbf66ce2)
|
||||
* [Prerequisites](#org727b3da)
|
||||
* [Installation](#orgdd31739)
|
||||
* [Usage](#org4a9b3c6)
|
||||
|
||||
|
||||
- [About](#org4ab08b6)
|
||||
- [Configuration](#org581ca61)
|
||||
- [Example Config](#orgb769597)
|
||||
- [Building](#orgbf66ce2)
|
||||
- [Prerequisites](#org727b3da)
|
||||
- [Installation](#orgdd31739)
|
||||
- [Usage](#org4a9b3c6)
|
||||
|
||||
<a id="org4ab08b6"></a>
|
||||
|
||||
@ -17,17 +14,16 @@
|
||||
|
||||
Elkowar’s Wacky Widgets is a standalone Widget System made in rust to add AwesomeWM like widgets to any WM
|
||||
|
||||
|
||||
<a id="org581ca61"></a>
|
||||
|
||||
# Configuration
|
||||
|
||||
Eww’s configuration should be placed in `~/.config/eww/eww.xml` and any `scss` styles you want to add should be put into `~/.config/eww/eww.scss`.
|
||||
|
||||
|
||||
<a id="orgb769597"></a>
|
||||
|
||||
## Example Config
|
||||
|
||||
```xml
|
||||
<eww>
|
||||
<definitions>
|
||||
@ -66,17 +62,16 @@ Eww’s configuration should be placed in `~/.config/eww/eww.xml` and any `s
|
||||
|
||||
# Building
|
||||
|
||||
|
||||
<a id="org727b3da"></a>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- cargo with nightly toolchain
|
||||
- rustc
|
||||
- cargo (nightly toolchain)
|
||||
|
||||
Rather than with your system package manager, I recommend installing it using [rustup](https://rustup.rs/),
|
||||
as this makes it easy to use the nightly toolchain, which is necessary to build eww.
|
||||
|
||||
|
||||
<a id="orgdd31739"></a>
|
||||
|
||||
## Installation
|
||||
@ -89,10 +84,8 @@ Build the Binary using -:
|
||||
|
||||
then copy the built binary from `./target/release` to anywhere in `$PATH` (example - `~/.local/bin`)
|
||||
|
||||
|
||||
<a id="org4a9b3c6"></a>
|
||||
|
||||
# Usage
|
||||
|
||||
Create a Config and then just do `eww`!
|
||||
|
||||
|
17
rustfmt.toml
17
rustfmt.toml
@ -1,4 +1,13 @@
|
||||
unstable_features=true
|
||||
fn_single_line=false
|
||||
max_width=130
|
||||
|
||||
unstable_features = true
|
||||
fn_single_line = false
|
||||
max_width = 130
|
||||
reorder_impl_items = true
|
||||
merge_imports = true
|
||||
normalize_comments = true
|
||||
use_field_init_shorthand = true
|
||||
wrap_comments = true
|
||||
combine_control_expr = false
|
||||
condense_wildcard_suffixes = true
|
||||
format_code_in_doc_comments = true
|
||||
format_macro_matchers = true
|
||||
format_strings = true
|
||||
|
@ -3,9 +3,10 @@ use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use std::ops::Range;
|
||||
|
||||
use crate::value::AttrValue;
|
||||
use crate::value::VarName;
|
||||
use crate::with_text_pos_context;
|
||||
use crate::{
|
||||
value::{AttrValue, VarName},
|
||||
with_text_pos_context,
|
||||
};
|
||||
use maplit::hashmap;
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
use crate::util;
|
||||
use crate::value::PrimitiveValue;
|
||||
use crate::value::VarName;
|
||||
use crate::{
|
||||
util,
|
||||
value::{PrimitiveValue, VarName},
|
||||
};
|
||||
use anyhow::*;
|
||||
use derive_more;
|
||||
use element::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::{collections::HashMap, fmt};
|
||||
use util::Coords;
|
||||
use xml_ext::*;
|
||||
|
||||
@ -134,12 +134,15 @@ impl EwwConfig {
|
||||
pub fn get_widgets(&self) -> &HashMap<String, WidgetDefinition> {
|
||||
&self.widgets
|
||||
}
|
||||
|
||||
pub fn get_windows(&self) -> &HashMap<WindowName, EwwWindowDefinition> {
|
||||
&self.windows
|
||||
}
|
||||
|
||||
pub fn get_default_vars(&self) -> &HashMap<VarName, PrimitiveValue> {
|
||||
&self.initial_variables
|
||||
}
|
||||
|
||||
pub fn get_script_vars(&self) -> &Vec<ScriptVar> {
|
||||
&self.script_vars
|
||||
}
|
||||
@ -211,6 +214,7 @@ impl Default for WindowStacking {
|
||||
|
||||
impl std::str::FromStr for WindowStacking {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
|
@ -141,6 +141,7 @@ impl<'a, 'b> XmlElement<'a, 'b> {
|
||||
|
||||
format!("<{} {}>", self.tag_name(), attrs)
|
||||
}
|
||||
|
||||
pub fn tag_name(&self) -> &str {
|
||||
self.0.tag_name().name()
|
||||
}
|
||||
@ -159,6 +160,7 @@ impl<'a, 'b> XmlElement<'a, 'b> {
|
||||
.filter(|child| child.is_element() || (child.is_text() && !child.text().unwrap_or_default().is_blank()))
|
||||
.map(XmlNode::from)
|
||||
}
|
||||
|
||||
pub fn child_elements(&self) -> impl Iterator<Item = XmlElement> {
|
||||
self.0.children().filter(|child| child.is_element()).map(XmlElement)
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
use crate::config::WindowName;
|
||||
use crate::value::VarName;
|
||||
use crate::{config::WindowName, value::VarName};
|
||||
use anyhow::*;
|
||||
use std::collections::HashMap;
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
use std::{collections::HashMap, process::Command, sync::Arc};
|
||||
|
||||
use crate::value::{AttrValue, PrimitiveValue};
|
||||
|
||||
/// Handler that get's executed to apply the necessary parts of the eww state to a gtk widget.
|
||||
/// These are created and initialized in EwwState::resolve.
|
||||
/// Handler that get's executed to apply the necessary parts of the eww state to
|
||||
/// a gtk widget. These are created and initialized in EwwState::resolve.
|
||||
pub struct StateChangeHandler {
|
||||
func: Box<dyn Fn(HashMap<String, PrimitiveValue>) -> Result<()> + 'static>,
|
||||
constant_values: HashMap<String, PrimitiveValue>,
|
||||
@ -57,7 +54,8 @@ impl EwwWindowState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores the actual state of eww, including the variable state and the window-specific state-change handlers.
|
||||
/// Stores the actual state of eww, including the variable state and the
|
||||
/// window-specific state-change handlers.
|
||||
#[derive(Default)]
|
||||
pub struct EwwState {
|
||||
windows: HashMap<WindowName, EwwWindowState>,
|
||||
@ -88,7 +86,8 @@ impl EwwState {
|
||||
self.windows.clear();
|
||||
}
|
||||
|
||||
/// Update the value of a variable, running all registered [StateChangeHandler]s.
|
||||
/// Update the value of a variable, running all registered
|
||||
/// [StateChangeHandler]s.
|
||||
pub fn update_variable(&mut self, key: VarName, value: PrimitiveValue) -> Result<()> {
|
||||
if !self.variables_state.contains_key(&key) {
|
||||
bail!("Tried to set unknown variable '{}'", key);
|
||||
@ -111,7 +110,8 @@ impl EwwState {
|
||||
|
||||
/// resolves a value if possible, using the current eww_state
|
||||
/// Expects there to be at max one level of nesting var_refs from local-env.
|
||||
/// This means that no elements in the local_env may be var-refs into the local_env again, but only into the global state.
|
||||
/// This means that no elements in the local_env may be var-refs into the
|
||||
/// local_env again, but only into the global state.
|
||||
pub fn resolve_once<'a>(
|
||||
&'a self,
|
||||
local_env: &'a HashMap<VarName, AttrValue>,
|
||||
@ -134,9 +134,11 @@ impl EwwState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve takes a function that applies a set of fully resolved attribute values to it's gtk widget.
|
||||
/// Expects there to be at max one level of nesting var_refs from local-env.
|
||||
/// This means that no elements in the local_env may be var-refs into the local_env again, but only into the global state.
|
||||
/// Resolve takes a function that applies a set of fully resolved attribute
|
||||
/// values to it's gtk widget. Expects there to be at max one level of
|
||||
/// nesting var_refs from local-env. This means that no elements in the
|
||||
/// local_env may be var-refs into the local_env again, but only into the
|
||||
/// global state.
|
||||
pub fn resolve<F: Fn(HashMap<String, PrimitiveValue>) -> Result<()> + 'static + Clone>(
|
||||
&mut self,
|
||||
window_name: &WindowName,
|
||||
@ -144,9 +146,11 @@ impl EwwState {
|
||||
mut needed_attributes: HashMap<String, AttrValue>,
|
||||
set_value: F,
|
||||
) {
|
||||
// Resolve first collects all variable references and creates a set of unresolved attribute -> VarName pairs.
|
||||
// additionally, all constant values are looked up and collected, including the values from the local environment
|
||||
// These are then used to generate a StateChangeHandler, which is then executed and registered in the windows state.
|
||||
// Resolve first collects all variable references and creates a set of
|
||||
// unresolved attribute -> VarName pairs. additionally, all constant values are
|
||||
// looked up and collected, including the values from the local environment
|
||||
// These are then used to generate a StateChangeHandler, which is then executed
|
||||
// and registered in the windows state.
|
||||
|
||||
let result: Result<_> = try {
|
||||
let window_state = self
|
||||
|
14
src/main.rs
14
src/main.rs
@ -16,11 +16,12 @@ use ipc_channel::ipc;
|
||||
use log;
|
||||
use pretty_env_logger;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use structopt::StructOpt;
|
||||
use value::PrimitiveValue;
|
||||
use value::VarName;
|
||||
use value::{PrimitiveValue, VarName};
|
||||
|
||||
pub mod app;
|
||||
pub mod config;
|
||||
@ -221,7 +222,8 @@ fn run_filewatch_thread<P: AsRef<Path>>(
|
||||
Ok(hotwatch)
|
||||
}
|
||||
|
||||
/// detach the process from the terminal, also closing stdout and redirecting stderr into /dev/null
|
||||
/// detach the process from the terminal, also closing stdout and redirecting
|
||||
/// stderr into /dev/null
|
||||
fn do_detach() {
|
||||
// detach from terminal
|
||||
let pid = unsafe { libc::fork() };
|
||||
@ -238,7 +240,7 @@ fn do_detach() {
|
||||
libc::close(1);
|
||||
}
|
||||
}
|
||||
//close stderr to not spam output
|
||||
// close stderr to not spam output
|
||||
if unsafe { libc::isatty(2) } != 0 {
|
||||
unsafe {
|
||||
let fd = libc::open(std::ffi::CString::new("/dev/null").unwrap().as_ptr(), libc::O_RDWR);
|
||||
|
@ -19,7 +19,8 @@ impl ScriptVarHandler {
|
||||
})
|
||||
}
|
||||
|
||||
/// clears and stops the currently running poll handles, then opens the new ones as configured
|
||||
/// clears and stops the currently running poll handles, then opens the new
|
||||
/// ones as configured
|
||||
pub fn setup_command_poll_tasks(&mut self, config: &config::EwwConfig) -> Result<()> {
|
||||
log::info!("reloading handler for poll script vars");
|
||||
self.poll_handles.iter().for_each(|handle| handle.stop());
|
||||
|
@ -3,8 +3,7 @@ use extend::ext;
|
||||
use grass;
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
use std::{fmt, path::Path};
|
||||
|
||||
pub fn parse_scss_from_file<P: AsRef<Path>>(path: P) -> Result<String> {
|
||||
let scss_content = std::fs::read_to_string(path)?;
|
||||
@ -14,7 +13,8 @@ pub fn parse_scss_from_file<P: AsRef<Path>>(path: P) -> Result<String> {
|
||||
|
||||
#[ext(pub, name = StringExt)]
|
||||
impl<T: AsRef<str>> T {
|
||||
/// check if the string is empty after removing all linebreaks and trimming whitespace
|
||||
/// check if the string is empty after removing all linebreaks and trimming
|
||||
/// whitespace
|
||||
fn is_blank(self) -> bool {
|
||||
self.as_ref().replace('\n', "").trim().is_empty()
|
||||
}
|
||||
@ -51,6 +51,7 @@ impl fmt::Display for Coords {
|
||||
|
||||
impl std::str::FromStr for Coords {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
let (x, y) = s.split_once('x').ok_or_else(|| anyhow!("must be formatted like 200x500"))?;
|
||||
Ok(Coords(x.parse()?, y.parse()?))
|
||||
|
17
src/value.rs
17
src/value.rs
@ -4,8 +4,7 @@ use lazy_static::lazy_static;
|
||||
use ref_cast::RefCast;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::{convert::TryFrom, fmt};
|
||||
|
||||
#[derive(Clone, PartialEq, Deserialize, Serialize, derive_more::From)]
|
||||
pub enum PrimitiveValue {
|
||||
@ -32,7 +31,8 @@ impl fmt::Debug for PrimitiveValue {
|
||||
impl std::str::FromStr for PrimitiveValue {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
/// parses the value, trying to turn it into a number and a boolean first, before deciding that it is a string.
|
||||
/// parses the value, trying to turn it into a number and a boolean first,
|
||||
/// before deciding that it is a string.
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
Ok(PrimitiveValue::parse_string(s))
|
||||
}
|
||||
@ -44,6 +44,7 @@ fn remove_surrounding(s: &str, surround: char) -> &str {
|
||||
|
||||
impl TryFrom<PrimitiveValue> for String {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(x: PrimitiveValue) -> Result<Self> {
|
||||
x.as_string()
|
||||
}
|
||||
@ -51,6 +52,7 @@ impl TryFrom<PrimitiveValue> for String {
|
||||
|
||||
impl TryFrom<PrimitiveValue> for f64 {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(x: PrimitiveValue) -> Result<Self> {
|
||||
x.as_f64()
|
||||
}
|
||||
@ -58,6 +60,7 @@ impl TryFrom<PrimitiveValue> for f64 {
|
||||
|
||||
impl TryFrom<PrimitiveValue> for bool {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(x: PrimitiveValue) -> Result<Self> {
|
||||
x.as_bool()
|
||||
}
|
||||
@ -70,13 +73,15 @@ impl From<&str> for PrimitiveValue {
|
||||
}
|
||||
|
||||
impl PrimitiveValue {
|
||||
/// parses the value, trying to turn it into a number and a boolean first, before deciding that it is a string.
|
||||
/// parses the value, trying to turn it into a number and a boolean first,
|
||||
/// before deciding that it is a string.
|
||||
pub fn parse_string(s: &str) -> Self {
|
||||
s.parse()
|
||||
.map(PrimitiveValue::Number)
|
||||
.or_else(|_| s.parse().map(PrimitiveValue::Boolean))
|
||||
.unwrap_or_else(|_| PrimitiveValue::String(remove_surrounding(s, '\'').to_string()))
|
||||
}
|
||||
|
||||
pub fn as_string(&self) -> Result<String> {
|
||||
match self {
|
||||
PrimitiveValue::String(x) => Ok(x.clone()),
|
||||
@ -84,6 +89,7 @@ impl PrimitiveValue {
|
||||
PrimitiveValue::Boolean(x) => Ok(format!("{}", x)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_f64(&self) -> Result<f64> {
|
||||
match self {
|
||||
PrimitiveValue::Number(x) => Ok(*x),
|
||||
@ -93,6 +99,7 @@ impl PrimitiveValue {
|
||||
_ => Err(anyhow!("{:?} is not an f64", &self)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_bool(&self) -> Result<bool> {
|
||||
match self {
|
||||
PrimitiveValue::Boolean(x) => Ok(*x),
|
||||
@ -145,12 +152,14 @@ impl AttrValue {
|
||||
_ => Err(anyhow!("{:?} is not a string", self)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_f64(&self) -> Result<f64> {
|
||||
match self {
|
||||
AttrValue::Concrete(x) => Ok(x.as_f64()?),
|
||||
_ => Err(anyhow!("{:?} is not an f64", self)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_bool(&self) -> Result<bool> {
|
||||
match self {
|
||||
AttrValue::Concrete(x) => Ok(x.as_bool()?),
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::config::{element, WindowName};
|
||||
use crate::eww_state::*;
|
||||
use crate::value::{AttrValue, VarName};
|
||||
use crate::{
|
||||
config::{element, WindowName},
|
||||
eww_state::*,
|
||||
value::{AttrValue, VarName},
|
||||
};
|
||||
use anyhow::*;
|
||||
use gtk::prelude::*;
|
||||
|
||||
@ -11,8 +13,8 @@ pub mod widget_definitions;
|
||||
|
||||
const CMD_STRING_PLACEHODLER: &str = "{}";
|
||||
|
||||
/// Run a command that was provided as an attribute. This command may use a placeholder ('{}')
|
||||
/// which will be replaced by the value provided as [arg]
|
||||
/// Run a command that was provided as an attribute. This command may use a
|
||||
/// placeholder ('{}') which will be replaced by the value provided as [arg]
|
||||
pub fn run_command<T: std::fmt::Display>(cmd: &str, arg: T) {
|
||||
let cmd = cmd.replace(CMD_STRING_PLACEHODLER, &format!("{}", arg));
|
||||
if let Err(e) = Command::new("bash").arg("-c").arg(cmd).output() {
|
||||
@ -30,12 +32,14 @@ struct BuilderArgs<'a, 'b, 'c, 'd, 'e> {
|
||||
}
|
||||
|
||||
/// Generate a [gtk::Widget] from a [element::WidgetUse].
|
||||
/// The widget_use may be using a builtin widget, or a custom [element::WidgetDefinition].
|
||||
/// The widget_use may be using a builtin widget, or a custom
|
||||
/// [element::WidgetDefinition].
|
||||
///
|
||||
/// Also registers all the necessary state-change handlers in the eww_state.
|
||||
///
|
||||
/// This may return `Err` in case there was an actual error while parsing or resolving the widget,
|
||||
/// Or `Ok(None)` if the widget_use just didn't match any widget name.
|
||||
/// This may return `Err` in case there was an actual error while parsing or
|
||||
/// resolving the widget, Or `Ok(None)` if the widget_use just didn't match any
|
||||
/// widget name.
|
||||
pub fn widget_use_to_gtk_widget(
|
||||
widget_definitions: &HashMap<String, element::WidgetDefinition>,
|
||||
eww_state: &mut EwwState,
|
||||
@ -48,18 +52,20 @@ pub fn widget_use_to_gtk_widget(
|
||||
let gtk_widget = if let Some(builtin_gtk_widget) = builtin_gtk_widget {
|
||||
builtin_gtk_widget
|
||||
} else if let Some(def) = widget_definitions.get(widget.name.as_str()) {
|
||||
//let mut local_env = local_env.clone();
|
||||
// let mut local_env = local_env.clone();
|
||||
|
||||
// the attributes that are set on the widget need to be resolved as far as possible.
|
||||
// If an attribute is a variable reference, it must either reference a variable in the current local_env, or in the global state.
|
||||
// As we are building widgets from the outer most to the most nested, we can resolve attributes at every step.
|
||||
// This way, any definition that is affected by changes in the eww_state will be directly linked to the eww_state's value.
|
||||
// Example:
|
||||
// foo="{{in_eww_state}}" => attr_in_child="{{foo}}" => attr_in_nested_child="{{attr_in_child}}"
|
||||
// will be resolved step by step. This code will first resolve attr_in_child to directly be attr_in_child={{in_eww_state}}.
|
||||
// then, in the widget_use_to_gtk_widget call of that child element,
|
||||
// attr_in_nested_child will again be resolved to point to the value of attr_in_child,
|
||||
// and thus: attr_in_nested_child="{{in_eww_state}}"
|
||||
// the attributes that are set on the widget need to be resolved as far as
|
||||
// possible. If an attribute is a variable reference, it must either reference a
|
||||
// variable in the current local_env, or in the global state. As we are building
|
||||
// widgets from the outer most to the most nested, we can resolve attributes at
|
||||
// every step. This way, any definition that is affected by changes in the
|
||||
// eww_state will be directly linked to the eww_state's value. Example:
|
||||
// foo="{{in_eww_state}}" => attr_in_child="{{foo}}" =>
|
||||
// attr_in_nested_child="{{attr_in_child}}" will be resolved step by step. This
|
||||
// code will first resolve attr_in_child to directly be
|
||||
// attr_in_child={{in_eww_state}}. then, in the widget_use_to_gtk_widget call of
|
||||
// that child element, attr_in_nested_child will again be resolved to point to
|
||||
// the value of attr_in_child, and thus: attr_in_nested_child="{{in_eww_state}}"
|
||||
let resolved_widget_attr_env = widget
|
||||
.attrs
|
||||
.clone()
|
||||
@ -93,13 +99,14 @@ pub fn widget_use_to_gtk_widget(
|
||||
Ok(gtk_widget)
|
||||
}
|
||||
|
||||
/// build a [gtk::Widget] out of a [element::WidgetUse] that uses a **builtin widget**.
|
||||
/// User defined widgets are handled by [widget_use_to_gtk_widget].
|
||||
/// build a [gtk::Widget] out of a [element::WidgetUse] that uses a **builtin
|
||||
/// widget**. User defined widgets are handled by [widget_use_to_gtk_widget].
|
||||
///
|
||||
/// Also registers all the necessary handlers in the `eww_state`.
|
||||
///
|
||||
/// This may return `Err` in case there was an actual error while parsing or resolving the widget,
|
||||
/// Or `Ok(None)` if the widget_use just didn't match any widget name.
|
||||
/// This may return `Err` in case there was an actual error while parsing or
|
||||
/// resolving the widget, Or `Ok(None)` if the widget_use just didn't match any
|
||||
/// widget name.
|
||||
fn build_builtin_gtk_widget(
|
||||
widget_definitions: &HashMap<String, element::WidgetDefinition>,
|
||||
eww_state: &mut EwwState,
|
||||
|
@ -1,15 +1,12 @@
|
||||
use super::{run_command, BuilderArgs};
|
||||
use crate::config;
|
||||
use crate::eww_state;
|
||||
use crate::resolve_block;
|
||||
use crate::value::{AttrValue, PrimitiveValue};
|
||||
use crate::{
|
||||
config, eww_state, resolve_block,
|
||||
value::{AttrValue, PrimitiveValue},
|
||||
};
|
||||
use anyhow::*;
|
||||
use gtk::prelude::*;
|
||||
use gtk::ImageExt;
|
||||
use gtk::{prelude::*, ImageExt};
|
||||
use maplit::hashmap;
|
||||
use std::cell::RefCell;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use std::{cell::RefCell, path::Path, rc::Rc};
|
||||
|
||||
use gdk_pixbuf;
|
||||
|
||||
@ -259,7 +256,8 @@ fn parse_align(o: &str) -> Result<gtk::Align> {
|
||||
}
|
||||
|
||||
fn connect_first_map<W: IsA<gtk::Widget>, F: Fn(&W) + 'static>(widget: &W, func: F) {
|
||||
// TODO it would be better to actually remove the connect_map after first map, but that would be highly annoying to implement...
|
||||
// TODO it would be better to actually remove the connect_map after first map,
|
||||
// but that would be highly annoying to implement...
|
||||
let is_first_map = std::rc::Rc::new(std::cell::RefCell::new(true));
|
||||
widget.connect_map(move |w| {
|
||||
if is_first_map.replace(false) {
|
||||
|
Loading…
Reference in New Issue
Block a user