153 lines
6.1 KiB
Rust
153 lines
6.1 KiB
Rust
use std::{collections::HashMap, rc::Rc};
|
|
|
|
use slotmap::{Key, SecondaryMap};
|
|
use wgui::{
|
|
components::button::ComponentButton,
|
|
event::{CallbackDataCommon, EventAlterables},
|
|
layout::Layout,
|
|
parser::{Fetchable, ParseDocumentParams, ParserState},
|
|
};
|
|
|
|
use crate::windowing::{OverlayID, backend::OverlayEventData, window::OverlayCategory};
|
|
|
|
#[derive(Default)]
|
|
/// Helper for managing a list of overlays
|
|
/// Populates `id="panels_root"` with `<Screen>`, `<Mirror>`, `<Panel>` templates
|
|
/// Populates `id="apps_root"` with `<App>` templates (optional)
|
|
/// Uses the following parameters: `name` (All), `display` (Screen, Mirror), `icon` (App)
|
|
pub struct OverlayList {
|
|
overlay_buttons: SecondaryMap<OverlayID, Rc<ComponentButton>>,
|
|
}
|
|
|
|
impl OverlayList {
|
|
pub fn on_notify(
|
|
&mut self,
|
|
layout: &mut Layout,
|
|
parser_state: &mut ParserState,
|
|
event_data: &OverlayEventData,
|
|
alterables: &mut EventAlterables,
|
|
doc_params: &ParseDocumentParams,
|
|
) -> anyhow::Result<bool> {
|
|
let mut elements_changed = false;
|
|
match event_data {
|
|
OverlayEventData::OverlaysChanged(metas) => {
|
|
let panels_root = parser_state
|
|
.get_widget_id("panels_root")
|
|
.unwrap_or_default();
|
|
let apps_root = parser_state.get_widget_id("apps_root").unwrap_or_default();
|
|
|
|
layout.remove_children(panels_root);
|
|
layout.remove_children(apps_root);
|
|
self.overlay_buttons.clear();
|
|
|
|
for (i, meta) in metas.iter().enumerate() {
|
|
let mut params = HashMap::new();
|
|
|
|
let (template, root) = match meta.category {
|
|
OverlayCategory::Screen => {
|
|
params.insert(
|
|
"display".into(),
|
|
format!(
|
|
"{}{}",
|
|
(*meta.name).chars().next().unwrap_or_default(),
|
|
(*meta.name).chars().last().unwrap_or_default()
|
|
)
|
|
.into(),
|
|
);
|
|
("Screen", panels_root)
|
|
}
|
|
OverlayCategory::Mirror => {
|
|
params.insert(
|
|
"display".into(),
|
|
(*meta.name).chars().last().unwrap().to_string().into(),
|
|
);
|
|
("Mirror", panels_root)
|
|
}
|
|
OverlayCategory::Panel => ("Panel", panels_root),
|
|
OverlayCategory::WayVR => {
|
|
params.insert(
|
|
"icon".into(),
|
|
meta.icon
|
|
.as_ref()
|
|
.expect("WayVR overlay without Icon attribute!")
|
|
.as_ref()
|
|
.into(),
|
|
);
|
|
("App", apps_root)
|
|
}
|
|
OverlayCategory::Dashboard | OverlayCategory::Keyboard => {
|
|
let key = if matches!(meta.category, OverlayCategory::Dashboard) {
|
|
"btn_dashboard"
|
|
} else {
|
|
"btn_keyboard"
|
|
};
|
|
|
|
let Ok(overlay_button) =
|
|
parser_state.fetch_component_as::<ComponentButton>(key)
|
|
else {
|
|
continue;
|
|
};
|
|
|
|
if meta.visible {
|
|
let mut com = CallbackDataCommon {
|
|
alterables: alterables,
|
|
state: &layout.state,
|
|
};
|
|
overlay_button.set_sticky_state(&mut com, true);
|
|
}
|
|
self.overlay_buttons.insert(meta.id, overlay_button);
|
|
continue;
|
|
}
|
|
_ => continue,
|
|
};
|
|
|
|
if root.is_null() {
|
|
continue;
|
|
}
|
|
|
|
params.insert("idx".into(), i.to_string().into());
|
|
params.insert("name".into(), meta.name.as_ref().into());
|
|
parser_state.instantiate_template(
|
|
&doc_params,
|
|
template,
|
|
layout,
|
|
root,
|
|
params,
|
|
)?;
|
|
let overlay_button = parser_state
|
|
.fetch_component_as::<ComponentButton>(&format!("overlay_{i}"))?;
|
|
if meta.visible {
|
|
let mut com = CallbackDataCommon {
|
|
alterables: alterables,
|
|
state: &layout.state,
|
|
};
|
|
overlay_button.set_sticky_state(&mut com, true);
|
|
}
|
|
self.overlay_buttons.insert(meta.id, overlay_button);
|
|
}
|
|
elements_changed = true;
|
|
}
|
|
OverlayEventData::VisibleOverlaysChanged(overlays) => {
|
|
let mut com = CallbackDataCommon {
|
|
alterables: alterables,
|
|
state: &layout.state,
|
|
};
|
|
let mut overlay_buttons = self.overlay_buttons.clone();
|
|
|
|
for visible in overlays.as_ref() {
|
|
if let Some(btn) = overlay_buttons.remove(*visible) {
|
|
btn.set_sticky_state(&mut com, true);
|
|
}
|
|
}
|
|
|
|
for btn in overlay_buttons.values() {
|
|
btn.set_sticky_state(&mut com, false);
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
|
|
Ok(elements_changed)
|
|
}
|
|
}
|