/ src / Ryujinx / UI / Views / Main / MainMenuBarView.axaml.cs
MainMenuBarView.axaml.cs
  1  using Avalonia;
  2  using Avalonia.Controls;
  3  using Avalonia.Interactivity;
  4  using Avalonia.Threading;
  5  using LibHac.Ncm;
  6  using LibHac.Tools.FsSystem.NcaUtils;
  7  using Ryujinx.Ava.Common.Locale;
  8  using Ryujinx.Ava.UI.Helpers;
  9  using Ryujinx.Ava.UI.ViewModels;
 10  using Ryujinx.Ava.UI.Windows;
 11  using Ryujinx.Common;
 12  using Ryujinx.Common.Utilities;
 13  using Ryujinx.Modules;
 14  using Ryujinx.UI.App.Common;
 15  using Ryujinx.UI.Common;
 16  using Ryujinx.UI.Common.Configuration;
 17  using Ryujinx.UI.Common.Helper;
 18  using System;
 19  using System.Collections.Generic;
 20  using System.IO;
 21  using System.Linq;
 22  
 23  namespace Ryujinx.Ava.UI.Views.Main
 24  {
 25      public partial class MainMenuBarView : UserControl
 26      {
 27          public MainWindow Window { get; private set; }
 28          public MainWindowViewModel ViewModel { get; private set; }
 29  
 30          public MainMenuBarView()
 31          {
 32              InitializeComponent();
 33  
 34              ToggleFileTypesMenuItem.ItemsSource = GenerateToggleFileTypeItems();
 35              ChangeLanguageMenuItem.ItemsSource = GenerateLanguageMenuItems();
 36          }
 37  
 38          private CheckBox[] GenerateToggleFileTypeItems()
 39          {
 40              List<CheckBox> checkBoxes = new();
 41  
 42              foreach (var item in Enum.GetValues(typeof(FileTypes)))
 43              {
 44                  string fileName = Enum.GetName(typeof(FileTypes), item);
 45                  checkBoxes.Add(new CheckBox
 46                  {
 47                      Content = $".{fileName}",
 48                      IsChecked = ((FileTypes)item).GetConfigValue(ConfigurationState.Instance.UI.ShownFileTypes),
 49                      Command = MiniCommand.Create(() => Window.ToggleFileType(fileName)),
 50                  });
 51              }
 52  
 53              return checkBoxes.ToArray();
 54          }
 55  
 56          private static MenuItem[] GenerateLanguageMenuItems()
 57          {
 58              List<MenuItem> menuItems = new();
 59  
 60              string localePath = "Ryujinx/Assets/Locales";
 61              string localeExt = ".json";
 62  
 63              string[] localesPath = EmbeddedResources.GetAllAvailableResources(localePath, localeExt);
 64  
 65              Array.Sort(localesPath);
 66  
 67              foreach (string locale in localesPath)
 68              {
 69                  string languageCode = Path.GetFileNameWithoutExtension(locale).Split('.').Last();
 70                  string languageJson = EmbeddedResources.ReadAllText($"{localePath}/{languageCode}{localeExt}");
 71                  var strings = JsonHelper.Deserialize(languageJson, CommonJsonContext.Default.StringDictionary);
 72  
 73                  if (!strings.TryGetValue("Language", out string languageName))
 74                  {
 75                      languageName = languageCode;
 76                  }
 77  
 78                  MenuItem menuItem = new()
 79                  {
 80                      Header = languageName,
 81                      Command = MiniCommand.Create(() =>
 82                      {
 83                          MainWindowViewModel.ChangeLanguage(languageCode);
 84                      }),
 85                  };
 86  
 87                  menuItems.Add(menuItem);
 88              }
 89  
 90              return menuItems.ToArray();
 91          }
 92  
 93          protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
 94          {
 95              base.OnAttachedToVisualTree(e);
 96  
 97              if (VisualRoot is MainWindow window)
 98              {
 99                  Window = window;
100              }
101  
102              ViewModel = Window.ViewModel;
103              DataContext = ViewModel;
104          }
105  
106          private async void StopEmulation_Click(object sender, RoutedEventArgs e)
107          {
108              await Window.ViewModel.AppHost?.ShowExitPrompt();
109          }
110  
111          private void PauseEmulation_Click(object sender, RoutedEventArgs e)
112          {
113              Window.ViewModel.AppHost?.Pause();
114          }
115  
116          private void ResumeEmulation_Click(object sender, RoutedEventArgs e)
117          {
118              Window.ViewModel.AppHost?.Resume();
119          }
120  
121          public async void OpenSettings(object sender, RoutedEventArgs e)
122          {
123              Window.SettingsWindow = new(Window.VirtualFileSystem, Window.ContentManager);
124  
125              await Window.SettingsWindow.ShowDialog(Window);
126  
127              Window.SettingsWindow = null;
128  
129              ViewModel.LoadConfigurableHotKeys();
130          }
131  
132          public async void OpenMiiApplet(object sender, RoutedEventArgs e)
133          {
134              string contentPath = ViewModel.ContentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
135  
136              if (!string.IsNullOrEmpty(contentPath))
137              {
138                  ApplicationData applicationData = new()
139                  {
140                      Name = "miiEdit",
141                      Id = 0x0100000000001009,
142                      Path = contentPath,
143                  };
144  
145                  await ViewModel.LoadApplication(applicationData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen);
146              }
147          }
148  
149          public async void OpenAmiiboWindow(object sender, RoutedEventArgs e)
150          {
151              if (!ViewModel.IsAmiiboRequested)
152              {
153                  return;
154              }
155  
156              if (ViewModel.AppHost.Device.System.SearchingForAmiibo(out int deviceId))
157              {
158                  string titleId = ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper();
159                  AmiiboWindow window = new(ViewModel.ShowAll, ViewModel.LastScannedAmiiboId, titleId);
160  
161                  await window.ShowDialog(Window);
162  
163                  if (window.IsScanned)
164                  {
165                      ViewModel.ShowAll = window.ViewModel.ShowAllAmiibo;
166                      ViewModel.LastScannedAmiiboId = window.ScannedAmiibo.GetId();
167  
168                      ViewModel.AppHost.Device.System.ScanAmiibo(deviceId, ViewModel.LastScannedAmiiboId, window.ViewModel.UseRandomUuid);
169                  }
170              }
171          }
172  
173          public async void OpenCheatManagerForCurrentApp(object sender, RoutedEventArgs e)
174          {
175              if (!ViewModel.IsGameRunning)
176              {
177                  return;
178              }
179  
180              string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString();
181  
182              await new CheatWindow(
183                  Window.VirtualFileSystem,
184                  ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText,
185                  name,
186                  Window.ViewModel.SelectedApplication.Path).ShowDialog(Window);
187  
188              ViewModel.AppHost.Device.EnableCheats();
189          }
190  
191          private void ScanAmiiboMenuItem_AttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
192          {
193              if (sender is MenuItem)
194              {
195                  ViewModel.IsAmiiboRequested = Window.ViewModel.AppHost.Device.System.SearchingForAmiibo(out _);
196              }
197          }
198  
199          private async void InstallFileTypes_Click(object sender, RoutedEventArgs e)
200          {
201              if (FileAssociationHelper.Install())
202              {
203                  await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
204              }
205              else
206              {
207                  await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesErrorMessage]);
208              }
209          }
210  
211          private async void UninstallFileTypes_Click(object sender, RoutedEventArgs e)
212          {
213              if (FileAssociationHelper.Uninstall())
214              {
215                  await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
216              }
217              else
218              {
219                  await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesErrorMessage]);
220              }
221          }
222  
223          private async void ChangeWindowSize_Click(object sender, RoutedEventArgs e)
224          {
225              if (sender is MenuItem item)
226              {
227                  int height;
228                  int width;
229  
230                  switch (item.Tag)
231                  {
232                      case "720":
233                          height = 720;
234                          width = 1280;
235                          break;
236  
237                      case "1080":
238                          height = 1080;
239                          width = 1920;
240                          break;
241  
242                      default:
243                          throw new ArgumentNullException($"Invalid Tag for {item}");
244                  }
245  
246                  await Dispatcher.UIThread.InvokeAsync(() =>
247                  {
248                      ViewModel.WindowState = WindowState.Normal;
249  
250                      height += (int)Window.StatusBarHeight + (int)Window.MenuBarHeight;
251  
252                      Window.Arrange(new Rect(Window.Position.X, Window.Position.Y, width, height));
253                  });
254              }
255          }
256  
257          public async void CheckForUpdates(object sender, RoutedEventArgs e)
258          {
259              if (Updater.CanUpdate(true))
260              {
261                  await Updater.BeginParse(Window, true);
262              }
263          }
264  
265          public async void OpenAboutWindow(object sender, RoutedEventArgs e)
266          {
267              await AboutWindow.Show();
268          }
269  
270          public void CloseWindow(object sender, RoutedEventArgs e)
271          {
272              Window.Close();
273          }
274      }
275  }