diff --git a/dash-frontend/assets/gui/view/popup_window.xml b/dash-frontend/assets/gui/view/popup_window.xml
index e373a2f4..e52f57ab 100644
--- a/dash-frontend/assets/gui/view/popup_window.xml
+++ b/dash-frontend/assets/gui/view/popup_window.xml
@@ -41,7 +41,8 @@
gradient="vertical"
position="relative"
>
-
+
+
diff --git a/dash-frontend/src/tab/settings/tab_controls.rs b/dash-frontend/src/tab/settings/tab_controls.rs
index 4dce6a9d..b4c36b39 100644
--- a/dash-frontend/src/tab/settings/tab_controls.rs
+++ b/dash-frontend/src/tab/settings/tab_controls.rs
@@ -80,12 +80,18 @@ fn create_input_profiles_button(
impl State {
pub fn mount(par: SettingsMountParams) -> anyhow::Result
{
+ let tasks = Tasks::::new();
+ let popup = PopupHolder::::default();
+
let c = options_category(
par.mp,
par.id_parent,
"APP_SETTINGS.CONTROLS",
"dashboard/controller.svg",
)?;
+ if par.feats.openxr {
+ create_input_profiles_button(par.mp, c, tasks.clone(), &popup)?;
+ }
options_dropdown::(par.mp, c, &SettingType::KeyboardMiddleClick)?;
options_dropdown::(par.mp, c, &SettingType::HandsfreePointer)?;
options_checkbox(par.mp, c, SettingType::FocusFollowsMouseMode)?;
@@ -111,13 +117,6 @@ impl State {
options_slider_i32(par.mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50)?;
- let tasks = Tasks::::new();
- let popup = PopupHolder::::default();
-
- if par.feats.openxr {
- create_input_profiles_button(par.mp, c, tasks.clone(), &popup)?;
- }
-
Ok(State {
popup_input_profiles: popup,
frontend_tasks: par.frontend_tasks.clone(),
diff --git a/dash-frontend/src/util/popup_manager.rs b/dash-frontend/src/util/popup_manager.rs
index 7f1ab24e..d2160455 100644
--- a/dash-frontend/src/util/popup_manager.rs
+++ b/dash-frontend/src/util/popup_manager.rs
@@ -6,11 +6,12 @@ use std::{
use wgui::{
assets::AssetPath,
components::button::ComponentButton,
- event::EventAlterables,
+ event::{EventAlterables, StyleSetRequest},
globals::WguiGlobals,
i18n::Translation,
layout::{Layout, LayoutTask, LayoutTasks, WidgetID},
parser::{Fetchable, ParseDocumentParams, ParserState},
+ taffy::Rect,
widget::label::WidgetLabel,
};
use wlx_common::config::GeneralConfig;
@@ -187,19 +188,33 @@ pub struct PopupContentFuncData<'a> {
type PopupClosedCallback = Box;
type OnContentCallback = Box anyhow::Result>;
+#[derive(Clone, Default)]
+pub enum PopupPadding {
+ #[default]
+ Normal,
+ None,
+}
+
+#[derive(Default, Clone)]
+pub struct MountPopupOnceParamsExtra {
+ pub padding: PopupPadding,
+}
+
// we need to implement Clone here, but the underlying function can be called only once.
// on_content will be cleared after the first call
#[derive(Clone)]
pub struct MountPopupOnceParams {
title: Translation,
on_content: Rc>>,
+ extra: MountPopupOnceParamsExtra,
}
impl MountPopupOnceParams {
- pub fn new(title: Translation, on_content: OnContentCallback) -> Self {
+ pub fn new(title: Translation, on_content: OnContentCallback, extra: MountPopupOnceParamsExtra) -> Self {
Self {
title,
on_content: Rc::new(RefCell::new(Some(on_content))),
+ extra,
}
}
}
@@ -257,6 +272,7 @@ impl PopupManager {
layout: &mut Layout,
frontend_tasks: &FrontendTasks,
popup_title: &Translation,
+ popup_padding: PopupPadding,
) -> anyhow::Result<(PopupHandle, WidgetID /* content widget ID */)> {
let doc_params = &ParseDocumentParams {
globals: globals.clone(),
@@ -268,6 +284,16 @@ impl PopupManager {
let id_root = state.get_widget_id("root")?;
let id_content = state.get_widget_id("content")?;
+ let padding = match popup_padding {
+ PopupPadding::Normal => 16.0,
+ PopupPadding::None => 0.0,
+ };
+
+ layout.tasks.push(LayoutTask::SetWidgetStyle(
+ id_content,
+ StyleSetRequest::Padding(Rect::length(padding)),
+ ));
+
{
let mut label_title = state.fetch_widget_as::(&layout.state, "popup_title")?;
label_title.set_text_simple(&mut globals.get(), popup_title.clone());
@@ -330,7 +356,8 @@ impl PopupManager {
anyhow::bail!("mount_popup_once called more than once");
};
- let (popup_handle, id_content) = self.mount_popup_prepare(globals, layout, frontend_tasks, ¶ms.title)?;
+ let (popup_handle, id_content) =
+ self.mount_popup_prepare(globals, layout, frontend_tasks, ¶ms.title, params.extra.padding)?;
// mount user-set popup content
let closed_callback = on_content_func(PopupContentFuncData {
diff --git a/dash-frontend/src/views/app_launcher.rs b/dash-frontend/src/views/app_launcher.rs
index af9c398b..9363f61c 100644
--- a/dash-frontend/src/views/app_launcher.rs
+++ b/dash-frontend/src/views/app_launcher.rs
@@ -453,5 +453,6 @@ pub fn mount_popup(frontend_tasks: FrontendTasks, globals: WguiGlobals, entry: D
popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout))
}),
+ Default::default(), /* extra */
)));
}
diff --git a/dash-frontend/src/views/bindings.rs b/dash-frontend/src/views/bindings.rs
index 8817b62b..4f6be755 100644
--- a/dash-frontend/src/views/bindings.rs
+++ b/dash-frontend/src/views/bindings.rs
@@ -1,5 +1,6 @@
use std::{borrow::Cow, collections::HashMap, rc::Rc};
+use glam::Vec2;
use wgui::{
assets::AssetPath,
components::button::{ButtonClickEvent, ComponentButton},
@@ -22,7 +23,8 @@ use crate::{
tab::settings::horiz_cell,
util::{
openxr_bindings_schema::{ClickType, Component, IdentifierType, ParsedOpenXrInputPath, Profile, Side},
- popup_manager::{MountPopupOnceParams, PopupHolder},
+ popup_manager::{MountPopupOnceParams, MountPopupOnceParamsExtra, PopupHolder, PopupPadding},
+ wgui_simple,
},
views::{ViewTrait, ViewUpdateParams},
};
@@ -85,7 +87,7 @@ impl ViewTrait for View {
}
// Dropdown handling
- if let TickResult::Action(name) = self.context_menu.tick(&mut par.layout, &mut self.parser_state)?
+ if let TickResult::Action(name) = self.context_menu.tick(par.layout, &mut self.parser_state)?
&& let (Some(action), Some(_), Some(action_name), Some(side), Some(value)) = {
let mut s = name.splitn(5, ';');
(s.next(), s.next(), s.next(), s.next(), s.next())
@@ -95,8 +97,8 @@ impl ViewTrait for View {
log::warn!("{action_name}");
- let mut cur_profile = &mut self.profiles[self.cur_profile_idx];
- let action_mut = get_action_mut(&mut cur_profile, action_name);
+ let cur_profile = &mut self.profiles[self.cur_profile_idx];
+ let action_mut = get_action_mut(cur_profile, action_name);
let side_mut = if side == "right" {
&mut action_mut.right
} else {
@@ -163,14 +165,6 @@ impl View {
let list_parent = parser_state.fetch_widget(¶ms.layout.state, "list_parent")?.id;
let tasks = Tasks::new();
- {
- let mut title_label = parser_state.fetch_widget_as::(¶ms.layout.state, "controller_type")?;
- title_label.set_text_simple(
- &mut params.globals.get(),
- Translation::from_raw_text_rc(params.profile.title.clone()),
- );
- }
-
tasks.handle_button(
&parser_state.fetch_component_as::("btn_save")?,
Task::Save,
@@ -267,7 +261,7 @@ pub fn mount_popup(
frontend_tasks
.clone()
.push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new(
- Translation::from_translation_key("APP_SETTINGS.INPUT_PROFILES"),
+ Translation::from_raw_text_rc(profile.title.clone()),
Box::new(move |data| {
let close_callback = popup.get_close_callback(data.layout);
let view = View::new(Params {
@@ -282,6 +276,9 @@ pub fn mount_popup(
popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout))
}),
+ MountPopupOnceParamsExtra {
+ padding: PopupPadding::None,
+ },
)));
}
@@ -367,16 +364,13 @@ fn input_controls_for_hand(
return Ok(()); // skip
}
- let current = current
- .map(|cur| ParsedOpenXrInputPath::try_from(cur).log_warn(cur).ok())
- .flatten();
+ let current = current.and_then(|cur| ParsedOpenXrInputPath::try_from(cur).log_warn(cur).ok());
let parent = horiz_cell(mp.layout, parent)?;
let available_components = current
.as_ref()
- .map(|par| profile.subpaths.get(&par.to_subpath()))
- .flatten()
+ .and_then(|par| profile.subpaths.get(&par.to_subpath()))
.map(|subp| subp.get_effective_components())
.unwrap_or_default();
@@ -387,8 +381,7 @@ fn input_controls_for_hand(
.filter_map(|(key, _)| {
key
.strip_prefix("/input/")
- .map(|ident| IdentifierType::try_from(ident).ok())
- .flatten()
+ .and_then(|ident| IdentifierType::try_from(ident).ok())
})
.collect::>();
@@ -430,11 +423,16 @@ fn subpath_dropdown(
let mut params: HashMap, Rc> = HashMap::new();
params.insert(Rc::from("id"), Rc::from(id.as_ref()));
- params.insert(
- Rc::from("translation"),
- Rc::from(format!("APP_SETTINGS.BINDINGS.{}", side.as_ref().to_uppercase())),
- );
params.insert(Rc::from("tooltip"), Rc::from("APP_SETTINGS.BINDINGS.SUBPATH"));
+ params.insert(Rc::from("min_width"), Rc::from("100"));
+
+ // left/right hand icon
+ wgui_simple::create_icon(
+ mp.layout,
+ parent,
+ Vec2::new(32.0, 32.0),
+ AssetPath::BuiltIn(&format!("dashboard/hand_{}.svg", side.as_ref().to_lowercase())),
+ )?;
mp.parser_state
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;
@@ -508,6 +506,7 @@ fn component_dropdown(
params.insert(Rc::from("id"), Rc::from(id.as_ref()));
params.insert(Rc::from("text"), Rc::from("・"));
params.insert(Rc::from("tooltip"), Rc::from("APP_SETTINGS.BINDINGS.COMPONENT"));
+ params.insert(Rc::from("min_width"), Rc::from("100"));
mp.parser_state
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;
@@ -561,6 +560,7 @@ fn clicks_dropdown(mp: &mut MacroParams, parent: WidgetID, action: Rc, curr
params.insert(Rc::from("id"), Rc::from(id.as_ref()));
params.insert(Rc::from("text"), Rc::from("・"));
params.insert(Rc::from("tooltip"), Rc::from("APP_SETTINGS.BINDINGS.CLICK.TYPE"));
+ params.insert(Rc::from("min_width"), Rc::from("100"));
mp.parser_state
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;
diff --git a/dash-frontend/src/views/dialog_box.rs b/dash-frontend/src/views/dialog_box.rs
index eba712af..86d58963 100644
--- a/dash-frontend/src/views/dialog_box.rs
+++ b/dash-frontend/src/views/dialog_box.rs
@@ -123,5 +123,6 @@ pub fn mount_popup(popup: PopupHolder, frontend_tasks: FrontendTasks, para
popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout))
}),
+ Default::default(), /* extra */
)));
}
diff --git a/dash-frontend/src/views/download_file.rs b/dash-frontend/src/views/download_file.rs
index 439f7b94..c2502451 100644
--- a/dash-frontend/src/views/download_file.rs
+++ b/dash-frontend/src/views/download_file.rs
@@ -261,5 +261,6 @@ pub fn mount_popup(
popup.set_view(data.handle, view, Some(on_view_close));
Ok(popup.get_close_callback(data.layout))
}),
+ Default::default(), /* extra */
)));
}
diff --git a/dash-frontend/src/views/game_launcher.rs b/dash-frontend/src/views/game_launcher.rs
index f16ca69b..2ffe4059 100644
--- a/dash-frontend/src/views/game_launcher.rs
+++ b/dash-frontend/src/views/game_launcher.rs
@@ -224,5 +224,6 @@ pub fn mount_popup(
popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout))
}),
+ Default::default(), /* extra */
)));
}
diff --git a/dash-frontend/src/views/input_profiles.rs b/dash-frontend/src/views/input_profiles.rs
index 11d6b626..8881f870 100644
--- a/dash-frontend/src/views/input_profiles.rs
+++ b/dash-frontend/src/views/input_profiles.rs
@@ -136,5 +136,6 @@ pub fn mount_popup(frontend_tasks: FrontendTasks, globals: WguiGlobals, popup: P
popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout))
}),
+ Default::default(), /* extra */
)));
}
diff --git a/dash-frontend/src/views/remote_skymap_downloader.rs b/dash-frontend/src/views/remote_skymap_downloader.rs
index 5dbaa9cf..10d91fef 100644
--- a/dash-frontend/src/views/remote_skymap_downloader.rs
+++ b/dash-frontend/src/views/remote_skymap_downloader.rs
@@ -393,5 +393,6 @@ pub fn mount_popup(
popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout))
}),
+ Default::default(), /* extra */
)));
}
diff --git a/dash-frontend/src/views/remote_skymap_list.rs b/dash-frontend/src/views/remote_skymap_list.rs
index 0ba02497..d834b5ed 100644
--- a/dash-frontend/src/views/remote_skymap_list.rs
+++ b/dash-frontend/src/views/remote_skymap_list.rs
@@ -297,5 +297,6 @@ pub fn mount_popup(
popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout))
}),
+ Default::default(), /* extra */
)));
}
diff --git a/dash-frontend/src/views/skymap_list.rs b/dash-frontend/src/views/skymap_list.rs
index 48999bca..e95f4ddd 100644
--- a/dash-frontend/src/views/skymap_list.rs
+++ b/dash-frontend/src/views/skymap_list.rs
@@ -265,5 +265,6 @@ pub fn mount_popup(frontend_tasks: FrontendTasks, globals: WguiGlobals, popup: P
popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout))
}),
+ Default::default(), /* extra */
)));
}
diff --git a/wgui/src/event.rs b/wgui/src/event.rs
index ea6e38a9..7557c8a2 100644
--- a/wgui/src/event.rs
+++ b/wgui/src/event.rs
@@ -107,6 +107,7 @@ impl Event {
pub enum StyleSetRequest {
Display(taffy::Display),
Margin(taffy::Rect),
+ Padding(taffy::Rect),
Width(taffy::Dimension),
Height(taffy::Dimension),
Size(taffy::Size),
diff --git a/wgui/src/layout.rs b/wgui/src/layout.rs
index 45870def..1eb05876 100644
--- a/wgui/src/layout.rs
+++ b/wgui/src/layout.rs
@@ -817,6 +817,9 @@ impl Layout {
event::StyleSetRequest::Margin(margin) => {
cur_style.margin = *margin;
}
+ event::StyleSetRequest::Padding(padding) => {
+ cur_style.padding = *padding;
+ }
event::StyleSetRequest::Width(val) => {
cur_style.size.width = *val;
}