Merge pull request #382 from wlx-team/feat-dash-tabbed-settings
dash-frontend: Tabbed settings, minor fixes
This commit is contained in:
BIN
dash-frontend/assets/dashboard/wayvr_dashboard.png
Normal file
BIN
dash-frontend/assets/dashboard/wayvr_dashboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -1,110 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="30"
|
||||
height="30"
|
||||
viewBox="0 0 7.9375004 7.9375004"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="dashboard_logo.svg"
|
||||
inkscape:export-filename="dashboard_logo.png"
|
||||
inkscape:export-xdpi="409.60001"
|
||||
inkscape:export-ydpi="409.60001"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="11.8125"
|
||||
inkscape:cy="16.78125"
|
||||
inkscape:window-width="1836"
|
||||
inkscape:window-height="1185"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
showguides="false">
|
||||
<inkscape:grid
|
||||
id="grid2"
|
||||
units="mm"
|
||||
originx="0"
|
||||
originy="0"
|
||||
spacingx="0.26458333"
|
||||
spacingy="0.26458333"
|
||||
empcolor="#0099e5"
|
||||
empopacity="0.30196078"
|
||||
color="#0099e5"
|
||||
opacity="0.14901961"
|
||||
empspacing="5"
|
||||
enabled="true"
|
||||
visible="true" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient1"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
style="stop-color:#ad70ff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop1" />
|
||||
<stop
|
||||
style="stop-color:#00ffff;stop-opacity:1;"
|
||||
offset="0.99844205"
|
||||
id="stop2" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1"
|
||||
id="linearGradient2"
|
||||
x1="0"
|
||||
y1="8.4666653"
|
||||
x2="8.4664993"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="scale(0.93751843,0.93750002)" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="back"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="font-variation-settings:'wght' 700;fill:url(#linearGradient2);stroke-width:0.468754;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="rect1"
|
||||
width="7.9380002"
|
||||
height="7.9375"
|
||||
x="0"
|
||||
y="0"
|
||||
rx="1.5874999"
|
||||
ry="1.5874999" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.05833;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1.5874998,3.7041664 v 1.3229167 h 1.3229166 v 1.3229165 l 1.3229165,-1e-7"
|
||||
id="path3"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.05833;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 1.5874998,2.6458332 V 1.5875 c 3.1749997,-2e-7 4.7624995,1.5874997 4.7624995,4.7624995 H 5.2916661"
|
||||
id="path4"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="front"
|
||||
style="stroke-width:2.11667;stroke-dasharray:none" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
@@ -8,7 +8,7 @@
|
||||
align_items="center"
|
||||
flex_grow="1"
|
||||
gap="24">
|
||||
<sprite src_builtin="dashboard/wayvr_dashboard.svg" width="96" height="96" />
|
||||
<sprite src_builtin="dashboard/wayvr_dashboard.png" width="96" height="96" />
|
||||
<label id="label_hello" size="32" weight="bold" />
|
||||
|
||||
<!-- main button list -->
|
||||
@@ -21,4 +21,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
@@ -28,7 +28,7 @@
|
||||
</template>
|
||||
|
||||
<template name="DangerButton">
|
||||
<Button id="${id}" color="#AA3333" height="32" tooltip="${translation}_HELP" padding="4" gap="8" >
|
||||
<Button id="${id}" color="#AA3333" height="32" tooltip="${translation}_HELP" padding="4" gap="8">
|
||||
<sprite src_builtin="${icon}" height="24" width="24" />
|
||||
<label align="left" translation="${translation}" weight="bold" min_width="200" />
|
||||
</Button>
|
||||
@@ -36,17 +36,27 @@
|
||||
|
||||
<template name="AutostartApp">
|
||||
<div id="${id}_root" flex_direction="row">
|
||||
<Button id="${id}" color="#AA3333" height="24" padding="4" margin_top="-2" margin_bottom="-2" >
|
||||
<Button id="${id}" color="#AA3333" height="24" padding="4" margin_top="-2" margin_bottom="-2">
|
||||
<sprite src_builtin="dashboard/close.svg" height="20" width="20" />
|
||||
</Button>
|
||||
<div padding_left="8" >
|
||||
<label align="left" text="${text}" weight="bold" overflow="hidden"/>
|
||||
<div padding_left="8">
|
||||
<label align="left" text="${text}" weight="bold" overflow="hidden" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<elements>
|
||||
<TabTitle translation="SETTINGS" icon="dashboard/settings.svg" />
|
||||
<div flex_wrap="wrap" justify_content="stretch" gap="4" id="settings_root" />
|
||||
<div gap="4">
|
||||
<Tabs id="tabs">
|
||||
<Tab name="look_and_feel" translation="APP_SETTINGS.LOOK_AND_FEEL" sprite_src_builtin="dashboard/palette.svg" />
|
||||
<Tab name="features" translation="APP_SETTINGS.FEATURES" sprite_src_builtin="dashboard/options.svg" />
|
||||
<Tab name="controls" translation="APP_SETTINGS.CONTROLS" sprite_src_builtin="dashboard/controller.svg" />
|
||||
<Tab name="misc" translation="APP_SETTINGS.MISC" sprite_src_builtin="dashboard/blocks.svg" />
|
||||
<Tab name="autostart_apps" translation="APP_SETTINGS.AUTOSTART_APPS" sprite_src_builtin="dashboard/apps.svg" />
|
||||
<Tab name="troubleshooting" translation="APP_SETTINGS.TROUBLESHOOTING" sprite_src_builtin="dashboard/cpu.svg" />
|
||||
</Tabs>
|
||||
<div flex_wrap="wrap" justify_content="stretch" gap="4" id="settings_root" width="100%" />
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
@@ -81,7 +81,7 @@ fn on_app_click(
|
||||
state: Rc<RefCell<State>>,
|
||||
tasks: Tasks<Task>,
|
||||
) -> ButtonClickCallback {
|
||||
Box::new(move |_common, _evt| {
|
||||
Rc::new(move |_common, _evt| {
|
||||
frontend_tasks.push(FrontendTask::MountPopup(MountPopupParams {
|
||||
title: Translation::from_raw_text(&entry.app_name),
|
||||
on_content: {
|
||||
|
||||
@@ -4,8 +4,14 @@ use glam::Vec2;
|
||||
use strum::{AsRefStr, EnumProperty, EnumString, VariantArray};
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
components::{button::ComponentButton, checkbox::ComponentCheckbox, slider::ComponentSlider},
|
||||
components::{
|
||||
button::{ButtonClickEvent, ComponentButton},
|
||||
checkbox::ComponentCheckbox,
|
||||
slider::ComponentSlider,
|
||||
tabs::ComponentTabs,
|
||||
},
|
||||
event::{CallbackDataCommon, EventAlterables},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID},
|
||||
log::LogErr,
|
||||
@@ -21,6 +27,30 @@ use crate::{
|
||||
tab::{Tab, TabType},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
enum TabNameEnum {
|
||||
LookAndFeel,
|
||||
Features,
|
||||
Controls,
|
||||
Misc,
|
||||
AutostartApps,
|
||||
Troubleshooting,
|
||||
}
|
||||
|
||||
impl TabNameEnum {
|
||||
fn from_string(s: &str) -> Option<Self> {
|
||||
match s {
|
||||
"look_and_feel" => Some(TabNameEnum::LookAndFeel),
|
||||
"features" => Some(TabNameEnum::Features),
|
||||
"controls" => Some(TabNameEnum::Controls),
|
||||
"misc" => Some(TabNameEnum::Misc),
|
||||
"autostart_apps" => Some(TabNameEnum::AutostartApps),
|
||||
"troubleshooting" => Some(TabNameEnum::Troubleshooting),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Task {
|
||||
UpdateBool(SettingType, bool),
|
||||
UpdateFloat(SettingType, f32),
|
||||
@@ -31,6 +61,7 @@ enum Task {
|
||||
DeleteAllConfigs,
|
||||
RestartSoftware,
|
||||
RemoveAutostartApp(Rc<str>),
|
||||
SetTab(TabNameEnum),
|
||||
}
|
||||
|
||||
pub struct TabSettings<T> {
|
||||
@@ -49,22 +80,33 @@ impl<T> Tab<T> for TabSettings<T> {
|
||||
}
|
||||
|
||||
fn update(&mut self, frontend: &mut Frontend<T>, data: &mut T) -> anyhow::Result<()> {
|
||||
let config = frontend.interface.general_config(data);
|
||||
let mut changed = false;
|
||||
for task in self.tasks.drain() {
|
||||
match task {
|
||||
Task::SetTab(tab) => {
|
||||
self.set_tab(frontend, data, tab)?;
|
||||
}
|
||||
Task::UpdateBool(setting, n) => {
|
||||
setting.get_frontend_task().map(|task| frontend.tasks.push(task));
|
||||
if let Some(task) = setting.get_frontend_task() {
|
||||
frontend.tasks.push(task)
|
||||
}
|
||||
let config = frontend.interface.general_config(data);
|
||||
*setting.mut_bool(config) = n;
|
||||
changed = true;
|
||||
}
|
||||
Task::UpdateFloat(setting, n) => {
|
||||
setting.get_frontend_task().map(|task| frontend.tasks.push(task));
|
||||
if let Some(task) = setting.get_frontend_task() {
|
||||
frontend.tasks.push(task)
|
||||
}
|
||||
let config = frontend.interface.general_config(data);
|
||||
*setting.mut_f32(config) = n;
|
||||
changed = true;
|
||||
}
|
||||
Task::UpdateInt(setting, n) => {
|
||||
setting.get_frontend_task().map(|task| frontend.tasks.push(task));
|
||||
if let Some(task) = setting.get_frontend_task() {
|
||||
frontend.tasks.push(task)
|
||||
}
|
||||
let config = frontend.interface.general_config(data);
|
||||
*setting.mut_i32(config) = n;
|
||||
changed = true;
|
||||
}
|
||||
@@ -98,6 +140,7 @@ impl<T> Tab<T> for TabSettings<T> {
|
||||
self.state.get_widget_id(&format!("{button_id}_root")),
|
||||
) {
|
||||
self.app_button_ids.remove(idx);
|
||||
let config = frontend.interface.general_config(data);
|
||||
config.autostart_apps.remove(idx);
|
||||
frontend.layout.remove_widget(widget);
|
||||
changed = true;
|
||||
@@ -107,32 +150,32 @@ impl<T> Tab<T> for TabSettings<T> {
|
||||
}
|
||||
|
||||
// Dropdown handling
|
||||
if let TickResult::Action(name) = self.context_menu.tick(&mut frontend.layout, &mut self.state)? {
|
||||
if let (Some(setting), Some(id), Some(value), Some(text), Some(translated)) = {
|
||||
if let TickResult::Action(name) = self.context_menu.tick(&mut frontend.layout, &mut self.state)?
|
||||
&& let (Some(setting), Some(id), Some(value), Some(text), Some(translated)) = {
|
||||
let mut s = name.splitn(5, ';');
|
||||
(s.next(), s.next(), s.next(), s.next(), s.next())
|
||||
} {
|
||||
let mut label = self
|
||||
.state
|
||||
.fetch_widget_as::<WidgetLabel>(&frontend.layout.state, &format!("{id}_value"))?;
|
||||
let mut label = self
|
||||
.state
|
||||
.fetch_widget_as::<WidgetLabel>(&frontend.layout.state, &format!("{id}_value"))?;
|
||||
|
||||
let mut alterables = EventAlterables::default();
|
||||
let mut common = CallbackDataCommon {
|
||||
alterables: &mut alterables,
|
||||
state: &frontend.layout.state,
|
||||
};
|
||||
let mut alterables = EventAlterables::default();
|
||||
let mut common = CallbackDataCommon {
|
||||
alterables: &mut alterables,
|
||||
state: &frontend.layout.state,
|
||||
};
|
||||
|
||||
let translation = Translation {
|
||||
text: text.into(),
|
||||
translated: translated == "1",
|
||||
};
|
||||
let translation = Translation {
|
||||
text: text.into(),
|
||||
translated: translated == "1",
|
||||
};
|
||||
|
||||
label.set_text(&mut common, translation);
|
||||
label.set_text(&mut common, translation);
|
||||
|
||||
let setting = SettingType::from_str(setting).expect("Invalid Enum string");
|
||||
setting.set_enum(config, value);
|
||||
changed = true;
|
||||
}
|
||||
let setting = SettingType::from_str(setting).expect("Invalid Enum string");
|
||||
let config = frontend.interface.general_config(data);
|
||||
setting.set_enum(config, value);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// Notify overlays of the change
|
||||
@@ -184,7 +227,7 @@ enum SettingType {
|
||||
}
|
||||
|
||||
impl SettingType {
|
||||
pub fn mut_bool<'a>(self, config: &'a mut GeneralConfig) -> &'a mut bool {
|
||||
pub fn mut_bool(self, config: &mut GeneralConfig) -> &mut bool {
|
||||
match self {
|
||||
Self::InvertScrollDirectionX => &mut config.invert_scroll_direction_x,
|
||||
Self::InvertScrollDirectionY => &mut config.invert_scroll_direction_y,
|
||||
@@ -213,7 +256,7 @@ impl SettingType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mut_f32<'a>(self, config: &'a mut GeneralConfig) -> &'a mut f32 {
|
||||
pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 {
|
||||
match self {
|
||||
Self::AnimationSpeed => &mut config.animation_speed,
|
||||
Self::RoundMultiplier => &mut config.round_multiplier,
|
||||
@@ -227,14 +270,14 @@ impl SettingType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mut_i32<'a>(self, config: &'a mut GeneralConfig) -> &'a mut i32 {
|
||||
pub fn mut_i32(self, config: &mut GeneralConfig) -> &mut i32 {
|
||||
match self {
|
||||
Self::ClickFreezeTimeMs => &mut config.click_freeze_time_ms,
|
||||
_ => panic!("Requested i32 for non-i32 SettingType"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_enum<'a>(self, config: &'a mut GeneralConfig, value: &str) {
|
||||
pub fn set_enum(self, config: &mut GeneralConfig, value: &str) {
|
||||
match self {
|
||||
Self::CaptureMethod => {
|
||||
config.capture_method = wlx_common::config::CaptureMethod::from_str(value).expect("Invalid enum value!")
|
||||
@@ -247,7 +290,7 @@ impl SettingType {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_enum_title<'a>(self, config: &'a mut GeneralConfig) -> Translation {
|
||||
fn get_enum_title(self, config: &mut GeneralConfig) -> Translation {
|
||||
match self {
|
||||
Self::CaptureMethod => Self::get_enum_title_inner(config.capture_method),
|
||||
Self::KeyboardMiddleClick => Self::get_enum_title_inner(config.keyboard_middle_click_mode),
|
||||
@@ -261,8 +304,8 @@ impl SettingType {
|
||||
{
|
||||
value
|
||||
.get_str("Translation")
|
||||
.map(|x| Translation::from_translation_key(x))
|
||||
.or_else(|| value.get_str("Text").map(|x| Translation::from_raw_text(x)))
|
||||
.map(Translation::from_translation_key)
|
||||
.or_else(|| value.get_str("Text").map(Translation::from_raw_text))
|
||||
.unwrap_or_else(|| Translation::from_raw_text(value.as_ref()))
|
||||
}
|
||||
|
||||
@@ -270,7 +313,7 @@ impl SettingType {
|
||||
where
|
||||
E: EnumProperty + AsRef<str>,
|
||||
{
|
||||
value.get_str("Tooltip").map(|x| Translation::from_translation_key(x))
|
||||
value.get_str("Tooltip").map(Translation::from_translation_key)
|
||||
}
|
||||
|
||||
/// Ok is translation, Err is raw text
|
||||
@@ -517,9 +560,9 @@ macro_rules! dropdown {
|
||||
}
|
||||
|
||||
let btn = $mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||
btn.on_click(Box::new({
|
||||
btn.on_click(Rc::new({
|
||||
let tasks = $mp.tasks.clone();
|
||||
move |_common, e| {
|
||||
move |_common, e: ButtonClickEvent| {
|
||||
tasks.push(Task::OpenContextMenu(
|
||||
e.mouse_pos_absolute.unwrap_or_default(),
|
||||
$options
|
||||
@@ -566,7 +609,7 @@ macro_rules! danger_button {
|
||||
.instantiate_template($mp.doc_params, "DangerButton", $mp.layout, $root, params)?;
|
||||
|
||||
let btn = $mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||
btn.on_click(Box::new({
|
||||
btn.on_click(Rc::new({
|
||||
let tasks = $mp.tasks.clone();
|
||||
move |_common, _e| {
|
||||
tasks.push($task);
|
||||
@@ -594,7 +637,7 @@ macro_rules! autostart_app {
|
||||
|
||||
$ids.push(id.clone());
|
||||
|
||||
btn.on_click(Box::new({
|
||||
btn.on_click(Rc::new({
|
||||
let tasks = $mp.tasks.clone();
|
||||
move |_common, _e| {
|
||||
tasks.push(Task::RemoveAutostartApp(id.clone()));
|
||||
@@ -613,121 +656,158 @@ struct MacroParams<'a> {
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
fn doc_params(globals: &'_ WguiGlobals) -> ParseDocumentParams<'_> {
|
||||
ParseDocumentParams {
|
||||
globals: globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/settings.xml"),
|
||||
extra: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> TabSettings<T> {
|
||||
pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, data: &mut T) -> anyhow::Result<Self> {
|
||||
fn set_tab(&mut self, frontend: &mut Frontend<T>, data: &mut T, name: TabNameEnum) -> anyhow::Result<()> {
|
||||
let root = self.state.get_widget_id("settings_root")?;
|
||||
frontend.layout.remove_children(root);
|
||||
let globals = frontend.layout.state.globals.clone();
|
||||
|
||||
let mut mp = MacroParams {
|
||||
layout: &mut frontend.layout,
|
||||
parser_state: &mut self.state,
|
||||
doc_params: &doc_params(&globals),
|
||||
config: frontend.interface.general_config(data),
|
||||
tasks: self.tasks.clone(),
|
||||
idx: 9001,
|
||||
};
|
||||
|
||||
match name {
|
||||
TabNameEnum::LookAndFeel => {
|
||||
let c = category!(mp, root, "APP_SETTINGS.LOOK_AND_FEEL", "dashboard/palette.svg")?;
|
||||
checkbox!(mp, c, SettingType::OpaqueBackground);
|
||||
checkbox!(mp, c, SettingType::HideUsername);
|
||||
checkbox!(mp, c, SettingType::HideGrabHelp);
|
||||
slider_f32!(mp, c, SettingType::AnimationSpeed, 0.5, 5.0, 0.1); // min, max, step
|
||||
slider_f32!(mp, c, SettingType::RoundMultiplier, 0.5, 5.0, 0.1);
|
||||
checkbox!(mp, c, SettingType::SetsOnWatch);
|
||||
checkbox!(mp, c, SettingType::UseSkybox);
|
||||
checkbox!(mp, c, SettingType::UsePassthrough);
|
||||
checkbox!(mp, c, SettingType::Clock12h);
|
||||
}
|
||||
TabNameEnum::Features => {
|
||||
let c = category!(mp, root, "APP_SETTINGS.FEATURES", "dashboard/options.svg")?;
|
||||
checkbox!(mp, c, SettingType::NotificationsEnabled);
|
||||
checkbox!(mp, c, SettingType::NotificationsSoundEnabled);
|
||||
checkbox!(mp, c, SettingType::KeyboardSoundEnabled);
|
||||
checkbox!(mp, c, SettingType::SpaceDragUnlocked);
|
||||
checkbox!(mp, c, SettingType::SpaceRotateUnlocked);
|
||||
slider_f32!(mp, c, SettingType::SpaceDragMultiplier, -10.0, 10.0, 0.5);
|
||||
checkbox!(mp, c, SettingType::BlockGameInput);
|
||||
checkbox!(mp, c, SettingType::BlockGameInputIgnoreWatch);
|
||||
}
|
||||
TabNameEnum::Controls => {
|
||||
let c = category!(mp, root, "APP_SETTINGS.CONTROLS", "dashboard/controller.svg")?;
|
||||
dropdown!(
|
||||
mp,
|
||||
c,
|
||||
SettingType::KeyboardMiddleClick,
|
||||
wlx_common::config::AltModifier::VARIANTS
|
||||
);
|
||||
checkbox!(mp, c, SettingType::FocusFollowsMouseMode);
|
||||
checkbox!(mp, c, SettingType::LeftHandedMouse);
|
||||
checkbox!(mp, c, SettingType::AllowSliding);
|
||||
checkbox!(mp, c, SettingType::InvertScrollDirectionX);
|
||||
checkbox!(mp, c, SettingType::InvertScrollDirectionY);
|
||||
slider_f32!(mp, c, SettingType::ScrollSpeed, 0.1, 5.0, 0.1);
|
||||
slider_f32!(mp, c, SettingType::LongPressDuration, 0.1, 2.0, 0.1);
|
||||
slider_f32!(mp, c, SettingType::PointerLerpFactor, 0.1, 1.0, 0.1);
|
||||
slider_f32!(mp, c, SettingType::XrClickSensitivity, 0.1, 1.0, 0.1);
|
||||
slider_f32!(mp, c, SettingType::XrClickSensitivityRelease, 0.1, 1.0, 0.1);
|
||||
slider_i32!(mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50);
|
||||
}
|
||||
TabNameEnum::Misc => {
|
||||
let c = category!(mp, root, "APP_SETTINGS.MISC", "dashboard/blocks.svg")?;
|
||||
dropdown!(
|
||||
mp,
|
||||
c,
|
||||
SettingType::CaptureMethod,
|
||||
wlx_common::config::CaptureMethod::VARIANTS
|
||||
);
|
||||
checkbox!(mp, c, SettingType::XwaylandByDefault);
|
||||
checkbox!(mp, c, SettingType::UprightScreenFix);
|
||||
checkbox!(mp, c, SettingType::DoubleCursorFix);
|
||||
checkbox!(mp, c, SettingType::ScreenRenderDown);
|
||||
}
|
||||
TabNameEnum::AutostartApps => {
|
||||
self.app_button_ids = vec![];
|
||||
|
||||
if !mp.config.autostart_apps.is_empty() {
|
||||
let c = category!(mp, root, "APP_SETTINGS.AUTOSTART_APPS", "dashboard/apps.svg")?;
|
||||
|
||||
for app in &mp.config.autostart_apps {
|
||||
autostart_app!(mp, c, app.name, self.app_button_ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
TabNameEnum::Troubleshooting => {
|
||||
let c = category!(mp, root, "APP_SETTINGS.TROUBLESHOOTING", "dashboard/cpu.svg")?;
|
||||
danger_button!(
|
||||
mp,
|
||||
c,
|
||||
"APP_SETTINGS.CLEAR_PIPEWIRE_TOKENS",
|
||||
"dashboard/display.svg",
|
||||
Task::ClearPipewireTokens
|
||||
);
|
||||
danger_button!(
|
||||
mp,
|
||||
c,
|
||||
"APP_SETTINGS.CLEAR_SAVED_STATE",
|
||||
"dashboard/binary.svg",
|
||||
Task::ClearSavedState
|
||||
);
|
||||
danger_button!(
|
||||
mp,
|
||||
c,
|
||||
"APP_SETTINGS.DELETE_ALL_CONFIGS",
|
||||
"dashboard/circle.svg",
|
||||
Task::DeleteAllConfigs
|
||||
);
|
||||
danger_button!(
|
||||
mp,
|
||||
c,
|
||||
"APP_SETTINGS.RESTART_SOFTWARE",
|
||||
"dashboard/refresh.svg",
|
||||
Task::RestartSoftware
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, _data: &mut T) -> anyhow::Result<Self> {
|
||||
let doc_params = ParseDocumentParams {
|
||||
globals: frontend.layout.state.globals.clone(),
|
||||
path: AssetPath::BuiltIn("gui/tab/settings.xml"),
|
||||
extra: Default::default(),
|
||||
};
|
||||
let mut parser_state = wgui::parser::parse_from_assets(&doc_params, &mut frontend.layout, parent_id)?;
|
||||
|
||||
let root = parser_state.get_widget_id("settings_root")?;
|
||||
let parser_state = wgui::parser::parse_from_assets(&doc_params, &mut frontend.layout, parent_id)?;
|
||||
let tasks = Tasks::default();
|
||||
let tabs = parser_state.fetch_component_as::<ComponentTabs>("tabs")?;
|
||||
tabs.on_select({
|
||||
let tasks = tasks.clone();
|
||||
Rc::new(move |_common, evt| {
|
||||
if let Some(tab) = TabNameEnum::from_string(&evt.name) {
|
||||
tasks.push(Task::SetTab(tab));
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
|
||||
let mut mp = MacroParams {
|
||||
layout: &mut frontend.layout,
|
||||
parser_state: &mut parser_state,
|
||||
doc_params: &doc_params,
|
||||
config: frontend.interface.general_config(data),
|
||||
tasks: Tasks::default(),
|
||||
idx: 9001,
|
||||
};
|
||||
|
||||
let c = category!(mp, root, "APP_SETTINGS.LOOK_AND_FEEL", "dashboard/palette.svg")?;
|
||||
checkbox!(mp, c, SettingType::OpaqueBackground);
|
||||
checkbox!(mp, c, SettingType::HideUsername);
|
||||
checkbox!(mp, c, SettingType::HideGrabHelp);
|
||||
slider_f32!(mp, c, SettingType::AnimationSpeed, 0.5, 5.0, 0.1); // min, max, step
|
||||
slider_f32!(mp, c, SettingType::RoundMultiplier, 0.5, 5.0, 0.1);
|
||||
checkbox!(mp, c, SettingType::SetsOnWatch);
|
||||
checkbox!(mp, c, SettingType::UseSkybox);
|
||||
checkbox!(mp, c, SettingType::UsePassthrough);
|
||||
checkbox!(mp, c, SettingType::Clock12h);
|
||||
|
||||
let c = category!(mp, root, "APP_SETTINGS.FEATURES", "dashboard/options.svg")?;
|
||||
checkbox!(mp, c, SettingType::NotificationsEnabled);
|
||||
checkbox!(mp, c, SettingType::NotificationsSoundEnabled);
|
||||
checkbox!(mp, c, SettingType::KeyboardSoundEnabled);
|
||||
checkbox!(mp, c, SettingType::SpaceDragUnlocked);
|
||||
checkbox!(mp, c, SettingType::SpaceRotateUnlocked);
|
||||
slider_f32!(mp, c, SettingType::SpaceDragMultiplier, -10.0, 10.0, 0.5);
|
||||
checkbox!(mp, c, SettingType::BlockGameInput);
|
||||
checkbox!(mp, c, SettingType::BlockGameInputIgnoreWatch);
|
||||
|
||||
let c = category!(mp, root, "APP_SETTINGS.CONTROLS", "dashboard/controller.svg")?;
|
||||
dropdown!(
|
||||
mp,
|
||||
c,
|
||||
SettingType::KeyboardMiddleClick,
|
||||
wlx_common::config::AltModifier::VARIANTS
|
||||
);
|
||||
checkbox!(mp, c, SettingType::FocusFollowsMouseMode);
|
||||
checkbox!(mp, c, SettingType::LeftHandedMouse);
|
||||
checkbox!(mp, c, SettingType::AllowSliding);
|
||||
checkbox!(mp, c, SettingType::InvertScrollDirectionX);
|
||||
checkbox!(mp, c, SettingType::InvertScrollDirectionY);
|
||||
slider_f32!(mp, c, SettingType::ScrollSpeed, 0.1, 5.0, 0.1);
|
||||
slider_f32!(mp, c, SettingType::LongPressDuration, 0.1, 2.0, 0.1);
|
||||
slider_f32!(mp, c, SettingType::PointerLerpFactor, 0.1, 1.0, 0.1);
|
||||
slider_f32!(mp, c, SettingType::XrClickSensitivity, 0.1, 1.0, 0.1);
|
||||
slider_f32!(mp, c, SettingType::XrClickSensitivityRelease, 0.1, 1.0, 0.1);
|
||||
slider_i32!(mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50);
|
||||
|
||||
let c = category!(mp, root, "APP_SETTINGS.MISC", "dashboard/blocks.svg")?;
|
||||
dropdown!(
|
||||
mp,
|
||||
c,
|
||||
SettingType::CaptureMethod,
|
||||
wlx_common::config::CaptureMethod::VARIANTS
|
||||
);
|
||||
checkbox!(mp, c, SettingType::XwaylandByDefault);
|
||||
checkbox!(mp, c, SettingType::UprightScreenFix);
|
||||
checkbox!(mp, c, SettingType::DoubleCursorFix);
|
||||
checkbox!(mp, c, SettingType::ScreenRenderDown);
|
||||
|
||||
let mut app_button_ids = vec![];
|
||||
|
||||
if !mp.config.autostart_apps.is_empty() {
|
||||
let c = category!(mp, root, "APP_SETTINGS.AUTOSTART_APPS", "dashboard/apps.svg")?;
|
||||
|
||||
for app in &mp.config.autostart_apps {
|
||||
autostart_app!(mp, c, app.name, app_button_ids);
|
||||
}
|
||||
}
|
||||
|
||||
let c = category!(mp, root, "APP_SETTINGS.TROUBLESHOOTING", "dashboard/cpu.svg")?;
|
||||
danger_button!(
|
||||
mp,
|
||||
c,
|
||||
"APP_SETTINGS.CLEAR_PIPEWIRE_TOKENS",
|
||||
"dashboard/display.svg",
|
||||
Task::ClearPipewireTokens
|
||||
);
|
||||
danger_button!(
|
||||
mp,
|
||||
c,
|
||||
"APP_SETTINGS.CLEAR_SAVED_STATE",
|
||||
"dashboard/binary.svg",
|
||||
Task::ClearSavedState
|
||||
);
|
||||
danger_button!(
|
||||
mp,
|
||||
c,
|
||||
"APP_SETTINGS.DELETE_ALL_CONFIGS",
|
||||
"dashboard/circle.svg",
|
||||
Task::DeleteAllConfigs
|
||||
);
|
||||
danger_button!(
|
||||
mp,
|
||||
c,
|
||||
"APP_SETTINGS.RESTART_SOFTWARE",
|
||||
"dashboard/refresh.svg",
|
||||
Task::RestartSoftware
|
||||
);
|
||||
tasks.push(Task::SetTab(TabNameEnum::LookAndFeel));
|
||||
|
||||
Ok(Self {
|
||||
app_button_ids,
|
||||
tasks: mp.tasks,
|
||||
app_button_ids: Vec::new(),
|
||||
tasks,
|
||||
state: parser_state,
|
||||
marker: PhantomData,
|
||||
context_menu: ContextMenu::default(),
|
||||
|
||||
@@ -163,7 +163,7 @@ impl PopupManager {
|
||||
|
||||
but_back.on_click({
|
||||
let popup_handle = Rc::downgrade(&popup_handle.state);
|
||||
Box::new(move |_common, _evt| {
|
||||
Rc::new(move |_common, _evt| {
|
||||
if let Some(popup_handle) = popup_handle.upgrade() {
|
||||
popup_handle.borrow_mut().mounted_popup = None; // will call Drop
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ fn mount_multi_selector(params: MultiSelectorParams) -> anyhow::Result<()> {
|
||||
button.on_click({
|
||||
let on_click = params.on_click.clone();
|
||||
let key = cell.key.clone();
|
||||
Box::new(move |_, _| {
|
||||
Rc::new(move |_, _| {
|
||||
(*on_click)(key.as_str());
|
||||
Ok(())
|
||||
})
|
||||
@@ -610,7 +610,7 @@ impl View {
|
||||
fn handle_func_button_click(&self, task: ViewTask) -> ButtonClickCallback {
|
||||
let tasks = self.tasks.clone();
|
||||
let on_update = self.on_update.clone();
|
||||
Box::new(move |_common, _evt| {
|
||||
Rc::new(move |_common, _evt| {
|
||||
tasks.push(task.clone());
|
||||
(*on_update)();
|
||||
Ok(())
|
||||
@@ -762,7 +762,7 @@ impl View {
|
||||
let tasks = self.tasks.clone();
|
||||
let card = params.card.clone();
|
||||
let on_update = self.on_update.clone();
|
||||
Box::new(move |_common, _evt| {
|
||||
Rc::new(move |_common, _evt| {
|
||||
tasks.push(ViewTask::SetMode(CurrentMode::CardProfileSelector(card.clone())));
|
||||
(*on_update)();
|
||||
Ok(())
|
||||
@@ -836,7 +836,7 @@ impl View {
|
||||
|
||||
btn_mute.on_click({
|
||||
let control = params.control.clone();
|
||||
Box::new(move |_common, _event| {
|
||||
Rc::new(move |_common, _event| {
|
||||
control.on_mute_toggle()?;
|
||||
Ok(())
|
||||
})
|
||||
@@ -957,7 +957,7 @@ impl View {
|
||||
btn_back.on_click({
|
||||
let tasks = self.tasks.clone();
|
||||
let on_update = self.on_update.clone();
|
||||
Box::new(move |_, _| {
|
||||
Rc::new(move |_, _| {
|
||||
tasks.push(ViewTask::SetMode(CurrentMode::Cards));
|
||||
(*on_update)();
|
||||
Ok(())
|
||||
|
||||
@@ -150,7 +150,7 @@ fn fill_game_list(
|
||||
view_cover.button.on_click({
|
||||
let tasks = tasks.clone();
|
||||
let manifest = manifest.clone();
|
||||
Box::new(move |_, _| {
|
||||
Rc::new(move |_, _| {
|
||||
tasks.push(Task::AppManifestClicked(manifest.clone()));
|
||||
Ok(())
|
||||
})
|
||||
|
||||
@@ -186,7 +186,7 @@ fn fill_process_list(
|
||||
entry_res.btn_terminate.on_click({
|
||||
let tasks = tasks.clone();
|
||||
let entry = process_entry.clone();
|
||||
Box::new(move |_, _| {
|
||||
Rc::new(move |_, _| {
|
||||
tasks.push(Task::TerminateProcess(entry.clone()));
|
||||
Ok(())
|
||||
})
|
||||
|
||||
@@ -190,7 +190,7 @@ fn fill_window_list<T>(
|
||||
|
||||
button.on_click({
|
||||
let tasks = tasks.clone();
|
||||
Box::new(move |_, _| {
|
||||
Rc::new(move |_, _| {
|
||||
tasks.push(Task::WindowClicked(entry.clone()));
|
||||
Ok(())
|
||||
})
|
||||
@@ -260,14 +260,14 @@ impl View {
|
||||
self.frontend_tasks.push(FrontendTask::MountPopup(MountPopupParams {
|
||||
title: Translation::from_translation_key("WINDOW_OPTIONS"),
|
||||
on_content: {
|
||||
let frontend_tasks = self.frontend_tasks.clone();
|
||||
let globals = self.globals.clone();
|
||||
let state = self.state.clone();
|
||||
let tasks = self.tasks.clone();
|
||||
let _frontend_tasks = self.frontend_tasks.clone();
|
||||
let _globals = self.globals.clone();
|
||||
let _state = self.state.clone();
|
||||
let _tasks = self.tasks.clone();
|
||||
|
||||
//TODO
|
||||
|
||||
Rc::new(move |data| {
|
||||
Rc::new(move |_data| {
|
||||
// state.borrow_mut().view_window_options = Some((
|
||||
// data.handle,
|
||||
// window_options::View::new(window_options::Params {
|
||||
|
||||
Reference in New Issue
Block a user