wgui: ParserResult struct
This commit is contained in:
@@ -48,16 +48,14 @@ struct ParserFile<'a> {
|
|||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
document: Rc<XmlDocument>,
|
document: Rc<XmlDocument>,
|
||||||
ctx: Rc<RefCell<ParserContext<'a>>>,
|
ctx: Rc<RefCell<ParserContext<'a>>>,
|
||||||
current_template: Rc<Template>,
|
|
||||||
template_parameters: HashMap<Rc<str>, Rc<str>>,
|
template_parameters: HashMap<Rc<str>, Rc<str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
pub struct ParserResult {
|
||||||
pub struct ParserState {
|
ids: HashMap<Rc<str>, WidgetID>,
|
||||||
pub ids: HashMap<Rc<str>, WidgetID>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParserState {
|
impl ParserResult {
|
||||||
pub fn require_by_id(&self, id: &str) -> anyhow::Result<WidgetID> {
|
pub fn require_by_id(&self, id: &str) -> anyhow::Result<WidgetID> {
|
||||||
match self.ids.get(id) {
|
match self.ids.get(id) {
|
||||||
Some(id) => Ok(*id),
|
Some(id) => Ok(*id),
|
||||||
@@ -70,7 +68,7 @@ struct ParserContext<'a> {
|
|||||||
layout: &'a mut Layout,
|
layout: &'a mut Layout,
|
||||||
var_map: VarMap,
|
var_map: VarMap,
|
||||||
templates: HashMap<Rc<str>, Rc<Template>>,
|
templates: HashMap<Rc<str>, Rc<Template>>,
|
||||||
state: &'a mut ParserState,
|
ids: HashMap<Rc<str>, WidgetID>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses a color from a HTML hex string
|
// Parses a color from a HTML hex string
|
||||||
@@ -562,6 +560,39 @@ fn parse_widget_sprite<'a>(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_widget_other<'a>(
|
||||||
|
xml_tag_name: &str,
|
||||||
|
file: &'a ParserFile,
|
||||||
|
ctx: &mut ParserContext,
|
||||||
|
node: roxmltree::Node<'a, 'a>,
|
||||||
|
parent_id: WidgetID,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let Some(template) = ctx.templates.get(xml_tag_name) else {
|
||||||
|
log::error!("Undefined tag named \"{}\"", xml_tag_name);
|
||||||
|
return Ok(()); // not critical
|
||||||
|
};
|
||||||
|
|
||||||
|
let template_parameters: HashMap<Rc<str>, Rc<str>> = iter_attribs(file, ctx, &node).collect();
|
||||||
|
|
||||||
|
let template_file = ParserFile {
|
||||||
|
ctx: file.ctx.clone(),
|
||||||
|
document: template.node_document.clone(),
|
||||||
|
path: file.path.clone(),
|
||||||
|
template_parameters,
|
||||||
|
};
|
||||||
|
|
||||||
|
let doc = template_file.document.clone();
|
||||||
|
|
||||||
|
let template_node = doc
|
||||||
|
.borrow_doc()
|
||||||
|
.get_node(template.node)
|
||||||
|
.ok_or(anyhow::anyhow!("template node invalid"))?;
|
||||||
|
|
||||||
|
parse_children(&template_file, ctx, template_node, parent_id)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_widget_label<'a>(
|
fn parse_widget_label<'a>(
|
||||||
file: &'a ParserFile,
|
file: &'a ParserFile,
|
||||||
ctx: &mut ParserContext,
|
ctx: &mut ParserContext,
|
||||||
@@ -800,7 +831,7 @@ fn parse_universal<'a>(
|
|||||||
match key.as_ref() {
|
match key.as_ref() {
|
||||||
"id" => {
|
"id" => {
|
||||||
// Attach a specific widget to name-ID map (just like getElementById)
|
// Attach a specific widget to name-ID map (just like getElementById)
|
||||||
if ctx.state.ids.insert(value.clone(), widget_id).is_some() {
|
if ctx.ids.insert(value.clone(), widget_id).is_some() {
|
||||||
log::warn!("duplicate ID \"{}\" in the same layout file!", value);
|
log::warn!("duplicate ID \"{}\" in the same layout file!", value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -835,30 +866,7 @@ fn parse_children<'a>(
|
|||||||
}
|
}
|
||||||
"" => { /* ignore */ }
|
"" => { /* ignore */ }
|
||||||
other_tag_name => {
|
other_tag_name => {
|
||||||
let Some(template) = ctx.templates.get(other_tag_name) else {
|
parse_widget_other(other_tag_name, file, ctx, child_node, parent_id)?;
|
||||||
log::error!("Undefined tag named \"{}\"", other_tag_name);
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let template_parameters: HashMap<Rc<str>, Rc<str>> =
|
|
||||||
iter_attribs(file, ctx, &child_node).collect();
|
|
||||||
|
|
||||||
let template_file = ParserFile {
|
|
||||||
ctx: file.ctx.clone(),
|
|
||||||
document: template.node_document.clone(),
|
|
||||||
path: file.path.clone(),
|
|
||||||
template_parameters,
|
|
||||||
current_template: template.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let doc = template_file.document.clone();
|
|
||||||
|
|
||||||
let template_node = doc
|
|
||||||
.borrow_doc()
|
|
||||||
.get_node(template.node)
|
|
||||||
.ok_or(anyhow::anyhow!("template node invalid"))?;
|
|
||||||
|
|
||||||
parse_children(&template_file, ctx, template_node, parent_id)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -869,13 +877,12 @@ pub fn parse_from_assets(
|
|||||||
layout: &mut Layout,
|
layout: &mut Layout,
|
||||||
parent_id: WidgetID,
|
parent_id: WidgetID,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> anyhow::Result<ParserState> {
|
) -> anyhow::Result<ParserResult> {
|
||||||
let path = PathBuf::from(path);
|
let path = PathBuf::from(path);
|
||||||
let mut result = ParserState::default();
|
|
||||||
|
|
||||||
let ctx_rc = Rc::new(RefCell::new(ParserContext {
|
let ctx_rc = Rc::new(RefCell::new(ParserContext {
|
||||||
layout,
|
layout,
|
||||||
state: &mut result,
|
ids: Default::default(),
|
||||||
var_map: Default::default(),
|
var_map: Default::default(),
|
||||||
templates: Default::default(),
|
templates: Default::default(),
|
||||||
}));
|
}));
|
||||||
@@ -884,11 +891,27 @@ pub fn parse_from_assets(
|
|||||||
|
|
||||||
let (file, node_layout) = get_doc_from_path(ctx_rc.clone(), &mut ctx, &path)?;
|
let (file, node_layout) = get_doc_from_path(ctx_rc.clone(), &mut ctx, &path)?;
|
||||||
parse_document_root(file, &mut ctx, parent_id, node_layout)?;
|
parse_document_root(file, &mut ctx, parent_id, node_layout)?;
|
||||||
|
|
||||||
|
// move everything essential to the result
|
||||||
|
let result = ParserResult {
|
||||||
|
ids: std::mem::take(&mut ctx.ids),
|
||||||
|
};
|
||||||
|
|
||||||
drop(ctx);
|
drop(ctx);
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_layout_from_assets(
|
||||||
|
assets: Box<dyn AssetProvider>,
|
||||||
|
path: &str,
|
||||||
|
) -> anyhow::Result<(Layout, ParserResult)> {
|
||||||
|
let mut layout = Layout::new(assets)?;
|
||||||
|
let widget = layout.root_widget;
|
||||||
|
let state = parse_from_assets(&mut layout, widget, path)?;
|
||||||
|
Ok((layout, state))
|
||||||
|
}
|
||||||
|
|
||||||
fn assets_path_to_xml(assets: &mut Box<dyn AssetProvider>, path: &Path) -> anyhow::Result<String> {
|
fn assets_path_to_xml(assets: &mut Box<dyn AssetProvider>, path: &Path) -> anyhow::Result<String> {
|
||||||
let data = assets.load_from_path(&path.to_string_lossy())?;
|
let data = assets.load_from_path(&path.to_string_lossy())?;
|
||||||
Ok(String::from_utf8(data)?)
|
Ok(String::from_utf8(data)?)
|
||||||
@@ -911,17 +934,11 @@ fn get_doc_from_path<'a>(
|
|||||||
let root = document.borrow_doc().root();
|
let root = document.borrow_doc().root();
|
||||||
let tag_layout = require_tag_by_name(&root, "layout")?;
|
let tag_layout = require_tag_by_name(&root, "layout")?;
|
||||||
|
|
||||||
let template = Template {
|
|
||||||
node: root.id(),
|
|
||||||
node_document: document.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let file = ParserFile {
|
let file = ParserFile {
|
||||||
ctx: ctx_rc.clone(),
|
ctx: ctx_rc.clone(),
|
||||||
path: PathBuf::from(path),
|
path: PathBuf::from(path),
|
||||||
document: document.clone(),
|
document: document.clone(),
|
||||||
current_template: Rc::new(template),
|
template_parameters: Default::default(),
|
||||||
template_parameters: Default::default(), // todo
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((file, tag_layout.id()))
|
Ok((file, tag_layout.id()))
|
||||||
|
|||||||
@@ -9,12 +9,7 @@ pub struct TestbedAny {
|
|||||||
impl TestbedAny {
|
impl TestbedAny {
|
||||||
pub fn new(name: &str) -> anyhow::Result<Self> {
|
pub fn new(name: &str) -> anyhow::Result<Self> {
|
||||||
let path = format!("gui/{name}.xml");
|
let path = format!("gui/{name}.xml");
|
||||||
let mut layout = Layout::new(Box::new(assets::Asset {}))?;
|
let (layout, _state) = wgui::parser::new_layout_from_assets(Box::new(assets::Asset {}), &path)?;
|
||||||
|
|
||||||
let parent = layout.root_widget;
|
|
||||||
|
|
||||||
let _res = wgui::parser::parse_from_assets(&mut layout, parent, &path)?;
|
|
||||||
|
|
||||||
Ok(Self { layout })
|
Ok(Self { layout })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,8 @@ pub struct TestbedDashboard {
|
|||||||
impl TestbedDashboard {
|
impl TestbedDashboard {
|
||||||
pub fn new() -> anyhow::Result<Self> {
|
pub fn new() -> anyhow::Result<Self> {
|
||||||
const XML_PATH: &str = "gui/dashboard.xml";
|
const XML_PATH: &str = "gui/dashboard.xml";
|
||||||
|
let (layout, _state) =
|
||||||
let mut layout = Layout::new(Box::new(assets::Asset {}))?;
|
wgui::parser::new_layout_from_assets(Box::new(assets::Asset {}), XML_PATH)?;
|
||||||
|
|
||||||
let parent = layout.root_widget;
|
|
||||||
|
|
||||||
let _res = wgui::parser::parse_from_assets(&mut layout, parent, XML_PATH)?;
|
|
||||||
|
|
||||||
Ok(Self { layout })
|
Ok(Self { layout })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,8 @@ impl TestbedGeneric {
|
|||||||
pub fn new() -> anyhow::Result<Self> {
|
pub fn new() -> anyhow::Result<Self> {
|
||||||
const XML_PATH: &str = "gui/testbed.xml";
|
const XML_PATH: &str = "gui/testbed.xml";
|
||||||
|
|
||||||
let mut layout = Layout::new(Box::new(assets::Asset {}))?;
|
let (mut layout, res) =
|
||||||
|
wgui::parser::new_layout_from_assets(Box::new(assets::Asset {}), XML_PATH)?;
|
||||||
layout.assets.load_from_path(XML_PATH)?;
|
|
||||||
|
|
||||||
let parent = layout.root_widget;
|
|
||||||
|
|
||||||
let res = wgui::parser::parse_from_assets(&mut layout, parent, XML_PATH)?;
|
|
||||||
|
|
||||||
use wgui::components::button;
|
use wgui::components::button;
|
||||||
let my_div_parent = res.require_by_id("my_div_parent")?;
|
let my_div_parent = res.require_by_id("my_div_parent")?;
|
||||||
|
|||||||
7
wlx-overlay-s/src/assets/key.xml
Normal file
7
wlx-overlay-s/src/assets/key.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<layout>
|
||||||
|
<template name="Key">
|
||||||
|
<rectangle color="#FF0000" width="32" height="32" margin="4">
|
||||||
|
|
||||||
|
</rectangle>
|
||||||
|
</template>
|
||||||
|
</layout>
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
mod asset;
|
pub mod asset;
|
||||||
pub mod panel;
|
pub mod panel;
|
||||||
mod timestep;
|
mod timestep;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
config::{self, ConfigType},
|
config::{self, ConfigType},
|
||||||
graphics::CommandBuffers,
|
graphics::CommandBuffers,
|
||||||
gui::panel::GuiPanel,
|
gui::{self, panel::GuiPanel},
|
||||||
hid::{
|
hid::{
|
||||||
ALT, CTRL, KEYS_TO_MODS, KeyModifier, KeyType, META, NUM_LOCK, SHIFT, SUPER, VirtualKey,
|
ALT, CTRL, KEYS_TO_MODS, KeyModifier, KeyType, META, NUM_LOCK, SHIFT, SUPER, VirtualKey,
|
||||||
XkbKeymap, get_key_type,
|
XkbKeymap, get_key_type,
|
||||||
@@ -125,6 +125,9 @@ where
|
|||||||
keymap = None;
|
keymap = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (key_layout, _state) =
|
||||||
|
wgui::parser::new_layout_from_assets(Box::new(gui::asset::GuiAsset {}), "key.xml")?;
|
||||||
|
|
||||||
for row in 0..LAYOUT.key_sizes.len() {
|
for row in 0..LAYOUT.key_sizes.len() {
|
||||||
let (div, _) = panel.layout.add_child(
|
let (div, _) = panel.layout.add_child(
|
||||||
background,
|
background,
|
||||||
@@ -142,7 +145,10 @@ where
|
|||||||
height: length(PIXELS_PER_UNIT),
|
height: length(PIXELS_PER_UNIT),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(key) = LAYOUT.main_layout[row][col].as_ref() {
|
let Some(key) = LAYOUT.main_layout[row][col].as_ref() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
let mut label = Vec::with_capacity(2);
|
let mut label = Vec::with_capacity(2);
|
||||||
let mut maybe_state: Option<KeyButtonData> = None;
|
let mut maybe_state: Option<KeyButtonData> = None;
|
||||||
let mut cap_type = KeyCapType::Regular;
|
let mut cap_type = KeyCapType::Regular;
|
||||||
@@ -251,7 +257,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let interaction_transform = Affine2::from_translation(vec2(0.5, 0.5))
|
let interaction_transform = Affine2::from_translation(vec2(0.5, 0.5))
|
||||||
* Affine2::from_scale(vec2(1., -size.x as f32 / size.y as f32));
|
* Affine2::from_scale(vec2(1., -size.x as f32 / size.y as f32));
|
||||||
|
|||||||
Reference in New Issue
Block a user