From f19519860862d5ab663f3c136e88a4d9c1501bb0 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Wed, 17 Apr 2024 19:58:25 -0400 Subject: [PATCH 01/31] Extend ContentDialogHelper to work on multiple windows --- src/Ryujinx/UI/Helpers/ContentDialogHelper.cs | 125 ++++++++++-------- 1 file changed, 70 insertions(+), 55 deletions(-) diff --git a/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs b/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs index 15b7ddd14b..2ff57322e6 100644 --- a/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs +++ b/src/Ryujinx/UI/Helpers/ContentDialogHelper.cs @@ -28,7 +28,8 @@ namespace Ryujinx.Ava.UI.Helpers string closeButton, UserResult primaryButtonResult = UserResult.Ok, ManualResetEvent deferResetEvent = null, - TypedEventHandler deferCloseAction = null) + TypedEventHandler deferCloseAction = null, + Window parent = null) { UserResult result = UserResult.None; @@ -62,7 +63,7 @@ namespace Ryujinx.Ava.UI.Helpers contentDialog.PrimaryButtonClick += deferCloseAction; } - await ShowAsync(contentDialog); + await ShowAsync(contentDialog, parent); return result; } @@ -77,11 +78,21 @@ namespace Ryujinx.Ava.UI.Helpers int iconSymbol, UserResult primaryButtonResult = UserResult.Ok, ManualResetEvent deferResetEvent = null, - TypedEventHandler deferCloseAction = null) + TypedEventHandler deferCloseAction = null, + Window parent = null) { Grid content = CreateTextDialogContent(primaryText, secondaryText, iconSymbol); - return await ShowContentDialog(title, content, primaryButton, secondaryButton, closeButton, primaryButtonResult, deferResetEvent, deferCloseAction); + return await ShowContentDialog( + title, + content, + primaryButton, + secondaryButton, + closeButton, + primaryButtonResult, + deferResetEvent, + deferCloseAction, + parent); } public async static Task ShowDeferredContentDialog( @@ -94,7 +105,8 @@ namespace Ryujinx.Ava.UI.Helpers string closeButton, int iconSymbol, ManualResetEvent deferResetEvent, - Func doWhileDeferred = null) + Func doWhileDeferred = null, + Window parent = null) { bool startedDeferring = false; @@ -108,7 +120,8 @@ namespace Ryujinx.Ava.UI.Helpers iconSymbol, primaryButton == LocaleManager.Instance[LocaleKeys.InputDialogYes] ? UserResult.Yes : UserResult.Ok, deferResetEvent, - DeferClose); + DeferClose, + parent); async void DeferClose(ContentDialog sender, ContentDialogButtonClickEventArgs args) { @@ -199,7 +212,8 @@ namespace Ryujinx.Ava.UI.Helpers string secondaryText, string acceptButton, string closeButton, - string title) + string title, + Window parent = null) { return await ShowTextDialog( title, @@ -208,7 +222,8 @@ namespace Ryujinx.Ava.UI.Helpers acceptButton, "", closeButton, - (int)Symbol.Important); + (int)Symbol.Important, + parent: parent); } internal static async Task CreateConfirmationDialog( @@ -217,7 +232,8 @@ namespace Ryujinx.Ava.UI.Helpers string acceptButtonText, string cancelButtonText, string title, - UserResult primaryButtonResult = UserResult.Yes) + UserResult primaryButtonResult = UserResult.Yes, + Window parent = null) { return await ShowTextDialog( string.IsNullOrWhiteSpace(title) ? LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle] : title, @@ -227,7 +243,8 @@ namespace Ryujinx.Ava.UI.Helpers "", cancelButtonText, (int)Symbol.Help, - primaryButtonResult); + primaryButtonResult, + parent: parent); } internal static async Task CreateUpdaterInfoDialog(string primary, string secondaryText) @@ -268,7 +285,11 @@ namespace Ryujinx.Ava.UI.Helpers (int)Symbol.Dismiss); } - internal static async Task CreateChoiceDialog(string title, string primary, string secondaryText) + internal static async Task CreateChoiceDialog( + string title, + string primary, + string secondaryText, + Window parent = null) { if (_isChoiceDialogOpen) { @@ -285,7 +306,8 @@ namespace Ryujinx.Ava.UI.Helpers "", LocaleManager.Instance[LocaleKeys.InputDialogNo], (int)Symbol.Help, - UserResult.Yes); + UserResult.Yes, + parent: parent); _isChoiceDialogOpen = false; @@ -308,69 +330,62 @@ namespace Ryujinx.Ava.UI.Helpers LocaleManager.Instance[LocaleKeys.DialogExitSubMessage]); } - public static async Task ShowAsync(ContentDialog contentDialog) + public static async Task ShowAsync(ContentDialog contentDialog, Window parent = null) { ContentDialogResult result; bool isTopDialog = true; - Window parent = GetMainWindow(); + parent ??= GetMainWindow(); if (_contentDialogOverlayWindow != null) { isTopDialog = false; } - if (parent is MainWindow window) + parent.Activate(); + + _contentDialogOverlayWindow = new ContentDialogOverlayWindow { - parent.Activate(); + Height = parent.Bounds.Height, + Width = parent.Bounds.Width, + Position = parent.PointToScreen(new Point()), + ShowInTaskbar = false, + }; - _contentDialogOverlayWindow = new ContentDialogOverlayWindow + parent.PositionChanged += OverlayOnPositionChanged; + + void OverlayOnPositionChanged(object sender, PixelPointEventArgs e) + { + if (_contentDialogOverlayWindow is null) { - Height = parent.Bounds.Height, - Width = parent.Bounds.Width, - Position = parent.PointToScreen(new Point()), - ShowInTaskbar = false, - }; - - parent.PositionChanged += OverlayOnPositionChanged; - - void OverlayOnPositionChanged(object sender, PixelPointEventArgs e) - { - if (_contentDialogOverlayWindow is null) - { - return; - } - - _contentDialogOverlayWindow.Position = parent.PointToScreen(new Point()); + return; } - _contentDialogOverlayWindow.ContentDialog = contentDialog; - - bool opened = false; - - _contentDialogOverlayWindow.Opened += OverlayOnActivated; - - async void OverlayOnActivated(object sender, EventArgs e) - { - if (opened) - { - return; - } - - opened = true; - - _contentDialogOverlayWindow.Position = parent.PointToScreen(new Point()); - - result = await ShowDialog(); - } - - result = await _contentDialogOverlayWindow.ShowDialog(parent); + _contentDialogOverlayWindow.Position = parent.PointToScreen(new Point()); } - else + + _contentDialogOverlayWindow.ContentDialog = contentDialog; + + bool opened = false; + + _contentDialogOverlayWindow.Opened += OverlayOnActivated; + + async void OverlayOnActivated(object sender, EventArgs e) { + if (opened) + { + return; + } + + opened = true; + + _contentDialogOverlayWindow.Position = parent.PointToScreen(new Point()); + result = await ShowDialog(); } + result = await _contentDialogOverlayWindow.ShowDialog(parent); + async Task ShowDialog() { if (_contentDialogOverlayWindow is not null) From c141b248a82d4c88af33d525806707213cf58f7e Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Thu, 18 Apr 2024 16:31:52 -0400 Subject: [PATCH 02/31] Change SettingsWindow title on dirty --- src/Ryujinx/Assets/Locales/en_US.json | 1 + src/Ryujinx/UI/ViewModels/SettingsViewModel.cs | 17 +++++++++++++++-- src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs | 18 ++++++++++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/Ryujinx/Assets/Locales/en_US.json b/src/Ryujinx/Assets/Locales/en_US.json index 8df0f96a14..30936a2a1b 100644 --- a/src/Ryujinx/Assets/Locales/en_US.json +++ b/src/Ryujinx/Assets/Locales/en_US.json @@ -91,6 +91,7 @@ "LinuxVmMaxMapCountWarningTextPrimary": "Max amount of memory mappings is lower than recommended.", "LinuxVmMaxMapCountWarningTextSecondary": "The current value of vm.max_map_count ({0}) is lower than {1}. Some games might try to create more memory mappings than currently allowed. Ryujinx will crash as soon as this limit gets exceeded.\n\nYou might want to either manually increase the limit or install pkexec, which allows Ryujinx to assist with that.", "Settings": "Settings", + "SettingsDirty": "Unsaved Changes", "SettingsTabGeneral": "User Interface", "SettingsTabGeneralGeneral": "General", "SettingsTabGeneralEnableDiscordRichPresence": "Enable Discord Rich Presence", diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 70e5fa5c74..3fda90a646 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -49,11 +49,24 @@ namespace Ryujinx.Ava.UI.ViewModels private int _graphicsBackendIndex; private int _scalingFilter; private int _scalingFilterLevel; + private int _networkInterfaceIndex; + private int _multiplayerModeIndex; + + private bool _isModified; + + public bool IsModified + { + get => _isModified; + set + { + DirtyEvent?.Invoke(value); + _isModified = value; + } + } public event Action CloseWindow; public event Action SaveSettingsEvent; - private int _networkInterfaceIndex; - private int _multiplayerModeIndex; + public event Action DirtyEvent; public int ResolutionScale { diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs b/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs index 314501c525..8d21636a86 100644 --- a/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs @@ -10,17 +10,18 @@ namespace Ryujinx.Ava.UI.Windows { public partial class SettingsWindow : StyleableWindow { - internal SettingsViewModel ViewModel { get; set; } + private SettingsViewModel ViewModel { get; } public SettingsWindow(VirtualFileSystem virtualFileSystem, ContentManager contentManager) { - Title = $"Ryujinx {Program.Version} - {LocaleManager.Instance[LocaleKeys.Settings]}"; + Title = $"{LocaleManager.Instance[LocaleKeys.Settings]}"; ViewModel = new SettingsViewModel(virtualFileSystem, contentManager); DataContext = ViewModel; ViewModel.CloseWindow += Close; ViewModel.SaveSettingsEvent += SaveSettings; + ViewModel.DirtyEvent += UpdateDirtyTitle; InitializeComponent(); Load(); @@ -35,6 +36,19 @@ namespace Ryujinx.Ava.UI.Windows Load(); } + public void UpdateDirtyTitle(bool isDirty) + { + if (isDirty) + { + Title = $"{LocaleManager.Instance[LocaleKeys.Settings]} - {LocaleManager.Instance[LocaleKeys.SettingsDirty]}"; + } + else + { + Title = $"{LocaleManager.Instance[LocaleKeys.Settings]}"; + + } + } + public void SaveSettings() { InputPage.InputView?.SaveCurrentProfile(); From ea80d922a661204c948881c4d593287b7ae7a702 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Thu, 18 Apr 2024 16:35:24 -0400 Subject: [PATCH 03/31] Move all remaining input controls to Input VM --- .../UI/ViewModels/Input/InputViewModel.cs | 20 + .../UI/ViewModels/SettingsViewModel.cs | 13 - src/Ryujinx/UI/Views/Input/InputView.axaml | 426 ++++++++++-------- .../UI/Views/Settings/SettingsInputView.axaml | 44 +- 4 files changed, 254 insertions(+), 249 deletions(-) diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs index 89cc6496d5..a02bf42bdd 100644 --- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs @@ -51,6 +51,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input private object _configViewModel; private string _profileName; private bool _isLoaded; + private bool _enableDockedMode; private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); @@ -70,6 +71,17 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public bool IsRight { get; set; } public bool IsLeft { get; set; } + public bool EnableDockedMode + { + get => _enableDockedMode; + set + { + _enableDockedMode = value; + } + } + public bool EnableKeyboard { get; set; } + public bool EnableMouse { get; set; } + public bool IsModified { get; set; } public event Action NotifyChangesEvent; @@ -288,6 +300,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input { ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig)); } + + EnableDockedMode = ConfigurationState.Instance.System.EnableDockedMode; + EnableKeyboard = ConfigurationState.Instance.Hid.EnableKeyboard; + EnableMouse = ConfigurationState.Instance.Hid.EnableMouse; } public void LoadDevice() @@ -853,6 +869,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input // NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event. ConfigurationState.Instance.Hid.InputConfig.Value = newConfig; + ConfigurationState.Instance.System.EnableDockedMode.Value = EnableDockedMode; + ConfigurationState.Instance.Hid.EnableKeyboard.Value = EnableKeyboard; + ConfigurationState.Instance.Hid.EnableMouse.Value = EnableMouse; + ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); } diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 3fda90a646..34c3af354e 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -146,9 +146,6 @@ namespace Ryujinx.Ava.UI.ViewModels public bool ShowConfirmExit { get; set; } public bool RememberWindowState { get; set; } public int HideCursor { get; set; } - public bool EnableDockedMode { get; set; } - public bool EnableKeyboard { get; set; } - public bool EnableMouse { get; set; } public bool EnableVsync { get; set; } public bool EnablePptc { get; set; } public bool EnableInternetAccess { get; set; } @@ -418,11 +415,6 @@ namespace Ryujinx.Ava.UI.ViewModels _ => 0 }; - // Input - EnableDockedMode = config.System.EnableDockedMode; - EnableKeyboard = config.Hid.EnableKeyboard; - EnableMouse = config.Hid.EnableMouse; - // Keyboard Hotkeys KeyboardHotkey = new HotkeyConfig(config.Hid.Hotkeys.Value); @@ -513,11 +505,6 @@ namespace Ryujinx.Ava.UI.ViewModels _ => "Auto" }; - // Input - config.System.EnableDockedMode.Value = EnableDockedMode; - config.Hid.EnableKeyboard.Value = EnableKeyboard; - config.Hid.EnableMouse.Value = EnableMouse; - // Keyboard Hotkeys config.Hid.Hotkeys.Value = KeyboardHotkey.GetConfig(); diff --git a/src/Ryujinx/UI/Views/Input/InputView.axaml b/src/Ryujinx/UI/Views/Input/InputView.axaml index b4940941cc..bd36fc5818 100644 --- a/src/Ryujinx/UI/Views/Input/InputView.axaml +++ b/src/Ryujinx/UI/Views/Input/InputView.axaml @@ -27,199 +27,237 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + IsChecked="{Binding EnableDockedMode}"> + + + + + + + + + + + diff --git a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml index 55c2ed6e3c..f474771f91 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml @@ -4,7 +4,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:views="clr-namespace:Ryujinx.Ava.UI.Views.Input" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" mc:Ignorable="d" @@ -21,47 +20,8 @@ - - - - - - - - - - - - - - - - - - - - - - + - \ No newline at end of file + From fd33ebb42d3e36292352459102b949f326b09b60 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Thu, 18 Apr 2024 17:54:07 -0400 Subject: [PATCH 04/31] Use IsDefault and IsCancel instead of Hotkeys --- src/Ryujinx/UI/Windows/SettingsWindow.axaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.axaml b/src/Ryujinx/UI/Windows/SettingsWindow.axaml index de3c2291af..d3c863133b 100644 --- a/src/Ryujinx/UI/Windows/SettingsWindow.axaml +++ b/src/Ryujinx/UI/Windows/SettingsWindow.axaml @@ -114,12 +114,12 @@ HorizontalAlignment="Right" ReverseOrder="{Binding IsMacOS}"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Ryujinx/UI/Views/Input/InputView.axaml.cs b/src/Ryujinx/UI/Views/Input/InputView.axaml.cs deleted file mode 100644 index 356381a8aa..0000000000 --- a/src/Ryujinx/UI/Views/Input/InputView.axaml.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Avalonia.Controls; -using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Ava.UI.Models; -using Ryujinx.Ava.UI.ViewModels.Input; - -namespace Ryujinx.Ava.UI.Views.Input -{ - public partial class InputView : UserControl - { - private bool _dialogOpen; - private InputViewModel ViewModel { get; set; } - - public InputView() - { - DataContext = ViewModel = new InputViewModel(this); - - InitializeComponent(); - } - - public void SaveCurrentProfile() - { - ViewModel.Save(); - } - - private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) - { - if (ViewModel.IsModified && !_dialogOpen) - { - _dialogOpen = true; - - var result = await ContentDialogHelper.CreateConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage], - LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage], - LocaleManager.Instance[LocaleKeys.InputDialogYes], - LocaleManager.Instance[LocaleKeys.InputDialogNo], - LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); - - if (result == UserResult.Yes) - { - ViewModel.Save(); - } - - _dialogOpen = false; - - ViewModel.IsModified = false; - - if (e.AddedItems.Count > 0) - { - var player = (PlayerModel)e.AddedItems[0]; - ViewModel.PlayerId = player.Id; - } - } - } - - public void Dispose() - { - ViewModel.Dispose(); - } - } -} diff --git a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml index f474771f91..5428435dc2 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml @@ -2,14 +2,17 @@ x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsInputView" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" + xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:views="clr-namespace:Ryujinx.Ava.UI.Views.Input" - xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" + xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input" + xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models" mc:Ignorable="d" - x:DataType="viewModels:SettingsViewModel"> + x:DataType="viewModels:InputViewModel"> - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs index fc88e322a9..29b8993d54 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs @@ -1,21 +1,67 @@ using Avalonia.Controls; +using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; +using Ryujinx.Ava.UI.ViewModels.Input; +using Ryujinx.Ava.UI.Views.Input; namespace Ryujinx.Ava.UI.Views.Settings { public partial class SettingsInputView : UserControl { - public SettingsViewModel ViewModel; + public SettingsViewModel SettingsViewModel; + + private bool _dialogOpen; + private InputViewModel ViewModel { get; set; } public SettingsInputView(SettingsViewModel viewModel) { - ViewModel = viewModel; + SettingsViewModel = viewModel; + + DataContext = ViewModel = new InputViewModel(this); + InitializeComponent(); } + public void SaveCurrentProfile() + { + ViewModel.Save(); + } + + private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (ViewModel.IsModified && !_dialogOpen) + { + _dialogOpen = true; + + var result = await ContentDialogHelper.CreateConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage], + LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage], + LocaleManager.Instance[LocaleKeys.InputDialogYes], + LocaleManager.Instance[LocaleKeys.InputDialogNo], + LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); + + if (result == UserResult.Yes) + { + ViewModel.Save(); + } + + _dialogOpen = false; + + ViewModel.IsModified = false; + + if (e.AddedItems.Count > 0) + { + var player = (PlayerModel)e.AddedItems[0]; + ViewModel.PlayerId = player.Id; + } + } + } + public void Dispose() { - InputView.Dispose(); + ViewModel.Dispose(); } } } diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs b/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs index ff05a2401d..9d6fb6c7c8 100644 --- a/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs @@ -79,7 +79,7 @@ namespace Ryujinx.Ava.UI.Windows public void SaveSettings() { - InputPage.InputView?.SaveCurrentProfile(); + InputPage.SaveCurrentProfile(); if (Owner is MainWindow window && ViewModel.DirectoryChanged) { From 1ad9b27ed64bc59c15ab5ea32f74720cf51fcb38 Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Thu, 18 Apr 2024 18:34:23 -0400 Subject: [PATCH 09/31] Remove InputViewModel.IsModified Format --- src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs | 13 +++++++------ .../UI/Views/Input/ControllerInputView.axaml.cs | 2 +- .../UI/Views/Input/KeyboardInputView.axaml.cs | 2 +- .../UI/Views/Settings/SettingsInputView.axaml.cs | 7 +++---- src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs | 7 ++++++- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs index a02bf42bdd..910382aef0 100644 --- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs @@ -82,9 +82,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public bool EnableKeyboard { get; set; } public bool EnableMouse { get; set; } - public bool IsModified { get; set; } public event Action NotifyChangesEvent; + public SettingsViewModel SettingsViewModel; + public object ConfigViewModel { get => _configViewModel; @@ -101,12 +102,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input get => _playerId; set { - if (IsModified) + if (SettingsViewModel.IsModified) { return; } - IsModified = false; + SettingsViewModel.IsModified = false; _playerId = value; if (!Enum.IsDefined(typeof(PlayerIndex), _playerId)) @@ -243,8 +244,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public InputConfig Config { get; set; } - public InputViewModel(UserControl owner) : this() + public InputViewModel(UserControl owner, SettingsViewModel settingsViewModel) : this() { + SettingsViewModel = settingsViewModel; + if (Program.PreviewerDetached) { _mainWindow = @@ -819,8 +822,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public void Save() { - IsModified = false; - List newConfig = new(); newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value); diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs index b76648da77..477401eebf 100644 --- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs @@ -71,7 +71,7 @@ namespace Ryujinx.Ava.UI.Views.Input if (e.ButtonValue.HasValue) { var buttonValue = e.ButtonValue.Value; - viewModel.ParentModel.IsModified = true; + viewModel.ParentModel.SettingsViewModel.IsModified = true; switch (button.Name) { diff --git a/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs index f17c7496ca..1a792088ec 100644 --- a/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/KeyboardInputView.axaml.cs @@ -68,7 +68,7 @@ namespace Ryujinx.Ava.UI.Views.Input if (e.ButtonValue.HasValue) { var buttonValue = e.ButtonValue.Value; - viewModel.ParentModel.IsModified = true; + viewModel.ParentModel.SettingsViewModel.IsModified = true; switch (button.Name) { diff --git a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs index 29b8993d54..ff71da9c74 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs @@ -4,7 +4,6 @@ using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels.Input; -using Ryujinx.Ava.UI.Views.Input; namespace Ryujinx.Ava.UI.Views.Settings { @@ -19,7 +18,7 @@ namespace Ryujinx.Ava.UI.Views.Settings { SettingsViewModel = viewModel; - DataContext = ViewModel = new InputViewModel(this); + DataContext = ViewModel = new InputViewModel(this, viewModel); InitializeComponent(); } @@ -31,7 +30,7 @@ namespace Ryujinx.Ava.UI.Views.Settings private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { - if (ViewModel.IsModified && !_dialogOpen) + if (SettingsViewModel.IsModified && !_dialogOpen) { _dialogOpen = true; @@ -49,7 +48,7 @@ namespace Ryujinx.Ava.UI.Views.Settings _dialogOpen = false; - ViewModel.IsModified = false; + SettingsViewModel.IsModified = false; if (e.AddedItems.Count > 0) { diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs b/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs index 9d6fb6c7c8..282f931763 100644 --- a/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs @@ -21,7 +21,7 @@ namespace Ryujinx.Ava.UI.Windows public readonly SettingsGraphicsView GraphicsPage; public readonly SettingsAudioView AudioPage; public readonly SettingsNetworkView NetworkPage; - public readonly SettingsLoggingView LoggingPage; + public readonly SettingsLoggingView LoggingPage; public SettingsWindow(VirtualFileSystem virtualFileSystem, ContentManager contentManager) { @@ -60,6 +60,11 @@ namespace Ryujinx.Ava.UI.Windows public void UpdateDirtyTitle(bool isDirty) { + if (!IsInitialized) + { + return; + } + if (isDirty) { Title = $"{LocaleManager.Instance[LocaleKeys.Settings]} - {LocaleManager.Instance[LocaleKeys.SettingsDirty]}"; From 286aebf70f57ee2d95d2d71934b3eaceeb6ed6aa Mon Sep 17 00:00:00 2001 From: Isaac Marovitz Date: Thu, 18 Apr 2024 18:42:47 -0400 Subject: [PATCH 10/31] Move confimration dialogue to SettingsWindow --- src/Ryujinx/Assets/Locales/en_US.json | 4 +- .../UI/ViewModels/SettingsViewModel.cs | 10 ----- .../UI/Views/Settings/SettingsInputView.axaml | 1 - .../Views/Settings/SettingsInputView.axaml.cs | 38 ------------------- src/Ryujinx/UI/Windows/SettingsWindow.axaml | 2 +- .../UI/Windows/SettingsWindow.axaml.cs | 29 ++++++++++++++ 6 files changed, 32 insertions(+), 52 deletions(-) diff --git a/src/Ryujinx/Assets/Locales/en_US.json b/src/Ryujinx/Assets/Locales/en_US.json index 30936a2a1b..6218fffd4c 100644 --- a/src/Ryujinx/Assets/Locales/en_US.json +++ b/src/Ryujinx/Assets/Locales/en_US.json @@ -490,8 +490,8 @@ "DialogUserProfileUnsavedChangesTitle": "Warning - Unsaved Changes", "DialogUserProfileUnsavedChangesMessage": "You have made changes to this user profile that have not been saved.", "DialogUserProfileUnsavedChangesSubMessage": "Do you want to discard your changes?", - "DialogControllerSettingsModifiedConfirmMessage": "The current controller settings has been updated.", - "DialogControllerSettingsModifiedConfirmSubMessage": "Do you want to save?", + "DialogSettingsUnsavedChangesMessage": "You have made changes to settings that have not been saved.", + "DialogSettingsUnsavedChangesSubMessage": "Do you want to discard your changes?", "DialogLoadFileErrorMessage": "{0}. Errored File: {1}", "DialogModAlreadyExistsMessage": "Mod already exists", "DialogModInvalidMessage": "The specified directory does not contain a mod!", diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index d1f5530968..9f2589071f 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -591,10 +591,6 @@ namespace Ryujinx.Ava.UI.ViewModels _directoryChanged = false; } - private static void RevertIfNotSaved() - { - Program.ReloadConfig(); - } public void ApplyButton() { @@ -606,11 +602,5 @@ namespace Ryujinx.Ava.UI.ViewModels SaveSettings(); CloseWindow?.Invoke(); } - - public void CancelButton() - { - RevertIfNotSaved(); - CloseWindow?.Invoke(); - } } } diff --git a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml index 5428435dc2..ff4779a441 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml @@ -65,7 +65,6 @@ Name="PlayerIndexBox" HorizontalAlignment="Stretch" VerticalAlignment="Center" - SelectionChanged="PlayerIndexBox_OnSelectionChanged" ItemsSource="{Binding PlayerIndexes}" SelectedIndex="{Binding PlayerId}"> diff --git a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs index ff71da9c74..e9b5cab736 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsInputView.axaml.cs @@ -1,7 +1,4 @@ using Avalonia.Controls; -using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels.Input; @@ -9,15 +6,10 @@ namespace Ryujinx.Ava.UI.Views.Settings { public partial class SettingsInputView : UserControl { - public SettingsViewModel SettingsViewModel; - - private bool _dialogOpen; private InputViewModel ViewModel { get; set; } public SettingsInputView(SettingsViewModel viewModel) { - SettingsViewModel = viewModel; - DataContext = ViewModel = new InputViewModel(this, viewModel); InitializeComponent(); @@ -28,36 +20,6 @@ namespace Ryujinx.Ava.UI.Views.Settings ViewModel.Save(); } - private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) - { - if (SettingsViewModel.IsModified && !_dialogOpen) - { - _dialogOpen = true; - - var result = await ContentDialogHelper.CreateConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage], - LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage], - LocaleManager.Instance[LocaleKeys.InputDialogYes], - LocaleManager.Instance[LocaleKeys.InputDialogNo], - LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); - - if (result == UserResult.Yes) - { - ViewModel.Save(); - } - - _dialogOpen = false; - - SettingsViewModel.IsModified = false; - - if (e.AddedItems.Count > 0) - { - var player = (PlayerModel)e.AddedItems[0]; - ViewModel.PlayerId = player.Id; - } - } - } - public void Dispose() { ViewModel.Dispose(); diff --git a/src/Ryujinx/UI/Windows/SettingsWindow.axaml b/src/Ryujinx/UI/Windows/SettingsWindow.axaml index b5f0242959..263f06ec71 100644 --- a/src/Ryujinx/UI/Windows/SettingsWindow.axaml +++ b/src/Ryujinx/UI/Windows/SettingsWindow.axaml @@ -110,7 +110,7 @@