Allow literal-tag content to use user-defined widgets
This commit is contained in:
parent
c37c5b3cf3
commit
0c762de864
5 changed files with 59 additions and 22 deletions
|
@ -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));
|
||||
|
|
|
@ -16,6 +16,7 @@ use std::path::PathBuf;
|
|||
/// Eww configuration structure.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EwwConfig {
|
||||
widgets: HashMap<String, WidgetDefinition>,
|
||||
windows: HashMap<WindowName, EwwWindowDefinition>,
|
||||
initial_variables: HashMap<VarName, PrimitiveValue>,
|
||||
script_vars: HashMap<VarName, ScriptVar>,
|
||||
|
@ -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::<Result<HashMap<_, _>>>()?,
|
||||
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<String, WidgetDefinition> {
|
||||
&self.widgets
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw Eww configuration, before expanding widget usages.
|
||||
|
|
|
@ -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<T: 'static + std::fmt::Display + Send + Sync>(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<String, WidgetDefinition>,
|
||||
}
|
||||
|
||||
/// 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<String, WidgetDefinition>,
|
||||
widget: &widget_node::Generic,
|
||||
) -> Result<Option<gtk::Widget>> {
|
||||
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::<gtk::Container>() {
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -410,6 +410,7 @@ fn build_gtk_literal(bargs: &mut BuilderArgs) -> Result<gtk::Box> {
|
|||
|
||||
// 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<gtk::Box> {
|
|||
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();
|
||||
}
|
||||
|
|
|
@ -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<gtk::Widget>;
|
||||
fn render(
|
||||
&self,
|
||||
eww_state: &mut EwwState,
|
||||
window_name: &WindowName,
|
||||
widget_definitions: &HashMap<String, WidgetDefinition>,
|
||||
) -> Result<gtk::Widget>;
|
||||
}
|
||||
|
||||
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<gtk::Widget> {
|
||||
self.content.render(eww_state, window_name)
|
||||
fn render(
|
||||
&self,
|
||||
eww_state: &mut EwwState,
|
||||
window_name: &WindowName,
|
||||
widget_definitions: &HashMap<String, WidgetDefinition>,
|
||||
) -> Result<gtk::Widget> {
|
||||
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<gtk::Widget> {
|
||||
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<String, WidgetDefinition>,
|
||||
) -> Result<gtk::Widget> {
|
||||
Ok(
|
||||
crate::widgets::build_builtin_gtk_widget(eww_state, window_name, widget_definitions, &self)?
|
||||
.with_context(|| format!("Unknown widget '{}'", self.get_name()))?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue