working bar context menus + kbd downsize
This commit is contained in:
@@ -23,7 +23,7 @@ use wgui::{
|
|||||||
task::Tasks,
|
task::Tasks,
|
||||||
widget::{div::WidgetDiv, label::WidgetLabel, rectangle::WidgetRectangle},
|
widget::{div::WidgetDiv, label::WidgetLabel, rectangle::WidgetRectangle},
|
||||||
windowing::{
|
windowing::{
|
||||||
context_menu,
|
context_menu::{self, TickResult},
|
||||||
window::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra},
|
window::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -285,7 +285,7 @@ impl Testbed for TestbedGeneric {
|
|||||||
let res = data
|
let res = data
|
||||||
.context_menu
|
.context_menu
|
||||||
.tick(&mut self.layout, &mut self.parser_state)?;
|
.tick(&mut self.layout, &mut self.parser_state)?;
|
||||||
if let Some(action_name) = res.action_name {
|
if let TickResult::Action(action_name) = res {
|
||||||
log::info!("got action: {}", action_name);
|
log::info!("got action: {}", action_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<layout>
|
<layout>
|
||||||
<!-- text: str -->
|
<!-- text: str -->
|
||||||
<template name="Cell">
|
<template name="Cell">
|
||||||
<Button id="button" text="${text}" weight="bold" border="0" color="#FFFFFF00" />
|
<Button id="button" text="${text}" weight="bold" border="0" padding="4" color="#FFFFFF00" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="Separator">
|
<template name="Separator">
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ use crate::{
|
|||||||
windowing::context_menu,
|
windowing::context_menu,
|
||||||
};
|
};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use glam::Vec2;
|
|
||||||
use ouroboros::self_referencing;
|
use ouroboros::self_referencing;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{cell::RefMut, collections::HashMap, path::Path, rc::Rc};
|
use std::{cell::RefMut, collections::HashMap, path::Path, rc::Rc};
|
||||||
@@ -97,7 +96,7 @@ pub trait Fetchable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ParserData {
|
impl ParserData {
|
||||||
fn take_results_from(&mut self, from: &mut Self) {
|
pub(crate) fn take_results_from(&mut self, from: &mut Self) {
|
||||||
let ids = std::mem::take(&mut from.ids);
|
let ids = std::mem::take(&mut from.ids);
|
||||||
let components = std::mem::take(&mut from.components);
|
let components = std::mem::take(&mut from.components);
|
||||||
let components_by_id = std::mem::take(&mut from.components_by_id);
|
let components_by_id = std::mem::take(&mut from.components_by_id);
|
||||||
@@ -140,7 +139,7 @@ impl Fetchable for ParserData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let Some(component) = weak.upgrade() else {
|
let Some(component) = weak.upgrade() else {
|
||||||
anyhow::bail!("Component by widget ID \"{widget_id:?}\" doesn't exist");
|
anyhow::bail!("Component by widget ID \"{widget_id:?}\" has disappeared");
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Component(component))
|
Ok(Component(component))
|
||||||
@@ -264,7 +263,6 @@ impl ParserState {
|
|||||||
&mut self,
|
&mut self,
|
||||||
template_name: &str,
|
template_name: &str,
|
||||||
template_params: &HashMap<Rc<str>, Rc<str>>,
|
template_params: &HashMap<Rc<str>, Rc<str>>,
|
||||||
position: Vec2,
|
|
||||||
) -> anyhow::Result<context_menu::Blueprint> {
|
) -> anyhow::Result<context_menu::Blueprint> {
|
||||||
let Some(template) = self.data.templates.get(template_name) else {
|
let Some(template) = self.data.templates.get(template_name) else {
|
||||||
anyhow::bail!("no template named \"{template_name}\" found");
|
anyhow::bail!("no template named \"{template_name}\" found");
|
||||||
@@ -320,7 +318,6 @@ impl ParserState {
|
|||||||
Ok(
|
Ok(
|
||||||
context_menu::Blueprint {
|
context_menu::Blueprint {
|
||||||
cells,
|
cells,
|
||||||
position,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use crate::drawing::{self};
|
|||||||
pub static SWASH_CACHE: LazyLock<Mutex<SwashCache>> = LazyLock::new(|| Mutex::new(SwashCache::new()));
|
pub static SWASH_CACHE: LazyLock<Mutex<SwashCache>> = LazyLock::new(|| Mutex::new(SwashCache::new()));
|
||||||
|
|
||||||
/// Used in case no `font_size` is defined
|
/// Used in case no `font_size` is defined
|
||||||
const DEFAULT_FONT_SIZE: f32 = 14.;
|
pub(crate) const DEFAULT_FONT_SIZE: f32 = 14.;
|
||||||
|
|
||||||
/// In case no `line_height` is defined, use `font_size` * `DEFAULT_LINE_HEIGHT_RATIO`
|
/// In case no `line_height` is defined, use `font_size` * `DEFAULT_LINE_HEIGHT_RATIO`
|
||||||
const DEFAULT_LINE_HEIGHT_RATIO: f32 = 1.43;
|
const DEFAULT_LINE_HEIGHT_RATIO: f32 = 1.43;
|
||||||
@@ -77,7 +77,11 @@ impl From<&TextStyle> for Metrics {
|
|||||||
|
|
||||||
impl From<&TextStyle> for Wrap {
|
impl From<&TextStyle> for Wrap {
|
||||||
fn from(value: &TextStyle) -> Self {
|
fn from(value: &TextStyle) -> Self {
|
||||||
if value.wrap { Self::WordOrGlyph } else { Self::None }
|
if value.wrap {
|
||||||
|
Self::WordOrGlyph
|
||||||
|
} else {
|
||||||
|
Self::None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ pub struct Cell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Blueprint {
|
pub(crate) struct Blueprint {
|
||||||
pub position: Vec2,
|
|
||||||
pub cells: Vec<Cell>,
|
pub cells: Vec<Cell>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,23 +42,25 @@ pub struct ContextMenu {
|
|||||||
tasks: Tasks<Task>,
|
tasks: Tasks<Task>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doc_params<'a>(
|
fn doc_params<'a>(globals: &WguiGlobals) -> parser::ParseDocumentParams<'a> {
|
||||||
globals: &WguiGlobals,
|
|
||||||
on_custom_attribs: Option<parser::OnCustomAttribsFunc>,
|
|
||||||
) -> parser::ParseDocumentParams<'a> {
|
|
||||||
parser::ParseDocumentParams {
|
parser::ParseDocumentParams {
|
||||||
globals: globals.clone(),
|
globals: globals.clone(),
|
||||||
path: AssetPath::WguiInternal("wgui/context_menu.xml"),
|
path: AssetPath::WguiInternal("wgui/context_menu.xml"),
|
||||||
extra: parser::ParseDocumentExtra {
|
extra: Default::default(),
|
||||||
on_custom_attribs,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TickResult {
|
pub enum TickResult {
|
||||||
pub action_name: Option<Rc<str>>,
|
/// Nothing happened
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
/// The context menu was opened.
|
||||||
|
Opened,
|
||||||
|
/// User has selected an action.
|
||||||
|
Action(Rc<str>),
|
||||||
|
/// The context menu was closed without an action.
|
||||||
|
Closed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContextMenu {
|
impl ContextMenu {
|
||||||
@@ -77,8 +78,7 @@ impl ContextMenu {
|
|||||||
layout: &mut Layout,
|
layout: &mut Layout,
|
||||||
parser_state: &mut ParserState,
|
parser_state: &mut ParserState,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let blueprint =
|
let blueprint = parser_state.context_menu_create_blueprint(¶ms.template_name, ¶ms.template_params)?;
|
||||||
parser_state.context_menu_create_blueprint(¶ms.template_name, ¶ms.template_params, params.position)?;
|
|
||||||
|
|
||||||
let globals = layout.state.globals.clone();
|
let globals = layout.state.globals.clone();
|
||||||
|
|
||||||
@@ -94,19 +94,20 @@ impl ContextMenu {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let content = self.window.get_content();
|
let content = self.window.get_content();
|
||||||
let doc_params = doc_params(&globals, params.on_custom_attribs.clone());
|
let doc_params = doc_params(&globals);
|
||||||
|
|
||||||
let mut state = parser::parse_from_assets(&doc_params, layout, content.id)?;
|
let mut inner_parser = parser::parse_from_assets(&doc_params, layout, content.id)?;
|
||||||
|
|
||||||
let id_buttons = state.get_widget_id("buttons")?;
|
let id_buttons = inner_parser.get_widget_id("buttons")?;
|
||||||
|
|
||||||
for (idx, cell) in blueprint.cells.iter().enumerate() {
|
for (idx, cell) in blueprint.cells.iter().enumerate() {
|
||||||
let mut par = HashMap::new();
|
let mut par = HashMap::new();
|
||||||
par.insert(Rc::from("text"), cell.title.generate(&mut globals.i18n()));
|
par.insert(Rc::from("text"), cell.title.generate(&mut globals.i18n()));
|
||||||
let data_cell = state.parse_template(&doc_params, "Cell", layout, id_buttons, par)?;
|
let mut data_cell = inner_parser.parse_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();
|
||||||
|
parser_state.data.take_results_from(&mut data_cell);
|
||||||
self
|
self
|
||||||
.tasks
|
.tasks
|
||||||
.handle_button(&button, Task::ActionClicked(cell.action_name.clone()));
|
.handle_button(&button, Task::ActionClicked(cell.action_name.clone()));
|
||||||
@@ -121,7 +122,7 @@ impl ContextMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if idx < blueprint.cells.len() - 1 {
|
if idx < blueprint.cells.len() - 1 {
|
||||||
state.parse_template(&doc_params, "Separator", layout, id_buttons, Default::default())?;
|
inner_parser.parse_template(&doc_params, "Separator", layout, id_buttons, Default::default())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -130,14 +131,20 @@ impl ContextMenu {
|
|||||||
pub fn tick(&mut self, layout: &mut Layout, parser_state: &mut ParserState) -> anyhow::Result<TickResult> {
|
pub fn tick(&mut self, layout: &mut Layout, parser_state: &mut ParserState) -> anyhow::Result<TickResult> {
|
||||||
if let Some(mut p) = self.pending_open.take() {
|
if let Some(mut p) = self.pending_open.take() {
|
||||||
self.open_process(&mut p, layout, parser_state)?;
|
self.open_process(&mut p, layout, parser_state)?;
|
||||||
|
let _ = self.tasks.drain();
|
||||||
|
return Ok(TickResult::Opened);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = TickResult::default();
|
let mut result = TickResult::default();
|
||||||
|
|
||||||
for task in self.tasks.drain() {
|
for task in self.tasks.drain() {
|
||||||
match task {
|
match task {
|
||||||
Task::ActionClicked(action_name) => {
|
Task::ActionClicked(Some(action_name)) => {
|
||||||
result.action_name = action_name;
|
result = TickResult::Action(action_name);
|
||||||
|
self.close();
|
||||||
|
}
|
||||||
|
Task::ActionClicked(None) => {
|
||||||
|
result = TickResult::Closed;
|
||||||
self.close();
|
self.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ use crate::{
|
|||||||
layout::{Layout, LayoutTask, LayoutTasks, WidgetPair},
|
layout::{Layout, LayoutTask, LayoutTasks, WidgetPair},
|
||||||
parser::{self, Fetchable, ParserState},
|
parser::{self, Fetchable, ParserState},
|
||||||
widget::{
|
widget::{
|
||||||
EventResult,
|
|
||||||
div::WidgetDiv,
|
div::WidgetDiv,
|
||||||
label::WidgetLabel,
|
label::WidgetLabel,
|
||||||
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
rectangle::{WidgetRectangle, WidgetRectangleParams},
|
||||||
|
EventResult,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -249,4 +249,7 @@ pub struct GeneralConfig {
|
|||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub xwayland_by_default: bool,
|
pub xwayland_by_default: bool,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub context_menu_hold_and_release: bool,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<layout>
|
<layout>
|
||||||
<macro name="keycap_rect"
|
<macro name="keycap_rect"
|
||||||
margin="2" width="100%" overflow="hidden" box_sizing="border_box"
|
margin="2" width="100%" overflow="hidden" box_sizing="border_box"
|
||||||
border_color="~color_accent_translucent" border="2" round="8" color="~color_accent_40" color2="~color_accent_10" gradient="vertical"
|
border_color="~color_accent_translucent" border="2" round="6" color="~color_accent_40" color2="~color_accent_10" gradient="vertical"
|
||||||
align_items="center" justify_content="center" />
|
align_items="center" justify_content="center" />
|
||||||
|
|
||||||
<macro name="tray_rect"
|
<macro name="tray_rect"
|
||||||
margin="2" width="100%" overflow="hidden" box_sizing="border_box"
|
margin="2" width="100%" overflow="hidden" box_sizing="border_box"
|
||||||
border_color="~color_accent_translucent" border="2" round="8" color="~color_bg" color2="~color_accent_10" gradient="vertical"
|
border_color="~color_accent_translucent" border="2" round="6" color="~color_bg" color2="~color_accent_10" gradient="vertical"
|
||||||
align_items="center" justify_content="center" />
|
align_items="center" justify_content="center" />
|
||||||
|
|
||||||
<macro name="keycap_div"
|
<macro name="keycap_div"
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
<template name="KeySpecial">
|
<template name="KeySpecial">
|
||||||
<div macro="keycap_div">
|
<div macro="keycap_div">
|
||||||
<rectangle id="${id}" macro="keycap_rect">
|
<rectangle id="${id}" macro="keycap_rect">
|
||||||
<sprite color="~color_text" width="32" height="32" src="keyboard/${text}.svg" />
|
<sprite color="~color_text" width="21" height="21" src="keyboard/${text}.svg" />
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<template name="KeyLetter">
|
<template name="KeyLetter">
|
||||||
<div macro="keycap_div">
|
<div macro="keycap_div">
|
||||||
<rectangle id="${id}" macro="keycap_rect">
|
<rectangle id="${id}" macro="keycap_rect">
|
||||||
<label text="${text}" size="24" />
|
<label text="${text}" size="16" />
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -43,9 +43,9 @@
|
|||||||
<!-- Used for letter keys on layouts with AltGr. -->
|
<!-- Used for letter keys on layouts with AltGr. -->
|
||||||
<template name="KeyLetterAltGr">
|
<template name="KeyLetterAltGr">
|
||||||
<div macro="keycap_div">
|
<div macro="keycap_div">
|
||||||
<rectangle id="${id}" macro="keycap_rect" gap="4">
|
<rectangle id="${id}" macro="keycap_rect" gap="3">
|
||||||
<label text="${text}" size="24" />
|
<label text="${text}" size="16" />
|
||||||
<label color="~color_text_translucent" text="${text_altgr}" size="24" />
|
<label color="~color_text_translucent" text="${text_altgr}" size="16" />
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -54,9 +54,9 @@
|
|||||||
<!-- Used for number & symbol keys on layouts without AltGr. -->
|
<!-- Used for number & symbol keys on layouts without AltGr. -->
|
||||||
<template name="KeySymbol">
|
<template name="KeySymbol">
|
||||||
<div macro="keycap_div">
|
<div macro="keycap_div">
|
||||||
<rectangle id="${id}" macro="keycap_rect" gap="4">
|
<rectangle id="${id}" macro="keycap_rect" gap="3">
|
||||||
<label color="~color_text_translucent" text="${text_shift}" size="24" />
|
<label color="~color_text_translucent" text="${text_shift}" size="16" />
|
||||||
<label text="${text}" size="24" />
|
<label text="${text}" size="16" />
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -67,149 +67,139 @@
|
|||||||
<div macro="keycap_div">
|
<div macro="keycap_div">
|
||||||
<rectangle id="${id}" macro="keycap_rect" flex_direction="row" flex_wrap="wrap">
|
<rectangle id="${id}" macro="keycap_rect" flex_direction="row" flex_wrap="wrap">
|
||||||
<div width="50%" height="50%" align_items="center" justify_content="center">
|
<div width="50%" height="50%" align_items="center" justify_content="center">
|
||||||
<label color="~color_text_translucent" text="${text_shift}" size="24" />
|
<label color="~color_text_translucent" text="${text_shift}" size="16" />
|
||||||
</div>
|
</div>
|
||||||
<div width="50%" height="50%" align_items="center" justify_content="center" />
|
<div width="50%" height="50%" align_items="center" justify_content="center" />
|
||||||
<div width="50%" height="50%" align_items="center" justify_content="center">
|
<div width="50%" height="50%" align_items="center" justify_content="center">
|
||||||
<label text="${text}" size="24" />
|
<label text="${text}" size="16" />
|
||||||
</div>
|
</div>
|
||||||
<div width="50%" height="50%" align_items="center" justify_content="center">
|
<div width="50%" height="50%" align_items="center" justify_content="center">
|
||||||
<label color="~color_text_translucent" text="${text_altgr}" size="24" />
|
<label color="~color_text_translucent" text="${text_altgr}" size="16" />
|
||||||
</div>
|
</div>
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<macro name="button_style" border="2" border_color="~color_accent_translucent" color="~color_bg" round="8"
|
<macro name="button_style" border="2" border_color="~color_accent_translucent" color="~color_bg" round="6"
|
||||||
align_items="center" justify_content="center" padding="8" width="80" height="80" overflow="visible"/>
|
align_items="center" justify_content="center" padding="6" width="60" height="60" overflow="visible"/>
|
||||||
|
|
||||||
<macro name="menu_button_style" border="2" border_color="~color_accent_translucent" color="~color_bg" round="8"
|
<macro name="bg_rect" width="100%" color="~color_bg" round="10" border="2" border_color="~color_accent" />
|
||||||
align_items="center" justify_content="center" padding="8" width="100%" height="60" />
|
|
||||||
|
|
||||||
<macro name="bg_rect" width="100%" color="~color_bg" round="16" border="2" border_color="~color_accent" />
|
<blueprint name="menu_app">
|
||||||
<macro name="dropdown_root" new_pass="1" width="200" color="~color_bg" flex_direction="column" position="absolute" margin_top="80" display="none" />
|
<context_menu >
|
||||||
<macro name="dropdown_title" color="~color_faded_50" width="100%" padding="16" overflow="hidden" />
|
<!-- title text="${name}" /-->
|
||||||
|
<cell translation="BAR.TOGGLE_VISIBILITY" _release="::OverlayToggle ${name}" />
|
||||||
<template name="MenuButton">
|
<cell translation="BAR.RESET_POSITION" _release="::OverlayReset ${name}" />
|
||||||
<Button macro="menu_button_style" _release="${action}">
|
<cell translation="BAR.CLOSE_APP" _release="::WvrOverlayTermProcess ${name}" />
|
||||||
<label translation="${translation}" size="24" />
|
<cell translation="BAR.FORCE_CLOSE_APP" _release="::WvrOverlayKillProcess ${name}" />
|
||||||
</Button>
|
</context_menu>
|
||||||
</template>
|
</blueprint>
|
||||||
|
|
||||||
<!-- An app with a single icon. -->
|
<!-- An app with a single icon. -->
|
||||||
<template name="App">
|
<template name="App">
|
||||||
<div>
|
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _press="::ContextMenuOpen menu_app">
|
||||||
<Button macro="button_style" id="overlay_${idx}" _press="::OverlayToggle ${name}" _release="::ElementSetDisplay dropdown_${idx} none">
|
<sprite width="38" height="38" color="~text_color" src_ext="${icon}" />
|
||||||
<sprite width="56" height="56" color="~text_color" src_ext="${icon}" />
|
</Button>
|
||||||
</Button>
|
|
||||||
<div macro="dropdown_root" id="dropdown_${idx}">
|
|
||||||
<rectangle macro="dropdown_title">
|
|
||||||
<label text="${name}" weight="bold" size="24" />
|
|
||||||
</rectangle>
|
|
||||||
<MenuButton translation="BAR.TOGGLE_IN_SET" action="::OverlayToggle ${name}" />
|
|
||||||
<MenuButton translation="BAR.CLOSE" action="::WvrOverlayTermProcess ${name}" />
|
|
||||||
<MenuButton translation="BAR.FORCE_CLOSE" action="::WvrOverlayKillProcess ${name}" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<blueprint name="menu_screen">
|
||||||
|
<context_menu >
|
||||||
|
<!-- title text="${name}" /-->
|
||||||
|
<cell translation="BAR.TOGGLE_VISIBILITY" _press="::OverlayToggle ${name}" />
|
||||||
|
<cell translation="BAR.RESET_POSITION" _press="::OverlayReset ${name}" />
|
||||||
|
</context_menu>
|
||||||
|
</blueprint>
|
||||||
|
|
||||||
<!-- A screen with a shortened connector name, e.g. "H1" for HDMI-A-1 or "D2" for DP-2 -->
|
<!-- A screen with a shortened connector name, e.g. "H1" for HDMI-A-1 or "D2" for DP-2 -->
|
||||||
<template name="Screen">
|
<template name="Screen">
|
||||||
<div>
|
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _context_name="${name}" _press="::ContextMenuOpen menu_screen">
|
||||||
<Button macro="button_style" id="overlay_${idx}" _press="::OverlayToggle ${name}" _release="::ElementSetDisplay dropdown_${idx} none">
|
<sprite width="38" height="38" color="~text_color" src_builtin="edit/screen.svg" />
|
||||||
<sprite width="56" height="56" color="~text_color" src_builtin="edit/screen.svg" />
|
<div position="absolute" margin_top="-7" margin_left="-1">
|
||||||
<div position="absolute" margin_top="-10">
|
<label text="${display}" size="18" color="~color_faded_20" weight="bold" />
|
||||||
<label text="${display}" size="26" color="~color_faded_20" weight="bold" />
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
<div macro="dropdown_root" id="dropdown_${idx}">
|
|
||||||
<rectangle macro="dropdown_title">
|
|
||||||
<label text="${name}" weight="bold" size="24" />
|
|
||||||
</rectangle>
|
|
||||||
<MenuButton translation="BAR.TOGGLE_IN_SET" action="::OverlayToggle ${name}" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<blueprint name="menu_panel">
|
||||||
|
<context_menu >
|
||||||
|
<!-- title text="${name}" /-->
|
||||||
|
<cell translation="BAR.TOGGLE_VISIBILITY" _release="::OverlayToggle ${name}" />
|
||||||
|
<cell translation="BAR.RESET_POSITION" _release="::OverlayReset ${name}" />
|
||||||
|
<cell translation="BAR.RELOAD_FROM_DISK" _release="::CustomOverlayReload ${name}" />
|
||||||
|
</context_menu>
|
||||||
|
</blueprint>
|
||||||
|
|
||||||
<template name="Panel">
|
<template name="Panel">
|
||||||
<div>
|
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _press="::ContextMenuOpen menu_panel">
|
||||||
<Button macro="button_style" id="overlay_${idx}" _press="::OverlayToggle ${name}" _release="::ElementSetDisplay dropdown_${idx} none">
|
<sprite width="38" height="38" color="~text_color" src_builtin="edit/panel.svg" />
|
||||||
<sprite width="56" height="56" color="~text_color" src_builtin="edit/panel.svg" />
|
</Button>
|
||||||
</Button>
|
|
||||||
<div macro="dropdown_root" id="dropdown_${idx}">
|
|
||||||
<rectangle macro="dropdown_title">
|
|
||||||
<label text="${name}" weight="bold" size="24" />
|
|
||||||
</rectangle>
|
|
||||||
<MenuButton translation="BAR.TOGGLE_IN_SET" action="::OverlayToggle ${name}" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<blueprint name="menu_mirror">
|
||||||
|
<context_menu >
|
||||||
|
<!-- title text="${name}" /-->
|
||||||
|
<cell translation="BAR.TOGGLE_VISIBILITY" _release="::OverlayToggle ${name}" />
|
||||||
|
<cell translation="BAR.RESET_POSITION" _release="::OverlayReset ${name}" />
|
||||||
|
<cell translation="BAR.CLOSE_MIRROR" _release="::OverlayDrop ${name}" />
|
||||||
|
</context_menu>
|
||||||
|
</blueprint>
|
||||||
|
|
||||||
<template name="Mirror">
|
<template name="Mirror">
|
||||||
<div>
|
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _press="::ContextMenuOpen menu_mirror">
|
||||||
<Button macro="button_style" id="overlay_${idx}" _press="::OverlayToggle ${name}" _release="::ElementSetDisplay dropdown_${idx} none">
|
<sprite width="38" height="38" color="~text_color" src_builtin="edit/mirror.svg" />
|
||||||
<sprite width="56" height="56" color="~text_color" src_builtin="edit/mirror.svg" />
|
<div position="absolute" margin_top="5" margin_left="13">
|
||||||
<div position="absolute" margin_top="7" margin_left="20">
|
<label text="${display}" size="20" color="~color_faded_20" weight="bold" />
|
||||||
<label text="${display}" size="26" color="~color_faded_20" weight="bold" />
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
<div macro="dropdown_root" id="dropdown_${idx}">
|
|
||||||
<rectangle macro="dropdown_title">
|
|
||||||
<label text="${name}" weight="bold" size="24" />
|
|
||||||
</rectangle>
|
|
||||||
<MenuButton translation="BAR.TOGGLE_IN_SET" action="::OverlayToggle ${name}" />
|
|
||||||
<MenuButton translation="BAR.CLOSE" action="::OverlayDrop ${name}" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="Set">
|
<template name="Set">
|
||||||
<Button macro="button_style" id="set_${idx}" _press="::SetSwitch ${idx}" tooltip="WATCH.SWITCH_TO_SET" tooltip_side="bottom">
|
<Button macro="button_style" id="set_${idx}" _press="::SetSwitch ${idx}" tooltip="WATCH.SWITCH_TO_SET" tooltip_side="bottom">
|
||||||
<sprite width="56" height="56" color="~text_color" src_builtin="watch/set2.svg" />
|
<sprite width="38" height="38" color="~text_color" src_builtin="watch/set2.svg" />
|
||||||
<div position="absolute" margin_top="16" margin_left="-8">
|
<div position="absolute" margin_top="10" margin_left="-7">
|
||||||
<label text="${display}" size="26" color="~color_faded_20" weight="bold" />
|
<label text="${display}" size="20" color="~color_faded_20" weight="bold" />
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<div flex_direction="column" interactable="0">
|
<div flex_direction="column" interactable="0">
|
||||||
<rectangle macro="bg_rect" padding="16" align_items="center" justify_content="space_between">
|
<rectangle macro="bg_rect" padding="10" align_items="center" justify_content="space_between">
|
||||||
<div gap="16">
|
<div gap="10">
|
||||||
<Button macro="button_style" id="btn_dashboard" _press="::DashToggle">
|
<Button macro="button_style" id="btn_dashboard" _press="::DashToggle">
|
||||||
<sprite width="56" height="56" color="~text_color" src="watch/wayvr_dashboard_mono.svg" />
|
<sprite width="38" height="38" color="~text_color" src="watch/wayvr_dashboard_mono.svg" />
|
||||||
</Button>
|
</Button>
|
||||||
<VerticalSeparator />
|
<VerticalSeparator />
|
||||||
<div id="panels_root" gap="8">
|
<div id="panels_root" gap="6">
|
||||||
<Screen idx="0" display="H1" name="HDMI-A-1" />
|
<Screen idx="0" display="H1" name="HDMI-A-1" />
|
||||||
<Screen idx="1" display="D2" name="Screen: DP-2" />
|
<Screen idx="1" display="D2" name="Screen: DP-2" />
|
||||||
<Mirror idx="1" display="1" name="M1" />
|
<Mirror idx="1" display="1" name="M1" />
|
||||||
<Panel idx="1" display="Test" name="Test" />
|
<Panel idx="1" display="Test" name="Test" />
|
||||||
</div>
|
</div>
|
||||||
<VerticalSeparator />
|
<VerticalSeparator />
|
||||||
<div id="apps_root" gap="8">
|
<div id="apps_root" gap="6">
|
||||||
<App id="test1" name="Blender" icon="/usr/share/icons/hicolor/scalable/apps/blender-5.0.svg" />
|
<App id="test1" name="Blender" icon="/usr/share/icons/hicolor/scalable/apps/blender-5.0.svg" />
|
||||||
<App id="test2" name="Inkscape" icon="/usr/share/icons/hicolor/scalable/apps/org.inkscape.Inkscape.svg" />
|
<App id="test2" name="Inkscape" icon="/usr/share/icons/hicolor/scalable/apps/org.inkscape.Inkscape.svg" />
|
||||||
<App id="test3" name="GIMP" icon="/usr/share/icons/hicolor/scalable/apps/gimp.svg" />
|
<App id="test3" name="GIMP" icon="/usr/share/icons/hicolor/scalable/apps/gimp.svg" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="tray_root" flex_direction="row" gap="16">
|
<div id="tray_root" flex_direction="row" gap="10">
|
||||||
<div id="sets_root" flex_direction="row" gap="8">
|
<div id="sets_root" flex_direction="row" gap="6">
|
||||||
<Set idx="0" display="1" />
|
<Set idx="0" display="1" />
|
||||||
<Set idx="1" display="2" />
|
<Set idx="1" display="2" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<VerticalSeparator />
|
<VerticalSeparator />
|
||||||
|
|
||||||
<div flex_direction="column" gap="4" align_items="center">
|
<div flex_direction="column" gap="3" align_items="center">
|
||||||
<label text="23:59" _source="clock" _display="time" size="32" weight="bold" />
|
<label text="23:59" _source="clock" _display="time" size="21" weight="bold" />
|
||||||
<label text="Tuesday" _source="clock" _display="dow" size="22" />
|
<label text="Tuesday" _source="clock" _display="dow" size="15" />
|
||||||
<label text="22/2/2022" _source="clock" _display="date" size="22" />
|
<label text="22/2/2022" _source="clock" _display="date" size="15" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</rectangle>
|
</rectangle>
|
||||||
<div width="100%" height="20" interactable="0" />
|
<div width="100%" height="13" interactable="0" />
|
||||||
<rectangle id="keyboard_root" macro="bg_rect" flex_direction="column" padding="16">
|
<rectangle id="keyboard_root" macro="bg_rect" flex_direction="column" padding="10">
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</div>
|
</div>
|
||||||
</elements>
|
</elements>
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
"CENTER": "Center"
|
"CENTER": "Center"
|
||||||
},
|
},
|
||||||
"BAR": {
|
"BAR": {
|
||||||
"HIDE": "Hide",
|
"TOGGLE_VISIBILITY": "Toggle visibility",
|
||||||
"TOGGLE_IN_SET": "Toggle in set",
|
"RESET_POSITION": "Reset position",
|
||||||
"CLOSE": "Close",
|
"RELOAD_FROM_DISK": "Reload XML from disk",
|
||||||
"FORCE_CLOSE": "Force close"
|
"CLOSE_MIRROR": "Close mirror",
|
||||||
|
"CLOSE_APP": "Close app",
|
||||||
|
"FORCE_CLOSE_APP": "Force close app"
|
||||||
},
|
},
|
||||||
"DEFAULT": "Default",
|
"DEFAULT": "Default",
|
||||||
"DISABLED": "Disabled",
|
"DISABLED": "Disabled",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
collections::HashMap,
|
||||||
process::{Child, Command, Stdio},
|
process::{Child, Command, Stdio},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
@@ -16,19 +17,21 @@ use wgui::{
|
|||||||
},
|
},
|
||||||
layout::Layout,
|
layout::Layout,
|
||||||
log::LogErr,
|
log::LogErr,
|
||||||
parser::{CustomAttribsInfoOwned, Fetchable, ParserState},
|
parser::{self, AttribPair, CustomAttribsInfoOwned, Fetchable, ParserState},
|
||||||
taffy,
|
taffy,
|
||||||
widget::EventResult,
|
widget::EventResult,
|
||||||
|
windowing::context_menu::{ContextMenu, OpenParams},
|
||||||
};
|
};
|
||||||
use wlx_common::overlays::ToastTopic;
|
use wlx_common::overlays::ToastTopic;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
RUNNING,
|
RUNNING,
|
||||||
backend::{
|
backend::{
|
||||||
|
XrBackend,
|
||||||
task::{OverlayTask, PlayspaceTask, TaskType},
|
task::{OverlayTask, PlayspaceTask, TaskType},
|
||||||
wayvr::process::KillSignal,
|
wayvr::process::KillSignal,
|
||||||
},
|
},
|
||||||
overlays::{custom::create_custom, dashboard::DASH_NAME, toast::Toast, wayvr::WvrCommand},
|
overlays::{custom::create_custom, toast::Toast, wayvr::WvrCommand},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::hid::VirtualKey,
|
subsystem::hid::VirtualKey,
|
||||||
windowing::{OverlaySelector, backend::OverlayEventData, window::OverlayCategory},
|
windowing::{OverlaySelector, backend::OverlayEventData, window::OverlayCategory},
|
||||||
@@ -186,7 +189,8 @@ pub(super) fn setup_custom_button<S: 'static>(
|
|||||||
layout: &mut Layout,
|
layout: &mut Layout,
|
||||||
parser_state: &ParserState,
|
parser_state: &ParserState,
|
||||||
attribs: &CustomAttribsInfoOwned,
|
attribs: &CustomAttribsInfoOwned,
|
||||||
_app: &AppState,
|
context_menu: &Rc<RefCell<ContextMenu>>,
|
||||||
|
on_custom_attribs: &parser::OnCustomAttribsFunc,
|
||||||
button: Rc<ComponentButton>,
|
button: Rc<ComponentButton>,
|
||||||
) {
|
) {
|
||||||
for (name, kind, test_button, test_duration) in &BUTTON_EVENTS {
|
for (name, kind, test_button, test_duration) in &BUTTON_EVENTS {
|
||||||
@@ -202,6 +206,49 @@ pub(super) fn setup_custom_button<S: 'static>(
|
|||||||
let button = button.clone();
|
let button = button.clone();
|
||||||
|
|
||||||
let callback: EventCallback<AppState, S> = match command {
|
let callback: EventCallback<AppState, S> = match command {
|
||||||
|
"::ContextMenuOpen" => {
|
||||||
|
let Some(template_name) = args.next() else {
|
||||||
|
log::warn!(
|
||||||
|
"{command} has incorrect arguments. Should be: {command} <context_menu>"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// pass attribs with key `_context_{name}` to the context_menu template
|
||||||
|
let mut template_params = HashMap::new();
|
||||||
|
for AttribPair { attrib, value } in &attribs.pairs {
|
||||||
|
const PREFIX: &'static str = "_context_";
|
||||||
|
if attrib.starts_with(PREFIX) {
|
||||||
|
template_params.insert(attrib[PREFIX.len()..].into(), value.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log::warn!("Context params: {template_params:?}");
|
||||||
|
|
||||||
|
let template_name: Rc<str> = template_name.into();
|
||||||
|
let context_menu = context_menu.clone();
|
||||||
|
let on_custom_attribs = on_custom_attribs.clone();
|
||||||
|
|
||||||
|
Box::new({
|
||||||
|
move |_common, data, _app, _| {
|
||||||
|
context_menu.borrow_mut().open(OpenParams {
|
||||||
|
on_custom_attribs: Some(on_custom_attribs.clone()),
|
||||||
|
template_name: template_name.clone(),
|
||||||
|
template_params: template_params.clone(),
|
||||||
|
position: data.metadata.get_mouse_pos_absolute().unwrap(), //want panic
|
||||||
|
});
|
||||||
|
Ok(EventResult::Consumed)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"::ContextMenuClose" => {
|
||||||
|
let context_menu = context_menu.clone();
|
||||||
|
|
||||||
|
Box::new(move |_common, _data, _app, _| {
|
||||||
|
context_menu.borrow_mut().close();
|
||||||
|
|
||||||
|
Ok(EventResult::Consumed)
|
||||||
|
})
|
||||||
|
}
|
||||||
"::ElementSetDisplay" => {
|
"::ElementSetDisplay" => {
|
||||||
let (Some(id), Some(value)) = (args.next(), args.next()) else {
|
let (Some(id), Some(value)) = (args.next(), args.next()) else {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
@@ -286,6 +333,8 @@ pub(super) fn setup_custom_button<S: 'static>(
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log::warn!("{command} {arg}");
|
||||||
|
|
||||||
Box::new(move |_common, data, app, _| {
|
Box::new(move |_common, data, app, _| {
|
||||||
if !test_button(data) || !test_duration(&button, app) {
|
if !test_button(data) || !test_duration(&button, app) {
|
||||||
return Ok(EventResult::Pass);
|
return Ok(EventResult::Pass);
|
||||||
@@ -506,6 +555,23 @@ pub(super) fn setup_custom_button<S: 'static>(
|
|||||||
RUNNING.store(false, Ordering::Relaxed);
|
RUNNING.store(false, Ordering::Relaxed);
|
||||||
Ok(EventResult::Consumed)
|
Ok(EventResult::Consumed)
|
||||||
}),
|
}),
|
||||||
|
"::Restart" => Box::new(move |_common, data, app, _| {
|
||||||
|
if !test_button(data) || !test_duration(&button, app) {
|
||||||
|
return Ok(EventResult::Pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
let runtime = match app.xr_backend {
|
||||||
|
XrBackend::OpenVR => "--openvr",
|
||||||
|
XrBackend::OpenXR => "--openxr",
|
||||||
|
};
|
||||||
|
|
||||||
|
Command::new("/proc/self/exe")
|
||||||
|
.arg(runtime) // ensure same runtime
|
||||||
|
.arg("--replace") // SIGTERM the previous process
|
||||||
|
.arg("--show");
|
||||||
|
|
||||||
|
Ok(EventResult::Consumed)
|
||||||
|
}),
|
||||||
"::SendKey" => {
|
"::SendKey" => {
|
||||||
let Some(key) = args.next().and_then(|s| VirtualKey::from_str(s).ok()) else {
|
let Some(key) = args.next().and_then(|s| VirtualKey::from_str(s).ok()) else {
|
||||||
log::error!("{command} has bad/missing arguments");
|
log::error!("{command} has bad/missing arguments");
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ use wgui::{
|
|||||||
},
|
},
|
||||||
gfx::cmd::WGfxClearMode,
|
gfx::cmd::WGfxClearMode,
|
||||||
layout::{Layout, LayoutParams, LayoutUpdateParams, WidgetID},
|
layout::{Layout, LayoutParams, LayoutUpdateParams, WidgetID},
|
||||||
parser::{CustomAttribsInfoOwned, Fetchable, ParseDocumentExtra, ParserState},
|
parser::{self, CustomAttribsInfoOwned, Fetchable, ParseDocumentExtra, ParserState},
|
||||||
renderer_vk::context::Context as WguiContext,
|
renderer_vk::context::Context as WguiContext,
|
||||||
widget::{EventResult, label::WidgetLabel},
|
widget::{EventResult, label::WidgetLabel},
|
||||||
|
windowing::context_menu::{self, ContextMenu},
|
||||||
};
|
};
|
||||||
use wlx_common::overlays::{BackendAttrib, BackendAttribValue};
|
use wlx_common::overlays::{BackendAttrib, BackendAttribValue};
|
||||||
use wlx_common::timestep::Timestep;
|
use wlx_common::timestep::Timestep;
|
||||||
@@ -59,7 +60,9 @@ pub struct GuiPanel<S> {
|
|||||||
has_focus: [bool; 2],
|
has_focus: [bool; 2],
|
||||||
last_content_size: Vec2,
|
last_content_size: Vec2,
|
||||||
custom_elems: Rc<RefCell<Vec<CustomAttribsInfoOwned>>>,
|
custom_elems: Rc<RefCell<Vec<CustomAttribsInfoOwned>>>,
|
||||||
|
context_menu: Rc<RefCell<ContextMenu>>,
|
||||||
on_custom_attrib: Option<OnCustomAttribFunc>,
|
on_custom_attrib: Option<OnCustomAttribFunc>,
|
||||||
|
on_custom_attrib_inner: parser::OnCustomAttribsFunc,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type OnCustomIdFunc<S> = Box<
|
pub type OnCustomIdFunc<S> = Box<
|
||||||
@@ -105,6 +108,13 @@ impl<S: 'static> GuiPanel<S> {
|
|||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
let custom_elems = Rc::new(RefCell::new(vec![]));
|
let custom_elems = Rc::new(RefCell::new(vec![]));
|
||||||
|
|
||||||
|
let on_custom_attrib_inner: parser::OnCustomAttribsFunc = Rc::new({
|
||||||
|
let custom_elems = custom_elems.clone();
|
||||||
|
move |attribs| {
|
||||||
|
custom_elems.borrow_mut().push(attribs.to_owned());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let doc_params = wgui::parser::ParseDocumentParams {
|
let doc_params = wgui::parser::ParseDocumentParams {
|
||||||
globals: app.wgui_globals.clone(),
|
globals: app.wgui_globals.clone(),
|
||||||
path: if params.external_xml {
|
path: if params.external_xml {
|
||||||
@@ -113,12 +123,7 @@ impl<S: 'static> GuiPanel<S> {
|
|||||||
AssetPath::FileOrBuiltIn(path)
|
AssetPath::FileOrBuiltIn(path)
|
||||||
},
|
},
|
||||||
extra: wgui::parser::ParseDocumentExtra {
|
extra: wgui::parser::ParseDocumentExtra {
|
||||||
on_custom_attribs: Some(Rc::new({
|
on_custom_attribs: Some(on_custom_attrib_inner.clone()),
|
||||||
let custom_elems = custom_elems.clone();
|
|
||||||
move |attribs| {
|
|
||||||
custom_elems.borrow_mut().push(attribs.to_owned());
|
|
||||||
}
|
|
||||||
})),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -164,13 +169,16 @@ impl<S: 'static> GuiPanel<S> {
|
|||||||
last_content_size: Vec2::ZERO,
|
last_content_size: Vec2::ZERO,
|
||||||
doc_extra: Some(doc_params.extra),
|
doc_extra: Some(doc_params.extra),
|
||||||
custom_elems,
|
custom_elems,
|
||||||
|
context_menu: Default::default(),
|
||||||
on_custom_attrib: params.on_custom_attrib,
|
on_custom_attrib: params.on_custom_attrib,
|
||||||
|
on_custom_attrib_inner,
|
||||||
};
|
};
|
||||||
me.process_custom_elems(app);
|
me.process_custom_elems(app);
|
||||||
|
|
||||||
Ok(me)
|
Ok(me)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform initial setup on newly added elements.
|
||||||
pub fn process_custom_elems(&mut self, app: &mut AppState) {
|
pub fn process_custom_elems(&mut self, app: &mut AppState) {
|
||||||
let mut elems = self.custom_elems.borrow_mut();
|
let mut elems = self.custom_elems.borrow_mut();
|
||||||
for elem in elems.iter() {
|
for elem in elems.iter() {
|
||||||
@@ -186,7 +194,14 @@ impl<S: 'static> GuiPanel<S> {
|
|||||||
.parser_state
|
.parser_state
|
||||||
.fetch_component_from_widget_id_as::<ComponentButton>(elem.widget_id)
|
.fetch_component_from_widget_id_as::<ComponentButton>(elem.widget_id)
|
||||||
{
|
{
|
||||||
setup_custom_button::<S>(&mut self.layout, &self.parser_state, elem, app, button);
|
setup_custom_button::<S>(
|
||||||
|
&mut self.layout,
|
||||||
|
&self.parser_state,
|
||||||
|
elem,
|
||||||
|
&self.context_menu,
|
||||||
|
&self.on_custom_attrib_inner,
|
||||||
|
button,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(on_custom_attrib) = &self.on_custom_attrib {
|
if let Some(on_custom_attrib) = &self.on_custom_attrib {
|
||||||
@@ -268,6 +283,14 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||||||
return Ok(ShouldRender::Unable);
|
return Ok(ShouldRender::Unable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let tick_result = self
|
||||||
|
.context_menu
|
||||||
|
.borrow_mut()
|
||||||
|
.tick(&mut self.layout, &mut self.parser_state)?;
|
||||||
|
if matches!(tick_result, context_menu::TickResult::Opened) {
|
||||||
|
self.process_custom_elems(app);
|
||||||
|
}
|
||||||
|
|
||||||
if !self
|
if !self
|
||||||
.last_content_size
|
.last_content_size
|
||||||
.abs_diff_eq(self.layout.content_size, 0.1 /* pixels */)
|
.abs_diff_eq(self.layout.content_size, 0.1 /* pixels */)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ use super::{
|
|||||||
layout::{self, KeyCapType},
|
layout::{self, KeyCapType},
|
||||||
};
|
};
|
||||||
|
|
||||||
const PIXELS_PER_UNIT: f32 = 80.;
|
const PIXELS_PER_UNIT: f32 = 60.;
|
||||||
|
|
||||||
fn new_doc_params(panel: &mut GuiPanel<KeyboardState>) -> ParseDocumentParams<'static> {
|
fn new_doc_params(panel: &mut GuiPanel<KeyboardState>) -> ParseDocumentParams<'static> {
|
||||||
ParseDocumentParams {
|
ParseDocumentParams {
|
||||||
@@ -335,7 +335,10 @@ pub(super) fn create_keyboard_panel(
|
|||||||
("Screen", panels_root)
|
("Screen", panels_root)
|
||||||
}
|
}
|
||||||
OverlayCategory::Mirror => {
|
OverlayCategory::Mirror => {
|
||||||
params.insert("display".into(), meta.name.as_ref().into());
|
params.insert(
|
||||||
|
"display".into(),
|
||||||
|
(*meta.name).chars().last().unwrap().to_string().into(),
|
||||||
|
);
|
||||||
("Mirror", panels_root)
|
("Mirror", panels_root)
|
||||||
}
|
}
|
||||||
OverlayCategory::Panel => ("Panel", panels_root),
|
OverlayCategory::Panel => ("Panel", panels_root),
|
||||||
|
|||||||
Reference in New Issue
Block a user