From 38519f3b9ade223983f7529f9b4f4b857c60f42b Mon Sep 17 00:00:00 2001 From: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com> Date: Fri, 6 Jan 2023 18:35:21 -0500 Subject: [PATCH] Ava GUI: `SettingsWindow` Refactor (#4177) * Fix redundancies * Add back elses * Settings Refactor * Fix Disposal functions * Use `ReflectionBinding` instead of redundant funcs * Ac_K suggestions * Update Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs Co-authored-by: Ac_K * Update locale keys * Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Use block-scoped namespaces * Fix typo * Make `TimeZone` internal again Co-authored-by: Ac_K Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> --- .../UI/ViewModels/SettingsViewModel.cs | 104 +-- .../UI/Views/Settings/SettingsAudioView.axaml | 81 ++ .../Views/Settings/SettingsAudioView.axaml.cs | 12 + .../UI/Views/Settings/SettingsCPUView.axaml | 72 ++ .../Views/Settings/SettingsCPUView.axaml.cs | 12 + .../Views/Settings/SettingsGraphicsView.axaml | 218 +++++ .../Settings/SettingsGraphicsView.axaml.cs | 12 + .../Views/Settings/SettingsHotkeysView.axaml | 104 +++ .../Settings/SettingsHotkeysView.axaml.cs | 81 ++ .../UI/Views/Settings/SettingsInputView.axaml | 46 + .../Views/Settings/SettingsInputView.axaml.cs | 17 + .../Views/Settings/SettingsLoggingView.axaml | 118 +++ .../Settings/SettingsLoggingView.axaml.cs | 12 + .../Views/Settings/SettingsNetworkView.axaml | 35 + .../Settings/SettingsNetworkView.axaml.cs | 12 + .../Views/Settings/SettingsSystemView.axaml | 195 ++++ .../Settings/SettingsSystemView.axaml.cs | 52 ++ .../UI/Views/Settings/SettingsUIView.axaml | 156 ++++ .../UI/Views/Settings/SettingsUIView.axaml.cs | 82 ++ Ryujinx.Ava/UI/Windows/SettingsWindow.axaml | 884 +----------------- .../UI/Windows/SettingsWindow.axaml.cs | 214 ++--- 21 files changed, 1422 insertions(+), 1097 deletions(-) create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml.cs create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml.cs create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml.cs create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml.cs create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml.cs create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml create mode 100644 Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs diff --git a/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs b/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs index 5570800a..d11b01f1 100644 --- a/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs +++ b/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs @@ -1,4 +1,3 @@ -using Avalonia; using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Threading; @@ -8,8 +7,6 @@ using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SoundIo; using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.Input; -using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; using Ryujinx.Common.Configuration; @@ -19,7 +16,6 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.Vulkan; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Time.TimeZone; -using Ryujinx.Input; using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration.System; using System; @@ -30,11 +26,10 @@ using TimeZone = Ryujinx.Ava.UI.Models.TimeZone; namespace Ryujinx.Ava.UI.ViewModels { - internal class SettingsViewModel : BaseModel + public class SettingsViewModel : BaseModel { private readonly VirtualFileSystem _virtualFileSystem; private readonly ContentManager _contentManager; - private readonly StyleableWindow _owner; private TimeZoneContentManager _timeZoneContentManager; private readonly List _validTzRegions; @@ -44,10 +39,14 @@ namespace Ryujinx.Ava.UI.ViewModels private int _graphicsBackendMultithreadingIndex; private float _volume; private bool _isVulkanAvailable = true; - private bool _directoryChanged = false; - private List _gpuIds = new List(); + private bool _directoryChanged; + private List _gpuIds = new(); private KeyboardHotkeys _keyboardHotkeys; private int _graphicsBackendIndex; + private string _customThemePath; + + public event Action CloseWindow; + public event Action SaveSettingsEvent; public int ResolutionScale { @@ -67,19 +66,16 @@ namespace Ryujinx.Ava.UI.ViewModels { _graphicsBackendMultithreadingIndex = value; - if (_owner != null) + if (_graphicsBackendMultithreadingIndex != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value) { - if (_graphicsBackendMultithreadingIndex != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value) + Dispatcher.UIThread.Post(async () => { - Dispatcher.UIThread.Post(async () => - { - await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage], - "", - "", - LocaleManager.Instance[LocaleKeys.InputDialogOk], - LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningTitle]); - }); - } + await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage], + "", + "", + LocaleManager.Instance[LocaleKeys.InputDialogOk], + LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningTitle]); + }); } OnPropertyChanged(); @@ -120,12 +116,12 @@ namespace Ryujinx.Ava.UI.ViewModels OnPropertyChanged(); } } - + public bool IsMacOS { get => OperatingSystem.IsMacOS(); } - + public bool EnableDiscordIntegration { get; set; } public bool CheckUpdatesOnStart { get; set; } public bool ShowConfirmExit { get; set; } @@ -160,7 +156,20 @@ namespace Ryujinx.Ava.UI.ViewModels public string TimeZone { get; set; } public string ShaderDumpPath { get; set; } - public string CustomThemePath { get; set; } + + public string CustomThemePath + { + get + { + return _customThemePath; + } + set + { + _customThemePath = value; + + OnPropertyChanged(); + } + } public int Language { get; set; } public int Region { get; set; } @@ -191,7 +200,7 @@ namespace Ryujinx.Ava.UI.ViewModels { _volume = value; - ConfigurationState.Instance.System.AudioVolume.Value = (float)(_volume / 100); + ConfigurationState.Instance.System.AudioVolume.Value = _volume / 100; OnPropertyChanged(); } @@ -199,7 +208,7 @@ namespace Ryujinx.Ava.UI.ViewModels public DateTimeOffset DateOffset { get; set; } public TimeSpan TimeOffset { get; set; } - public AvaloniaList TimeZones { get; set; } + private AvaloniaList TimeZones { get; set; } public AvaloniaList GameDirectories { get; set; } public ObservableCollection AvailableGpus { get; set; } @@ -214,17 +223,13 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public IGamepadDriver AvaloniaKeyboardDriver { get; } - - public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager, StyleableWindow owner) : this() + public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this() { _virtualFileSystem = virtualFileSystem; _contentManager = contentManager; - _owner = owner; if (Program.PreviewerDetached) { LoadTimeZones(); - AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner); } } @@ -251,10 +256,10 @@ namespace Ryujinx.Ava.UI.ViewModels IsSDL2Enabled = SDL2HardwareDeviceDriver.IsSupported; } - private unsafe void LoadAvailableGpus() + private void LoadAvailableGpus() { _gpuIds = new List(); - List names = new List(); + List names = new(); var devices = VulkanRenderer.GetPhysicalDevices(); if (devices.Length == 0) @@ -272,7 +277,7 @@ namespace Ryujinx.Ava.UI.ViewModels } AvailableGpus.Clear(); - AvailableGpus.AddRange(names.Select(x => new ComboBoxItem() { Content = x })); + AvailableGpus.AddRange(names.Select(x => new ComboBoxItem { Content = x })); } public void LoadTimeZones() @@ -302,25 +307,6 @@ namespace Ryujinx.Ava.UI.ViewModels } } - public async void BrowseTheme() - { - var dialog = new OpenFileDialog() - { - Title = LocaleManager.Instance[LocaleKeys.SettingsSelectThemeFileDialogTitle], - AllowMultiple = false - }; - - dialog.Filters.Add(new FileDialogFilter() { Extensions = { "xaml" }, Name = LocaleManager.Instance[LocaleKeys.SettingsXamlThemeFile] }); - - var file = await dialog.ShowAsync(_owner); - - if (file != null && file.Length > 0) - { - CustomThemePath = file[0]; - OnPropertyChanged(nameof(CustomThemePath)); - } - } - public void LoadCurrentConfiguration() { ConfigurationState config = ConfigurationState.Instance; @@ -477,16 +463,8 @@ namespace Ryujinx.Ava.UI.ViewModels config.ToFileFormat().SaveConfig(Program.ConfigurationPath); MainWindow.UpdateGraphicsConfig(); - - if (_owner is SettingsWindow owner) - { - owner.ControllerSettings?.SaveCurrentProfile(); - } - - if (_owner.Owner is MainWindow window && _directoryChanged) - { - window.ViewModel.LoadApplications(); - } + + SaveSettingsEvent?.Invoke(); _directoryChanged = false; } @@ -504,13 +482,13 @@ namespace Ryujinx.Ava.UI.ViewModels public void OkButton() { SaveSettings(); - _owner.Close(); + CloseWindow?.Invoke(); } public void CancelButton() { RevertIfNotSaved(); - _owner.Close(); + CloseWindow?.Invoke(); } } } \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml b/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml new file mode 100644 index 00000000..35283353 --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml.cs b/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml.cs new file mode 100644 index 00000000..026c7fdf --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml.cs @@ -0,0 +1,12 @@ +using Avalonia.Controls; + +namespace Ryujinx.Ava.UI.Views.Settings +{ + public partial class SettingsAudioView : UserControl + { + public SettingsAudioView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml b/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml new file mode 100644 index 00000000..a0cf3452 --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml.cs b/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml.cs new file mode 100644 index 00000000..5c5b6079 --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml.cs @@ -0,0 +1,12 @@ +using Avalonia.Controls; + +namespace Ryujinx.Ava.UI.Views.Settings +{ + public partial class SettingsCPUView : UserControl + { + public SettingsCPUView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml b/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml new file mode 100644 index 00000000..1f65155a --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml.cs b/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml.cs new file mode 100644 index 00000000..8fe08552 --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml.cs @@ -0,0 +1,12 @@ +using Avalonia.Controls; + +namespace Ryujinx.Ava.UI.Views.Settings +{ + public partial class SettingsGraphicsView : UserControl + { + public SettingsGraphicsView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml b/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml new file mode 100644 index 00000000..361125bf --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs b/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs new file mode 100644 index 00000000..702f73e8 --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs @@ -0,0 +1,81 @@ +using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.Input; +using Avalonia.Interactivity; +using Ryujinx.Ava.Input; +using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Input; +using Ryujinx.Input.Assigner; + +namespace Ryujinx.Ava.UI.Views.Settings +{ + public partial class SettingsHotkeysView : UserControl + { + private ButtonKeyAssigner _currentAssigner; + private IGamepadDriver AvaloniaKeyboardDriver; + + public SettingsHotkeysView() + { + InitializeComponent(); + AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(this); + } + + private void MouseClick(object sender, PointerPressedEventArgs e) + { + bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed; + + _currentAssigner?.Cancel(shouldUnbind); + + PointerPressed -= MouseClick; + } + + private void Button_Checked(object sender, RoutedEventArgs e) + { + if (sender is ToggleButton button) + { + if (_currentAssigner != null && button == _currentAssigner.ToggledButton) + { + return; + } + + if (_currentAssigner == null && button.IsChecked != null && (bool)button.IsChecked) + { + _currentAssigner = new ButtonKeyAssigner(button); + + FocusManager.Instance?.Focus(this, NavigationMethod.Pointer); + + PointerPressed += MouseClick; + + var keyboard = (IKeyboard)AvaloniaKeyboardDriver.GetGamepad(AvaloniaKeyboardDriver.GamepadsIds[0]); + IButtonAssigner assigner = new KeyboardKeyAssigner(keyboard); + + _currentAssigner.GetInputAndAssign(assigner); + } + else + { + if (_currentAssigner != null) + { + ToggleButton oldButton = _currentAssigner.ToggledButton; + + _currentAssigner.Cancel(); + _currentAssigner = null; + + button.IsChecked = false; + } + } + } + } + + private void Button_Unchecked(object sender, RoutedEventArgs e) + { + _currentAssigner?.Cancel(); + _currentAssigner = null; + } + + public void Dispose() + { + _currentAssigner?.Cancel(); + _currentAssigner = null; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml b/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml new file mode 100644 index 00000000..1c774bda --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs b/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs new file mode 100644 index 00000000..0c2105ec --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs @@ -0,0 +1,17 @@ +using Avalonia.Controls; + +namespace Ryujinx.Ava.UI.Views.Settings +{ + public partial class SettingsInputView : UserControl + { + public SettingsInputView() + { + InitializeComponent(); + } + + public void Dispose() + { + ControllerSettings.Dispose(); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml b/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml new file mode 100644 index 00000000..2163dcda --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml.cs b/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml.cs new file mode 100644 index 00000000..2ec476ac --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml.cs @@ -0,0 +1,12 @@ +using Avalonia.Controls; + +namespace Ryujinx.Ava.UI.Views.Settings +{ + public partial class SettingsLoggingView : UserControl + { + public SettingsLoggingView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml b/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml new file mode 100644 index 00000000..8efd367d --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml.cs b/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml.cs new file mode 100644 index 00000000..d7407b9d --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml.cs @@ -0,0 +1,12 @@ +using Avalonia.Controls; + +namespace Ryujinx.Ava.UI.Views.Settings +{ + public partial class SettingsNetworkView : UserControl + { + public SettingsNetworkView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml b/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml new file mode 100644 index 00000000..ddcca39c --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs b/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs new file mode 100644 index 00000000..d2ea59de --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs @@ -0,0 +1,52 @@ +using Avalonia.Controls; +using Avalonia.Data; +using Avalonia.Data.Converters; +using Ryujinx.Ava.UI.ViewModels; +using System; +using System.Linq; +using TimeZone = Ryujinx.Ava.UI.Models.TimeZone; + +namespace Ryujinx.Ava.UI.Views.Settings +{ + public partial class SettingsSystemView : UserControl + { + public SettingsViewModel ViewModel; + + public SettingsSystemView() + { + InitializeComponent(); + + FuncMultiValueConverter converter = new(parts => string.Format("{0} {1} {2}", parts.ToArray()).Trim()); + MultiBinding tzMultiBinding = new() { Converter = converter }; + + tzMultiBinding.Bindings.Add(new Binding("UtcDifference")); + tzMultiBinding.Bindings.Add(new Binding("Location")); + tzMultiBinding.Bindings.Add(new Binding("Abbreviation")); + + TimeZoneBox.ValueMemberBinding = tzMultiBinding; + } + + private void TimeZoneBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (e.AddedItems != null && e.AddedItems.Count > 0) + { + if (e.AddedItems[0] is TimeZone timeZone) + { + e.Handled = true; + + ViewModel.ValidateAndSetTimeZone(timeZone.Location); + } + } + } + + private void TimeZoneBox_OnTextChanged(object sender, EventArgs e) + { + if (sender is AutoCompleteBox box && box.SelectedItem is TimeZone timeZone) + { + { + ViewModel.ValidateAndSetTimeZone(timeZone.Location); + } + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml b/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml new file mode 100644 index 00000000..61b6c433 --- /dev/null +++ b/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - -