mirror of https://github.com/wayvr-org/wayvr.git
ParserState: add `realize_template`, fix sliders not being updated
This commit is contained in:
parent
0a4fc34fac
commit
80277e0c12
|
|
@ -1,16 +1,16 @@
|
||||||
<layout>
|
<layout>
|
||||||
<include src="../t_group_box.xml" />
|
<include src_builtin="../t_group_box.xml" />
|
||||||
|
|
||||||
<!-- device_name, device_icon -->
|
<!-- device_name, device_icon -->
|
||||||
<template name="DeviceSlider">
|
<template name="DeviceSlider">
|
||||||
<rectangle macro="group_box">
|
<rectangle macro="group_box">
|
||||||
<div width="100%" align_items="center" justify_content="center" gap="8">
|
<div width="100%" align_items="center" justify_content="center" gap="8">
|
||||||
<sprite src="${device_icon}" width="16" height="16" />
|
<sprite src_builtin="${device_icon}" width="16" height="16" />
|
||||||
<label text="${device_name}" margin_right="8" size="12" weight="bold" />
|
<label text="${device_name}" margin_right="8" size="12" weight="bold" />
|
||||||
</div>
|
</div>
|
||||||
<div width="100%" align_items="center">
|
<div width="100%" align_items="center">
|
||||||
<CheckBox id="checkbox" />
|
<CheckBox id="checkbox" />
|
||||||
<Button sprite_src="${volume_icon}" id="btn_mute" width="32" />
|
<Button sprite_src_builtin="${volume_icon}" id="btn_mute" width="32" />
|
||||||
<Slider id="slider" flex_grow="1" height="16" min_value="0" max_value="150" margin_left="8" />
|
<Slider id="slider" flex_grow="1" height="16" min_value="0" max_value="150" margin_left="8" />
|
||||||
</div>
|
</div>
|
||||||
</rectangle>
|
</rectangle>
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
flex_grow="1"
|
flex_grow="1"
|
||||||
id="${id}"
|
id="${id}"
|
||||||
translation="${translation}"
|
translation="${translation}"
|
||||||
sprite_src="${src}">
|
sprite_src_builtin="${src}">
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -67,4 +67,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</elements>
|
</elements>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@ impl AppList {
|
||||||
let mut params = HashMap::<Rc<str>, Rc<str>>::new();
|
let mut params = HashMap::<Rc<str>, Rc<str>>::new();
|
||||||
params.insert("text".into(), category_name.into());
|
params.insert("text".into(), category_name.into());
|
||||||
|
|
||||||
parser_state.parse_template(
|
parser_state.realize_template(
|
||||||
doc_params,
|
doc_params,
|
||||||
"CategoryText",
|
"CategoryText",
|
||||||
&mut frontend.layout,
|
&mut frontend.layout,
|
||||||
|
|
@ -318,7 +318,7 @@ impl AppList {
|
||||||
);
|
);
|
||||||
params.insert("name".into(), entry.app_name.clone());
|
params.insert("name".into(), entry.app_name.clone());
|
||||||
|
|
||||||
let data = parser_state.parse_template(
|
let data = parser_state.realize_template(
|
||||||
doc_params,
|
doc_params,
|
||||||
"AppEntry",
|
"AppEntry",
|
||||||
&mut frontend.layout,
|
&mut frontend.layout,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use wgui::{
|
||||||
drawing::Color,
|
drawing::Color,
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
layout::{Layout, WidgetID},
|
layout::{Layout, WidgetID},
|
||||||
parser::{self, Fetchable, ParseDocumentParams, ParserData, ParserState},
|
parser::{self, Fetchable, ParseDocumentParams, ParserState},
|
||||||
task::Tasks,
|
task::Tasks,
|
||||||
};
|
};
|
||||||
use wlx_common::dash_interface::{self, MonadoDumpSessionFrame};
|
use wlx_common::dash_interface::{self, MonadoDumpSessionFrame};
|
||||||
|
|
@ -66,15 +66,11 @@ struct SubtabGeneralSettings {
|
||||||
|
|
||||||
struct DebugGraph {
|
struct DebugGraph {
|
||||||
graph: Rc<ComponentBarGraph>,
|
graph: Rc<ComponentBarGraph>,
|
||||||
#[allow(dead_code)]
|
|
||||||
data: ParserData,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DebugSessionList {
|
struct DebugSessionList {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
buttons: Vec<Rc<ComponentButton>>,
|
buttons: Vec<Rc<ComponentButton>>,
|
||||||
#[allow(dead_code)]
|
|
||||||
data_vec: Vec<ParserData>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TimingsSession {
|
struct TimingsSession {
|
||||||
|
|
@ -288,7 +284,6 @@ fn mount_sessions_list(
|
||||||
sessions: &SessionsMap,
|
sessions: &SessionsMap,
|
||||||
) -> anyhow::Result<DebugSessionList> {
|
) -> anyhow::Result<DebugSessionList> {
|
||||||
let mut buttons = Vec::new();
|
let mut buttons = Vec::new();
|
||||||
let mut data_vec = Vec::new();
|
|
||||||
let globals = layout.state.globals.clone();
|
let globals = layout.state.globals.clone();
|
||||||
layout.remove_children(id_parent);
|
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),
|
&doc_params_tab_debug_timings(&globals),
|
||||||
"SessionButton",
|
"SessionButton",
|
||||||
layout,
|
layout,
|
||||||
|
|
@ -324,10 +319,9 @@ fn mount_sessions_list(
|
||||||
});
|
});
|
||||||
|
|
||||||
buttons.push(button);
|
buttons.push(button);
|
||||||
data_vec.push(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(DebugSessionList { buttons, data_vec })
|
Ok(DebugSessionList { buttons })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mount_graph(
|
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_min"), Rc::from(limits.0.to_string()));
|
||||||
params.insert(Rc::from("limit_max"), Rc::from(limits.1.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),
|
&doc_params_tab_debug_timings(&globals),
|
||||||
"DebugGraph",
|
"DebugGraph",
|
||||||
layout,
|
layout,
|
||||||
|
|
@ -352,7 +346,7 @@ fn mount_graph(
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let graph = data.fetch_component_as::<ComponentBarGraph>("graph")?;
|
let graph = data.fetch_component_as::<ComponentBarGraph>("graph")?;
|
||||||
Ok(DebugGraph { graph, data })
|
Ok(DebugGraph { graph })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ns_to_ms(ns: i64) -> f32 {
|
fn ns_to_ms(ns: i64) -> f32 {
|
||||||
|
|
@ -585,7 +579,7 @@ impl SubtabProcessList {
|
||||||
|
|
||||||
let globals = layout.state.globals.clone();
|
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),
|
&doc_params_tab_process_list(&globals),
|
||||||
"Cell",
|
"Cell",
|
||||||
layout,
|
layout,
|
||||||
|
|
|
||||||
|
|
@ -750,7 +750,7 @@ impl View {
|
||||||
|
|
||||||
let data = self
|
let data = self
|
||||||
.state
|
.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::<ComponentButton>("btn_card")?;
|
let btn_card = data.fetch_component_as::<ComponentButton>("btn_card")?;
|
||||||
btn_card.on_click({
|
btn_card.on_click({
|
||||||
|
|
@ -764,7 +764,6 @@ impl View {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
log::info!("mount card TODO: {}", params.card.name);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -794,7 +793,7 @@ impl View {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let data = self.state.parse_template(
|
let data = self.state.realize_template(
|
||||||
&doc_params(&self.globals),
|
&doc_params(&self.globals),
|
||||||
"DeviceSlider",
|
"DeviceSlider",
|
||||||
params.layout,
|
params.layout,
|
||||||
|
|
@ -941,7 +940,7 @@ impl View {
|
||||||
layout.remove_children(self.id_devices);
|
layout.remove_children(self.id_devices);
|
||||||
|
|
||||||
{
|
{
|
||||||
let data = self.state.parse_template(
|
let data = self.state.realize_template(
|
||||||
&doc_params(&self.globals),
|
&doc_params(&self.globals),
|
||||||
"SelectAudioProfileText",
|
"SelectAudioProfileText",
|
||||||
layout,
|
layout,
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ impl View {
|
||||||
for game in games {
|
for game in games {
|
||||||
let game_name = View::extract_name_from_appid(&game.app_id, &self.installed_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()),
|
&doc_params(layout.state.globals.clone()),
|
||||||
"RunningGameCell",
|
"RunningGameCell",
|
||||||
layout,
|
layout,
|
||||||
|
|
|
||||||
|
|
@ -377,7 +377,7 @@ impl Layout {
|
||||||
self.registered_components_to_refresh.insert(*node_id, component.weak());
|
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<U1: 'static, U2: 'static>(
|
pub fn add_event_listener<U1: 'static, U2: 'static>(
|
||||||
&self,
|
&self,
|
||||||
widget_id: WidgetID,
|
widget_id: WidgetID,
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,6 @@ impl Fetchable for ParserData {
|
||||||
let casted = widget
|
let casted = widget
|
||||||
.get_as::<T>()
|
.get_as::<T>()
|
||||||
.ok_or_else(|| anyhow::anyhow!("fetch_widget_as({id}): failed to cast"))?;
|
.ok_or_else(|| anyhow::anyhow!("fetch_widget_as({id}): failed to cast"))?;
|
||||||
|
|
||||||
Ok(casted)
|
Ok(casted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,16 +218,40 @@ pub struct ParserState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParserState {
|
impl ParserState {
|
||||||
/// This function is suitable in cases if you don't want to pollute main parser state with dynamic IDs
|
/// Parse named <template> tag and process it.
|
||||||
/// Use `instantiate_template` instead unless you want to handle `components` results yourself.
|
/// Preferred method of parsing templates. Same as `parse_template_only`,
|
||||||
/// Make sure not to drop them if you want to have your listener handles valid
|
/// but it keeps components data in this `ParserState` object for you.
|
||||||
pub fn parse_template(
|
/// 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,
|
&mut self,
|
||||||
doc_params: &ParseDocumentParams,
|
doc_params: &ParseDocumentParams,
|
||||||
template_name: &str,
|
template_name: &str,
|
||||||
layout: &mut Layout,
|
layout: &mut Layout,
|
||||||
widget_id: WidgetID,
|
widget_id: WidgetID,
|
||||||
template_parameters: HashMap<Rc<str>, Rc<str>>,
|
template_parameters: HashMap<Rc<str>, Rc<str>>,
|
||||||
|
) -> anyhow::Result<ParserData> {
|
||||||
|
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 <template> 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<str>, Rc<str>>,
|
||||||
) -> anyhow::Result<ParserData> {
|
) -> anyhow::Result<ParserData> {
|
||||||
let Some(template) = self.data.templates.get(template_name) else {
|
let Some(template) = self.data.templates.get(template_name) else {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
|
|
@ -254,7 +277,13 @@ impl ParserState {
|
||||||
Ok(ctx.data_local)
|
Ok(ctx.data_local)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instantiate template by saving all the results into the main `ParserState`
|
/// Parse named <template> 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(
|
pub fn instantiate_template(
|
||||||
&mut self,
|
&mut self,
|
||||||
doc_params: &ParseDocumentParams,
|
doc_params: &ParseDocumentParams,
|
||||||
|
|
@ -263,7 +292,7 @@ impl ParserState {
|
||||||
widget_id: WidgetID,
|
widget_id: WidgetID,
|
||||||
template_parameters: HashMap<Rc<str>, Rc<str>>,
|
template_parameters: HashMap<Rc<str>, Rc<str>>,
|
||||||
) -> anyhow::Result<()> {
|
) -> 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);
|
self.data.take_results_from(&mut data_local);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ impl ContextMenu {
|
||||||
par.insert(Rc::from("tooltip_str"), tooltip.generate(&mut globals.i18n()));
|
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::<ComponentButton>("button")?;
|
let button = data_cell.fetch_component_as::<ComponentButton>("button")?;
|
||||||
let button_id = button.base().get_id();
|
let button_id = button.base().get_id();
|
||||||
|
|
@ -136,7 +136,7 @@ impl ContextMenu {
|
||||||
}
|
}
|
||||||
|
|
||||||
if idx < cells.len() - 1 {
|
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(())
|
Ok(())
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue