diff --git a/src/app.rs b/src/app.rs index e69cc27..a2c9404 100644 --- a/src/app.rs +++ b/src/app.rs @@ -247,7 +247,10 @@ impl App { let mut window_def = self.eww_config.get_window(window_name)?.clone(); window_def.geometry = window_def.geometry.override_if_given(anchor, pos, size); - let root_widget = window_def.widget.render(&mut self.eww_state, window_name)?; + let root_widget = + window_def + .widget + .render(&mut self.eww_state, window_name, &self.eww_config.get_widget_definitions())?; root_widget.get_style_context().add_class(&window_name.to_string()); let monitor_geometry = get_monitor_geometry(window_def.screen_number.unwrap_or_else(get_default_monitor_index)); diff --git a/src/config/eww_config.rs b/src/config/eww_config.rs index 100ab99..7b11bf5 100644 --- a/src/config/eww_config.rs +++ b/src/config/eww_config.rs @@ -16,6 +16,7 @@ use std::path::PathBuf; /// Eww configuration structure. #[derive(Debug, Clone)] pub struct EwwConfig { + widgets: HashMap, windows: HashMap, initial_variables: HashMap, script_vars: HashMap, @@ -35,9 +36,6 @@ impl EwwConfig { widgets, } = conf; Ok(EwwConfig { - initial_variables, - script_vars, - filepath, windows: windows .into_iter() .map(|(name, window)| { @@ -47,6 +45,10 @@ impl EwwConfig { )) }) .collect::>>()?, + widgets, + initial_variables, + script_vars, + filepath, }) } @@ -76,6 +78,10 @@ impl EwwConfig { .get(name) .with_context(|| format!("No script var named '{}' exists", name)) } + + pub fn get_widget_definitions(&self) -> &HashMap { + &self.widgets + } } /// Raw Eww configuration, before expanding widget usages. diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 64659d3..15e6c04 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -1,7 +1,12 @@ -use crate::{config::window_definition::WindowName, eww_state::*, value::AttrName}; +use crate::{ + config::{element::WidgetDefinition, window_definition::WindowName}, + eww_state::*, + value::AttrName, +}; use anyhow::*; use gtk::prelude::*; use itertools::Itertools; +use std::collections::HashMap; use std::process::Command; use widget_definitions::*; @@ -36,11 +41,12 @@ pub(self) fn run_command(cmd: &str }); } -struct BuilderArgs<'a, 'b, 'c, 'd> { +struct BuilderArgs<'a, 'b, 'c, 'd, 'e> { eww_state: &'a mut EwwState, widget: &'b widget_node::Generic, unhandled_attrs: Vec<&'c AttrName>, window_name: &'d WindowName, + widget_definitions: &'e HashMap, } /// build a [`gtk::Widget`] out of a [`element::WidgetUse`] that uses a @@ -55,6 +61,7 @@ struct BuilderArgs<'a, 'b, 'c, 'd> { fn build_builtin_gtk_widget( eww_state: &mut EwwState, window_name: &WindowName, + widget_definitions: &HashMap, widget: &widget_node::Generic, ) -> Result> { let mut bargs = BuilderArgs { @@ -62,6 +69,7 @@ fn build_builtin_gtk_widget( widget, window_name, unhandled_attrs: widget.attrs.keys().collect(), + widget_definitions, }; let gtk_widget = match widget_to_gtk_widget(&mut bargs) { Ok(Some(gtk_widget)) => gtk_widget, @@ -81,14 +89,16 @@ fn build_builtin_gtk_widget( if let Some(gtk_widget) = gtk_widget.dynamic_cast_ref::() { resolve_container_attrs(&mut bargs, >k_widget); for child in &widget.children { - let child_widget = child.render(bargs.eww_state, window_name).with_context(|| { - format!( - "{}error while building child '{:#?}' of '{}'", - widget.text_pos.map(|x| format!("{} |", x)).unwrap_or_default(), - &child, - >k_widget.get_widget_name() - ) - })?; + let child_widget = child + .render(bargs.eww_state, window_name, widget_definitions) + .with_context(|| { + format!( + "{}error while building child '{:#?}' of '{}'", + widget.text_pos.map(|x| format!("{} |", x)).unwrap_or_default(), + &child, + >k_widget.get_widget_name() + ) + })?; gtk_widget.add(&child_widget); child_widget.show(); } diff --git a/src/widgets/widget_definitions.rs b/src/widgets/widget_definitions.rs index b7f97d6..2be85bc 100644 --- a/src/widgets/widget_definitions.rs +++ b/src/widgets/widget_definitions.rs @@ -410,6 +410,7 @@ fn build_gtk_literal(bargs: &mut BuilderArgs) -> Result { // TODO these clones here are dumdum let window_name = bargs.window_name.clone(); + let widget_definitions = bargs.widget_definitions.clone(); resolve_block!(bargs, gtk_widget, { // @prop content - inline Eww XML that will be rendered as a widget. prop(content: as_string) { @@ -418,8 +419,8 @@ fn build_gtk_literal(bargs: &mut BuilderArgs) -> Result { let document = roxmltree::Document::parse(&content).map_err(|e| anyhow!("Failed to parse eww xml literal: {:?}", e))?; let content_widget_use = config::element::WidgetUse::from_xml_node(document.root_element().into())?; - let widget_node = &*widget_node::generate_generic_widget_node(&HashMap::new(), &HashMap::new(), content_widget_use)?; - let child_widget = widget_node.render( &mut eww_state::EwwState::default(), &window_name)?; + let widget_node = &*widget_node::generate_generic_widget_node(&widget_definitions, &HashMap::new(), content_widget_use)?; + let child_widget = widget_node.render(&mut eww_state::EwwState::default(), &window_name, &widget_definitions)?; gtk_widget.add(&child_widget); child_widget.show(); } diff --git a/src/widgets/widget_node.rs b/src/widgets/widget_node.rs index a43263c..e305e0f 100644 --- a/src/widgets/widget_node.rs +++ b/src/widgets/widget_node.rs @@ -20,7 +20,12 @@ pub trait WidgetNode: std::fmt::Debug + dyn_clone::DynClone + Send + Sync { /// 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 render(&self, eww_state: &mut EwwState, window_name: &WindowName) -> Result; + fn render( + &self, + eww_state: &mut EwwState, + window_name: &WindowName, + widget_definitions: &HashMap, + ) -> Result; } dyn_clone::clone_trait_object!(WidgetNode); @@ -41,8 +46,13 @@ impl WidgetNode for UserDefined { self.text_pos.as_ref() } - fn render(&self, eww_state: &mut EwwState, window_name: &WindowName) -> Result { - self.content.render(eww_state, window_name) + fn render( + &self, + eww_state: &mut EwwState, + window_name: &WindowName, + widget_definitions: &HashMap, + ) -> Result { + self.content.render(eww_state, window_name, widget_definitions) } } @@ -76,9 +86,16 @@ impl WidgetNode for Generic { self.text_pos.as_ref() } - fn render(&self, eww_state: &mut EwwState, window_name: &WindowName) -> Result { - Ok(crate::widgets::build_builtin_gtk_widget(eww_state, window_name, &self)? - .with_context(|| format!("Unknown widget '{}'", self.get_name()))?) + fn render( + &self, + eww_state: &mut EwwState, + window_name: &WindowName, + widget_definitions: &HashMap, + ) -> Result { + Ok( + crate::widgets::build_builtin_gtk_widget(eww_state, window_name, widget_definitions, &self)? + .with_context(|| format!("Unknown widget '{}'", self.get_name()))?, + ) } }