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 15b7ddd14..2ff57322e 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 8df0f96a1..30936a2a1 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 70e5fa5c7..3fda90a64 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 314501c52..8d21636a8 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 89cc6496d..a02bf42bd 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 3fda90a64..34c3af354 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 b4940941c..bd36fc581 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 55c2ed6e3..f474771f9 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 de3c2291a..d3c863133 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 356381a8a..000000000 --- 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 f474771f9..5428435dc 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 fc88e322a..29b8993d5 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 ff05a2401..9d6fb6c7c 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 a02bf42bd..910382aef 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 b76648da7..477401eeb 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 f17c7496c..1a792088e 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 29b8993d5..ff71da9c7 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 9d6fb6c7c..282f93176 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 30936a2a1..6218fffd4 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 d1f553096..9f2589071 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 5428435dc..ff4779a44 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 ff71da9c7..e9b5cab73 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 b5f024295..263f06ec7 100644 --- a/src/Ryujinx/UI/Windows/SettingsWindow.axaml +++ b/src/Ryujinx/UI/Windows/SettingsWindow.axaml @@ -110,7 +110,7 @@