diff --git a/dash-frontend/assets/gui/view/audio_settings.xml b/dash-frontend/assets/gui/view/audio_settings.xml
index a6a4b887..e1dbabc2 100644
--- a/dash-frontend/assets/gui/view/audio_settings.xml
+++ b/dash-frontend/assets/gui/view/audio_settings.xml
@@ -1,16 +1,16 @@
-
+
-
+
-
+
@@ -41,7 +41,7 @@
flex_grow="1"
id="${id}"
translation="${translation}"
- sprite_src="${src}">
+ sprite_src_builtin="${src}">
@@ -67,4 +67,4 @@
-
\ No newline at end of file
+
diff --git a/dash-frontend/src/tab/apps.rs b/dash-frontend/src/tab/apps.rs
index cd2a5150..7e17ff39 100644
--- a/dash-frontend/src/tab/apps.rs
+++ b/dash-frontend/src/tab/apps.rs
@@ -286,7 +286,7 @@ impl AppList {
let mut params = HashMap::, Rc>::new();
params.insert("text".into(), category_name.into());
- parser_state.parse_template(
+ parser_state.realize_template(
doc_params,
"CategoryText",
&mut frontend.layout,
@@ -318,7 +318,7 @@ impl AppList {
);
params.insert("name".into(), entry.app_name.clone());
- let data = parser_state.parse_template(
+ let data = parser_state.realize_template(
doc_params,
"AppEntry",
&mut frontend.layout,
diff --git a/dash-frontend/src/tab/monado.rs b/dash-frontend/src/tab/monado.rs
index c65861b9..0f714306 100644
--- a/dash-frontend/src/tab/monado.rs
+++ b/dash-frontend/src/tab/monado.rs
@@ -12,7 +12,7 @@ use wgui::{
drawing::Color,
globals::WguiGlobals,
layout::{Layout, WidgetID},
- parser::{self, Fetchable, ParseDocumentParams, ParserData, ParserState},
+ parser::{self, Fetchable, ParseDocumentParams, ParserState},
task::Tasks,
};
use wlx_common::dash_interface::{self, MonadoDumpSessionFrame};
@@ -66,15 +66,11 @@ struct SubtabGeneralSettings {
struct DebugGraph {
graph: Rc,
- #[allow(dead_code)]
- data: ParserData,
}
struct DebugSessionList {
#[allow(dead_code)]
buttons: Vec>,
- #[allow(dead_code)]
- data_vec: Vec,
}
struct TimingsSession {
@@ -288,7 +284,6 @@ fn mount_sessions_list(
sessions: &SessionsMap,
) -> anyhow::Result {
let mut buttons = Vec::new();
- let mut data_vec = Vec::new();
let globals = layout.state.globals.clone();
layout.remove_children(id_parent);
@@ -304,7 +299,7 @@ fn mount_sessions_list(
)),
);
- let data = state.parse_template(
+ let data = state.realize_template(
&doc_params_tab_debug_timings(&globals),
"SessionButton",
layout,
@@ -324,10 +319,9 @@ fn mount_sessions_list(
});
buttons.push(button);
- data_vec.push(data);
}
- Ok(DebugSessionList { buttons, data_vec })
+ Ok(DebugSessionList { buttons })
}
fn mount_graph(
@@ -343,7 +337,7 @@ fn mount_graph(
params.insert(Rc::from("limit_min"), Rc::from(limits.0.to_string()));
params.insert(Rc::from("limit_max"), Rc::from(limits.1.to_string()));
- let data = state.parse_template(
+ let data = state.realize_template(
&doc_params_tab_debug_timings(&globals),
"DebugGraph",
layout,
@@ -352,7 +346,7 @@ fn mount_graph(
)?;
let graph = data.fetch_component_as::("graph")?;
- Ok(DebugGraph { graph, data })
+ Ok(DebugGraph { graph })
}
fn ns_to_ms(ns: i64) -> f32 {
@@ -585,7 +579,7 @@ impl SubtabProcessList {
let globals = layout.state.globals.clone();
- let state_cell = self.state.parse_template(
+ let state_cell = self.state.realize_template(
&doc_params_tab_process_list(&globals),
"Cell",
layout,
diff --git a/dash-frontend/src/views/audio_settings.rs b/dash-frontend/src/views/audio_settings.rs
index f2c43f45..61061d33 100644
--- a/dash-frontend/src/views/audio_settings.rs
+++ b/dash-frontend/src/views/audio_settings.rs
@@ -750,7 +750,7 @@ impl View {
let data = self
.state
- .parse_template(&doc_params(&self.globals), "Card", params.layout, self.id_devices, par)?;
+ .realize_template(&doc_params(&self.globals), "Card", params.layout, self.id_devices, par)?;
let btn_card = data.fetch_component_as::("btn_card")?;
btn_card.on_click({
@@ -764,7 +764,6 @@ impl View {
})
});
- log::info!("mount card TODO: {}", params.card.name);
Ok(())
}
@@ -794,7 +793,7 @@ impl View {
},
);
- let data = self.state.parse_template(
+ let data = self.state.realize_template(
&doc_params(&self.globals),
"DeviceSlider",
params.layout,
@@ -941,7 +940,7 @@ impl View {
layout.remove_children(self.id_devices);
{
- let data = self.state.parse_template(
+ let data = self.state.realize_template(
&doc_params(&self.globals),
"SelectAudioProfileText",
layout,
diff --git a/dash-frontend/src/views/running_games_list.rs b/dash-frontend/src/views/running_games_list.rs
index 19f96911..6428f5d1 100644
--- a/dash-frontend/src/views/running_games_list.rs
+++ b/dash-frontend/src/views/running_games_list.rs
@@ -127,7 +127,7 @@ impl View {
for game in games {
let game_name = View::extract_name_from_appid(&game.app_id, &self.installed_games);
- let t = self.state.parse_template(
+ let t = self.state.realize_template(
&doc_params(layout.state.globals.clone()),
"RunningGameCell",
layout,
diff --git a/wgui/src/layout.rs b/wgui/src/layout.rs
index 9c9a786b..2569f8b7 100644
--- a/wgui/src/layout.rs
+++ b/wgui/src/layout.rs
@@ -377,7 +377,7 @@ impl Layout {
self.registered_components_to_refresh.insert(*node_id, component.weak());
}
- /// Convenience function to avoid repeated `WidgetID` → `WidgetState` lookups.
+ /// Convenience function to avoid repeated `WidgetID` → `WidgetState` look-ups.
pub fn add_event_listener(
&self,
widget_id: WidgetID,
diff --git a/wgui/src/parser/mod.rs b/wgui/src/parser/mod.rs
index bd716e7e..a715b4df 100644
--- a/wgui/src/parser/mod.rs
+++ b/wgui/src/parser/mod.rs
@@ -203,7 +203,6 @@ impl Fetchable for ParserData {
let casted = widget
.get_as::()
.ok_or_else(|| anyhow::anyhow!("fetch_widget_as({id}): failed to cast"))?;
-
Ok(casted)
}
}
@@ -219,16 +218,40 @@ pub struct ParserState {
}
impl ParserState {
- /// This function is suitable in cases if you don't want to pollute main parser state with dynamic IDs
- /// Use `instantiate_template` instead unless you want to handle `components` results yourself.
- /// Make sure not to drop them if you want to have your listener handles valid
- pub fn parse_template(
+ /// Parse named tag and process it.
+ /// Preferred method of parsing templates. Same as `parse_template_only`,
+ /// but it keeps components data in this `ParserState` object for you.
+ /// The result can be safely dropped, all required event listeners and components
+ /// will be kept intact in this `ParserState`.
+ /// Resulting ParserData::components Vec will be left empty (they are moved into this `ParserState::data`)
+ pub fn realize_template(
&mut self,
doc_params: &ParseDocumentParams,
template_name: &str,
layout: &mut Layout,
widget_id: WidgetID,
template_parameters: HashMap, Rc>,
+ ) -> anyhow::Result {
+ let mut parser_data =
+ self.parse_template_only(doc_params, template_name, layout, widget_id, template_parameters)?;
+ // Collect components contained in this freshly-parsed template
+ self.data.components.append(&mut parser_data.components);
+ Ok(parser_data)
+ }
+
+ /// Parse named tag and process it.
+ /// Semi-internal - This function is suitable in cases if you don't want to pollute
+ /// the main parser state state with dynamic IDs (this won't propagate components!)
+ /// Use `realize_template` (or in some rare cases: `instantiate_template`) instead unless you want to handle `components` results yourself.
+ /// Make sure not to drop resulting ParserData if you want to have your listener handles valid
+ /// (they are contained in components). Use `realize_template` instead if you don't want to think about it.
+ pub fn parse_template_only(
+ &self,
+ doc_params: &ParseDocumentParams,
+ template_name: &str,
+ layout: &mut Layout,
+ widget_id: WidgetID,
+ template_parameters: HashMap, Rc>,
) -> anyhow::Result {
let Some(template) = self.data.templates.get(template_name) else {
anyhow::bail!(
@@ -254,7 +277,13 @@ impl ParserState {
Ok(ctx.data_local)
}
- /// Instantiate template by saving all the results into the main `ParserState`
+ /// Parse named tag and process it.
+ /// Instantiate template by saving all the results into the main `ParserState`.
+ /// Be aware you this function will save ALL parsed IDs and other metadata
+ /// into your main ParserState context (deep move).
+ /// You shouldn't instantiate the same template twice, to prevent ID name clash.
+ /// Consider using `parse_template_only` or `realize_template` instead if you want
+ /// to instantiate more than a single template of the same type.
pub fn instantiate_template(
&mut self,
doc_params: &ParseDocumentParams,
@@ -263,7 +292,7 @@ impl ParserState {
widget_id: WidgetID,
template_parameters: HashMap, Rc>,
) -> anyhow::Result<()> {
- let mut data_local = self.parse_template(doc_params, template_name, layout, widget_id, template_parameters)?;
+ let mut data_local = self.parse_template_only(doc_params, template_name, layout, widget_id, template_parameters)?;
self.data.take_results_from(&mut data_local);
Ok(())
diff --git a/wgui/src/windowing/context_menu.rs b/wgui/src/windowing/context_menu.rs
index 6a139dfe..15982d7d 100644
--- a/wgui/src/windowing/context_menu.rs
+++ b/wgui/src/windowing/context_menu.rs
@@ -117,7 +117,7 @@ impl ContextMenu {
par.insert(Rc::from("tooltip_str"), tooltip.generate(&mut globals.i18n()));
}
- let mut data_cell = inner_parser.parse_template(&doc_params, "Cell", layout, id_buttons, par)?;
+ let mut data_cell = inner_parser.realize_template(&doc_params, "Cell", layout, id_buttons, par)?;
let button = data_cell.fetch_component_as::("button")?;
let button_id = button.base().get_id();
@@ -136,7 +136,7 @@ impl ContextMenu {
}
if idx < cells.len() - 1 {
- inner_parser.parse_template(&doc_params, "Separator", layout, id_buttons, Default::default())?;
+ inner_parser.realize_template(&doc_params, "Separator", layout, id_buttons, Default::default())?;
}
}
Ok(())