MainMenuBarView.axaml.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. using Avalonia;
  2. using Avalonia.Controls;
  3. using Avalonia.Interactivity;
  4. using Avalonia.Threading;
  5. using Gommon;
  6. using Ryujinx.Ava.Common.Locale;
  7. using Ryujinx.Ava.UI.Helpers;
  8. using Ryujinx.Ava.UI.ViewModels;
  9. using Ryujinx.Ava.UI.Windows;
  10. using Ryujinx.Common;
  11. using Ryujinx.Common.Utilities;
  12. using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
  13. using Ryujinx.UI.Common;
  14. using Ryujinx.UI.Common.Configuration;
  15. using Ryujinx.UI.Common.Helper;
  16. using System;
  17. using System.Collections.Generic;
  18. using System.Linq;
  19. namespace Ryujinx.Ava.UI.Views.Main
  20. {
  21. public partial class MainMenuBarView : UserControl
  22. {
  23. public MainWindow Window { get; private set; }
  24. public MainWindowViewModel ViewModel { get; private set; }
  25. public MainMenuBarView()
  26. {
  27. InitializeComponent();
  28. RyuLogo.IsVisible = !ConfigurationState.Instance.ShowTitleBar;
  29. ToggleFileTypesMenuItem.ItemsSource = GenerateToggleFileTypeItems();
  30. ChangeLanguageMenuItem.ItemsSource = GenerateLanguageMenuItems();
  31. }
  32. private CheckBox[] GenerateToggleFileTypeItems() =>
  33. Enum.GetValues<FileTypes>()
  34. .Select(it => (FileName: Enum.GetName(it)!, FileType: it))
  35. .Select(it =>
  36. new CheckBox
  37. {
  38. Content = $".{it.FileName}",
  39. IsChecked = it.FileType.GetConfigValue(ConfigurationState.Instance.UI.ShownFileTypes),
  40. Command = MiniCommand.Create(() => Window.ToggleFileType(it.FileName))
  41. }
  42. ).ToArray();
  43. private static MenuItem[] GenerateLanguageMenuItems()
  44. {
  45. List<MenuItem> menuItems = new();
  46. string localePath = "Ryujinx/Assets/locales.json";
  47. string languageJson = EmbeddedResources.ReadAllText(localePath);
  48. LocalesJson locales = JsonHelper.Deserialize(languageJson, LocalesJsonContext.Default.LocalesJson);
  49. foreach (string language in locales.Languages)
  50. {
  51. int index = locales.Locales.FindIndex(x => x.ID == "Language");
  52. string languageName;
  53. if (index == -1)
  54. {
  55. languageName = language;
  56. }
  57. else
  58. {
  59. languageName = locales.Locales[index].Translations[language] == "" ? language : locales.Locales[index].Translations[language];
  60. }
  61. MenuItem menuItem = new()
  62. {
  63. Padding = new Thickness(10, 0, 0, 0),
  64. Header = " " + languageName,
  65. Command = MiniCommand.Create(() => MainWindowViewModel.ChangeLanguage(language))
  66. };
  67. menuItems.Add(menuItem);
  68. }
  69. return menuItems.ToArray();
  70. }
  71. protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
  72. {
  73. base.OnAttachedToVisualTree(e);
  74. if (VisualRoot is MainWindow window)
  75. {
  76. Window = window;
  77. DataContext = ViewModel = window.ViewModel;
  78. }
  79. }
  80. private async void StopEmulation_Click(object sender, RoutedEventArgs e)
  81. {
  82. await ViewModel.AppHost?.ShowExitPrompt().OrCompleted()!;
  83. }
  84. private void PauseEmulation_Click(object sender, RoutedEventArgs e)
  85. {
  86. ViewModel.AppHost?.Pause();
  87. }
  88. private void ResumeEmulation_Click(object sender, RoutedEventArgs e)
  89. {
  90. ViewModel.AppHost?.Resume();
  91. }
  92. public async void OpenSettings(object sender, RoutedEventArgs e)
  93. {
  94. Window.SettingsWindow = new(Window.VirtualFileSystem, Window.ContentManager);
  95. await Window.SettingsWindow.ShowDialog(Window);
  96. Window.SettingsWindow = null;
  97. ViewModel.LoadConfigurableHotKeys();
  98. }
  99. public static readonly AppletMetadata MiiApplet = new("miiEdit", 0x0100000000001009);
  100. public async void OpenMiiApplet(object sender, RoutedEventArgs e)
  101. {
  102. if (MiiApplet.CanStart(ViewModel.ContentManager, out var appData, out var nacpData))
  103. {
  104. await ViewModel.LoadApplication(appData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
  105. }
  106. }
  107. public async void OpenAmiiboWindow(object sender, RoutedEventArgs e)
  108. => await ViewModel.OpenAmiiboWindow();
  109. public async void OpenBinFile(object sender, RoutedEventArgs e)
  110. => await ViewModel.OpenBinFile();
  111. public async void OpenCheatManagerForCurrentApp(object sender, RoutedEventArgs e)
  112. {
  113. if (!ViewModel.IsGameRunning)
  114. return;
  115. string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString();
  116. await new CheatWindow(
  117. Window.VirtualFileSystem,
  118. ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText,
  119. name,
  120. ViewModel.SelectedApplication.Path).ShowDialog(Window);
  121. ViewModel.AppHost.Device.EnableCheats();
  122. }
  123. private void ScanAmiiboMenuItem_AttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
  124. {
  125. if (sender is MenuItem)
  126. ViewModel.IsAmiiboRequested = ViewModel.AppHost.Device.System.SearchingForAmiibo(out _);
  127. }
  128. private void ScanBinAmiiboMenuItem_AttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
  129. {
  130. if (sender is MenuItem)
  131. ViewModel.IsAmiiboBinRequested = ViewModel.IsAmiiboRequested && AmiiboBinReader.HasAmiiboKeyFile;
  132. }
  133. private async void InstallFileTypes_Click(object sender, RoutedEventArgs e)
  134. {
  135. ViewModel.AreMimeTypesRegistered = FileAssociationHelper.Install();
  136. if (ViewModel.AreMimeTypesRegistered)
  137. await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
  138. else
  139. await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesErrorMessage]);
  140. }
  141. private async void UninstallFileTypes_Click(object sender, RoutedEventArgs e)
  142. {
  143. ViewModel.AreMimeTypesRegistered = !FileAssociationHelper.Uninstall();
  144. if (!ViewModel.AreMimeTypesRegistered)
  145. await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
  146. else
  147. await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesErrorMessage]);
  148. }
  149. private async void ChangeWindowSize_Click(object sender, RoutedEventArgs e)
  150. {
  151. if (sender is not MenuItem { Tag: string resolution })
  152. return;
  153. (int resolutionWidth, int resolutionHeight) = resolution.Split(' ', 2)
  154. .Into(parts =>
  155. (int.Parse(parts[0]), int.Parse(parts[1]))
  156. );
  157. // Correctly size window when 'TitleBar' is enabled (Nov. 14, 2024)
  158. double barsHeight = ((Window.StatusBarHeight + Window.MenuBarHeight) +
  159. (ConfigurationState.Instance.ShowTitleBar ? (int)Window.TitleBar.Height : 0));
  160. double windowWidthScaled = (resolutionWidth * Program.WindowScaleFactor);
  161. double windowHeightScaled = ((resolutionHeight + barsHeight) * Program.WindowScaleFactor);
  162. await Dispatcher.UIThread.InvokeAsync(() =>
  163. {
  164. ViewModel.WindowState = WindowState.Normal;
  165. Window.Arrange(new Rect(Window.Position.X, Window.Position.Y, windowWidthScaled, windowHeightScaled));
  166. });
  167. }
  168. public async void CheckForUpdates(object sender, RoutedEventArgs e)
  169. {
  170. if (Updater.CanUpdate(true))
  171. await Updater.BeginUpdateAsync(true);
  172. }
  173. private void MenuItem_OnClick(object sender, RoutedEventArgs e)
  174. {
  175. if (sender is MenuItem { Tag: string url })
  176. OpenHelper.OpenUrl(url);
  177. }
  178. public async void OpenXCITrimmerWindow(object sender, RoutedEventArgs e) => await XCITrimmerWindow.Show(ViewModel);
  179. public async void OpenAboutWindow(object sender, RoutedEventArgs e) => await AboutWindow.Show();
  180. public void CloseWindow(object sender, RoutedEventArgs e) => Window.Close();
  181. }
  182. }