SettingsWindow.axaml.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. using Avalonia;
  2. using Avalonia.Controls;
  3. using Avalonia.Controls.Presenters;
  4. using Avalonia.Controls.Primitives;
  5. using Avalonia.Data;
  6. using Avalonia.Data.Converters;
  7. using Avalonia.Input;
  8. using Avalonia.Interactivity;
  9. using Avalonia.LogicalTree;
  10. using Avalonia.Markup.Xaml;
  11. using Avalonia.Threading;
  12. using FluentAvalonia.Core;
  13. using FluentAvalonia.UI.Controls;
  14. using Ryujinx.Ava.Common.Locale;
  15. using Ryujinx.Ava.Ui.Controls;
  16. using Ryujinx.Ava.Ui.Models;
  17. using Ryujinx.Ava.Ui.ViewModels;
  18. using Ryujinx.HLE.FileSystem;
  19. using Ryujinx.Input;
  20. using Ryujinx.Input.Assigner;
  21. using System;
  22. using System.Collections.Generic;
  23. using System.Diagnostics;
  24. using System.IO;
  25. using System.Linq;
  26. using System.Threading;
  27. using System.Threading.Tasks;
  28. using TimeZone = Ryujinx.Ava.Ui.Models.TimeZone;
  29. namespace Ryujinx.Ava.Ui.Windows
  30. {
  31. public partial class SettingsWindow : StyleableWindow
  32. {
  33. private ButtonKeyAssigner _currentAssigner;
  34. internal SettingsViewModel ViewModel { get; set; }
  35. public SettingsWindow(VirtualFileSystem virtualFileSystem, ContentManager contentManager)
  36. {
  37. Title = $"Ryujinx {Program.Version} - {LocaleManager.Instance["Settings"]}";
  38. ViewModel = new SettingsViewModel(virtualFileSystem, contentManager, this);
  39. DataContext = ViewModel;
  40. InitializeComponent();
  41. Load();
  42. AttachDebugDevTools();
  43. FuncMultiValueConverter<string, string> converter = new(parts => string.Format("{0} {1} {2}", parts.ToArray()));
  44. MultiBinding tzMultiBinding = new() { Converter = converter };
  45. tzMultiBinding.Bindings.Add(new Binding("UtcDifference"));
  46. tzMultiBinding.Bindings.Add(new Binding("Location"));
  47. tzMultiBinding.Bindings.Add(new Binding("Abbreviation"));
  48. TimeZoneBox.ValueMemberBinding = tzMultiBinding;
  49. }
  50. public SettingsWindow()
  51. {
  52. ViewModel = new SettingsViewModel();
  53. DataContext = ViewModel;
  54. InitializeComponent();
  55. Load();
  56. AttachDebugDevTools();
  57. }
  58. [Conditional("DEBUG")]
  59. private void AttachDebugDevTools()
  60. {
  61. this.AttachDevTools();
  62. }
  63. private void Load()
  64. {
  65. Pages.Children.Clear();
  66. NavPanel.SelectionChanged += NavPanelOnSelectionChanged;
  67. NavPanel.SelectedItem = NavPanel.MenuItems.ElementAt(0);
  68. }
  69. private void Button_Checked(object sender, RoutedEventArgs e)
  70. {
  71. if (sender is ToggleButton button)
  72. {
  73. if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
  74. {
  75. return;
  76. }
  77. if (_currentAssigner == null && (bool)button.IsChecked)
  78. {
  79. _currentAssigner = new ButtonKeyAssigner(button);
  80. FocusManager.Instance.Focus(this, NavigationMethod.Pointer);
  81. PointerPressed += MouseClick;
  82. IKeyboard keyboard = (IKeyboard)ViewModel.AvaloniaKeyboardDriver.GetGamepad(ViewModel.AvaloniaKeyboardDriver.GamepadsIds[0]);
  83. IButtonAssigner assigner = new KeyboardKeyAssigner(keyboard);
  84. _currentAssigner.GetInputAndAssign(assigner);
  85. }
  86. else
  87. {
  88. if (_currentAssigner != null)
  89. {
  90. ToggleButton oldButton = _currentAssigner.ToggledButton;
  91. _currentAssigner.Cancel();
  92. _currentAssigner = null;
  93. button.IsChecked = false;
  94. }
  95. }
  96. }
  97. }
  98. private void Button_Unchecked(object sender, RoutedEventArgs e)
  99. {
  100. _currentAssigner?.Cancel();
  101. _currentAssigner = null;
  102. }
  103. private void MouseClick(object sender, PointerPressedEventArgs e)
  104. {
  105. bool shouldUnbind = false;
  106. if (e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed)
  107. {
  108. shouldUnbind = true;
  109. }
  110. _currentAssigner?.Cancel(shouldUnbind);
  111. PointerPressed -= MouseClick;
  112. }
  113. private void NavPanelOnSelectionChanged(object sender, NavigationViewSelectionChangedEventArgs e)
  114. {
  115. if (e.SelectedItem is NavigationViewItem navitem)
  116. {
  117. switch (navitem.Tag.ToString())
  118. {
  119. case "UiPage":
  120. NavPanel.Content = UiPage;
  121. break;
  122. case "InputPage":
  123. NavPanel.Content = InputPage;
  124. break;
  125. case "HotkeysPage":
  126. NavPanel.Content = HotkeysPage;
  127. break;
  128. case "SystemPage":
  129. NavPanel.Content = SystemPage;
  130. break;
  131. case "CpuPage":
  132. NavPanel.Content = CpuPage;
  133. break;
  134. case "GraphicsPage":
  135. NavPanel.Content = GraphicsPage;
  136. break;
  137. case "AudioPage":
  138. NavPanel.Content = AudioPage;
  139. break;
  140. case "NetworkPage":
  141. NavPanel.Content = NetworkPage;
  142. break;
  143. case "LoggingPage":
  144. NavPanel.Content = LoggingPage;
  145. break;
  146. }
  147. }
  148. }
  149. private async void AddButton_OnClick(object sender, RoutedEventArgs e)
  150. {
  151. string path = PathBox.Text;
  152. if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.GameDirectories.Contains(path))
  153. {
  154. ViewModel.GameDirectories.Add(path);
  155. }
  156. else
  157. {
  158. path = await new OpenFolderDialog().ShowAsync(this);
  159. if (!string.IsNullOrWhiteSpace(path))
  160. {
  161. ViewModel.GameDirectories.Add(path);
  162. }
  163. }
  164. }
  165. private void RemoveButton_OnClick(object sender, RoutedEventArgs e)
  166. {
  167. List<string> selected = new(GameList.SelectedItems.Cast<string>());
  168. foreach (string path in selected)
  169. {
  170. ViewModel.GameDirectories.Remove(path);
  171. }
  172. }
  173. private void TimeZoneBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
  174. {
  175. if (e.AddedItems != null && e.AddedItems.Count > 0)
  176. {
  177. if (e.AddedItems[0] is TimeZone timeZone)
  178. {
  179. e.Handled = true;
  180. ViewModel.ValidateAndSetTimeZone(timeZone.Location);
  181. }
  182. }
  183. }
  184. private void TimeZoneBox_OnTextChanged(object sender, EventArgs e)
  185. {
  186. if (sender is AutoCompleteBox box)
  187. {
  188. if (box.SelectedItem != null && box.SelectedItem is TimeZone timeZone)
  189. {
  190. ViewModel.ValidateAndSetTimeZone(timeZone.Location);
  191. }
  192. }
  193. }
  194. private void SaveButton_Clicked(object sender, RoutedEventArgs e)
  195. {
  196. SaveSettings();
  197. Close();
  198. }
  199. private void CloseButton_Clicked(object sender, RoutedEventArgs e)
  200. {
  201. ViewModel.RevertIfNotSaved();
  202. Close();
  203. }
  204. private void ApplyButton_Clicked(object sender, RoutedEventArgs e)
  205. {
  206. SaveSettings();
  207. }
  208. private void SaveSettings()
  209. {
  210. ViewModel.SaveSettings();
  211. ControllerSettings?.SaveCurrentProfile();
  212. if (Owner is MainWindow window)
  213. {
  214. window.ViewModel.LoadApplications();
  215. }
  216. }
  217. protected override void OnClosed(EventArgs e)
  218. {
  219. ControllerSettings.Dispose();
  220. _currentAssigner?.Cancel();
  221. _currentAssigner = null;
  222. base.OnClosed(e);
  223. }
  224. }
  225. }