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();
|
let mut window_def = self.eww_config.get_window(window_name)?.clone();
|
||||||
window_def.geometry = window_def.geometry.override_if_given(anchor, pos, size);
|
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());
|
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));
|
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.
|
/// Eww configuration structure.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct EwwConfig {
|
pub struct EwwConfig {
|
||||||
|
widgets: HashMap<String, WidgetDefinition>,
|
||||||
windows: HashMap<WindowName, EwwWindowDefinition>,
|
windows: HashMap<WindowName, EwwWindowDefinition>,
|
||||||
initial_variables: HashMap<VarName, PrimitiveValue>,
|
initial_variables: HashMap<VarName, PrimitiveValue>,
|
||||||
script_vars: HashMap<VarName, ScriptVar>,
|
script_vars: HashMap<VarName, ScriptVar>,
|
||||||
|
@ -35,9 +36,6 @@ impl EwwConfig {
|
||||||
widgets,
|
widgets,
|
||||||
} = conf;
|
} = conf;
|
||||||
Ok(EwwConfig {
|
Ok(EwwConfig {
|
||||||
initial_variables,
|
|
||||||
script_vars,
|
|
||||||
filepath,
|
|
||||||
windows: windows
|
windows: windows
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(name, window)| {
|
.map(|(name, window)| {
|
||||||
|
@ -47,6 +45,10 @@ impl EwwConfig {
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.collect::<Result<HashMap<_, _>>>()?,
|
.collect::<Result<HashMap<_, _>>>()?,
|
||||||
|
widgets,
|
||||||
|
initial_variables,
|
||||||
|
script_vars,
|
||||||
|
filepath,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +78,10 @@ impl EwwConfig {
|
||||||
.get(name)
|
.get(name)
|
||||||
.with_context(|| format!("No script var named '{}' exists", 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.
|
/// 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 anyhow::*;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use widget_definitions::*;
|
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,
|
eww_state: &'a mut EwwState,
|
||||||
widget: &'b widget_node::Generic,
|
widget: &'b widget_node::Generic,
|
||||||
unhandled_attrs: Vec<&'c AttrName>,
|
unhandled_attrs: Vec<&'c AttrName>,
|
||||||
window_name: &'d WindowName,
|
window_name: &'d WindowName,
|
||||||
|
widget_definitions: &'e HashMap<String, WidgetDefinition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// build a [`gtk::Widget`] out of a [`element::WidgetUse`] that uses a
|
/// 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(
|
fn build_builtin_gtk_widget(
|
||||||
eww_state: &mut EwwState,
|
eww_state: &mut EwwState,
|
||||||
window_name: &WindowName,
|
window_name: &WindowName,
|
||||||
|
widget_definitions: &HashMap<String, WidgetDefinition>,
|
||||||
widget: &widget_node::Generic,
|
widget: &widget_node::Generic,
|
||||||
) -> Result<Option<gtk::Widget>> {
|
) -> Result<Option<gtk::Widget>> {
|
||||||
let mut bargs = BuilderArgs {
|
let mut bargs = BuilderArgs {
|
||||||
|
@ -62,6 +69,7 @@ fn build_builtin_gtk_widget(
|
||||||
widget,
|
widget,
|
||||||
window_name,
|
window_name,
|
||||||
unhandled_attrs: widget.attrs.keys().collect(),
|
unhandled_attrs: widget.attrs.keys().collect(),
|
||||||
|
widget_definitions,
|
||||||
};
|
};
|
||||||
let gtk_widget = match widget_to_gtk_widget(&mut bargs) {
|
let gtk_widget = match widget_to_gtk_widget(&mut bargs) {
|
||||||
Ok(Some(gtk_widget)) => gtk_widget,
|
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>() {
|
if let Some(gtk_widget) = gtk_widget.dynamic_cast_ref::<gtk::Container>() {
|
||||||
resolve_container_attrs(&mut bargs, >k_widget);
|
resolve_container_attrs(&mut bargs, >k_widget);
|
||||||
for child in &widget.children {
|
for child in &widget.children {
|
||||||
let child_widget = child.render(bargs.eww_state, window_name).with_context(|| {
|
let child_widget = child
|
||||||
format!(
|
.render(bargs.eww_state, window_name, widget_definitions)
|
||||||
"{}error while building child '{:#?}' of '{}'",
|
.with_context(|| {
|
||||||
widget.text_pos.map(|x| format!("{} |", x)).unwrap_or_default(),
|
format!(
|
||||||
&child,
|
"{}error while building child '{:#?}' of '{}'",
|
||||||
>k_widget.get_widget_name()
|
widget.text_pos.map(|x| format!("{} |", x)).unwrap_or_default(),
|
||||||
)
|
&child,
|
||||||
})?;
|
>k_widget.get_widget_name()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
gtk_widget.add(&child_widget);
|
gtk_widget.add(&child_widget);
|
||||||
child_widget.show();
|
child_widget.show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -410,6 +410,7 @@ fn build_gtk_literal(bargs: &mut BuilderArgs) -> Result<gtk::Box> {
|
||||||
|
|
||||||
// TODO these clones here are dumdum
|
// TODO these clones here are dumdum
|
||||||
let window_name = bargs.window_name.clone();
|
let window_name = bargs.window_name.clone();
|
||||||
|
let widget_definitions = bargs.widget_definitions.clone();
|
||||||
resolve_block!(bargs, gtk_widget, {
|
resolve_block!(bargs, gtk_widget, {
|
||||||
// @prop content - inline Eww XML that will be rendered as a widget.
|
// @prop content - inline Eww XML that will be rendered as a widget.
|
||||||
prop(content: as_string) {
|
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 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 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 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)?;
|
let child_widget = widget_node.render(&mut eww_state::EwwState::default(), &window_name, &widget_definitions)?;
|
||||||
gtk_widget.add(&child_widget);
|
gtk_widget.add(&child_widget);
|
||||||
child_widget.show();
|
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
|
/// 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
|
/// resolving the widget, Or `Ok(None)` if the widget_use just didn't match any
|
||||||
/// widget name.
|
/// 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);
|
dyn_clone::clone_trait_object!(WidgetNode);
|
||||||
|
@ -41,8 +46,13 @@ impl WidgetNode for UserDefined {
|
||||||
self.text_pos.as_ref()
|
self.text_pos.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, eww_state: &mut EwwState, window_name: &WindowName) -> Result<gtk::Widget> {
|
fn render(
|
||||||
self.content.render(eww_state, window_name)
|
&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()
|
self.text_pos.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, eww_state: &mut EwwState, window_name: &WindowName) -> Result<gtk::Widget> {
|
fn render(
|
||||||
Ok(crate::widgets::build_builtin_gtk_widget(eww_state, window_name, &self)?
|
&self,
|
||||||
.with_context(|| format!("Unknown widget '{}'", self.get_name()))?)
|
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