AvaHostUiHandler.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. using Avalonia.Controls;
  2. using Avalonia.Threading;
  3. using FluentAvalonia.UI.Controls;
  4. using Ryujinx.Ava.Common.Locale;
  5. using Ryujinx.Ava.UI.Controls;
  6. using Ryujinx.Ava.UI.Helpers;
  7. using Ryujinx.Ava.UI.Windows;
  8. using Ryujinx.HLE;
  9. using Ryujinx.HLE.HOS.Applets;
  10. using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
  11. using Ryujinx.HLE.Ui;
  12. using System;
  13. using System.Threading;
  14. namespace Ryujinx.Ava.UI.Applet
  15. {
  16. internal class AvaHostUiHandler : IHostUiHandler
  17. {
  18. private readonly MainWindow _parent;
  19. public IHostUiTheme HostUiTheme { get; }
  20. public AvaHostUiHandler(MainWindow parent)
  21. {
  22. _parent = parent;
  23. HostUiTheme = new AvaloniaHostUiTheme(parent);
  24. }
  25. public bool DisplayMessageDialog(ControllerAppletUiArgs args)
  26. {
  27. string playerCount = args.PlayerCountMin == args.PlayerCountMax
  28. ? args.PlayerCountMin.ToString()
  29. : $"{args.PlayerCountMin}-{args.PlayerCountMax}";
  30. LocaleKeys key = args.PlayerCountMin == args.PlayerCountMax ? LocaleKeys.DialogControllerAppletMessage : LocaleKeys.DialogControllerAppletMessagePlayerRange;
  31. string message = string.Format(LocaleManager.Instance[key],
  32. playerCount,
  33. args.SupportedStyles,
  34. string.Join(", ", args.SupportedPlayers),
  35. args.IsDocked ? LocaleManager.Instance[LocaleKeys.DialogControllerAppletDockModeSet] : "");
  36. return DisplayMessageDialog(LocaleManager.Instance[LocaleKeys.DialogControllerAppletTitle], message);
  37. }
  38. public bool DisplayMessageDialog(string title, string message)
  39. {
  40. ManualResetEvent dialogCloseEvent = new(false);
  41. bool okPressed = false;
  42. Dispatcher.UIThread.InvokeAsync(async () =>
  43. {
  44. try
  45. {
  46. ManualResetEvent deferEvent = new(false);
  47. bool opened = false;
  48. UserResult response = await ContentDialogHelper.ShowDeferredContentDialog(_parent,
  49. title,
  50. message,
  51. "",
  52. LocaleManager.Instance[LocaleKeys.DialogOpenSettingsWindowLabel],
  53. "",
  54. LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
  55. (int)Symbol.Important,
  56. deferEvent,
  57. async (window) =>
  58. {
  59. if (opened)
  60. {
  61. return;
  62. }
  63. opened = true;
  64. _parent.SettingsWindow = new SettingsWindow(_parent.VirtualFileSystem, _parent.ContentManager);
  65. await _parent.SettingsWindow.ShowDialog(window);
  66. opened = false;
  67. });
  68. if (response == UserResult.Ok)
  69. {
  70. okPressed = true;
  71. }
  72. dialogCloseEvent.Set();
  73. }
  74. catch (Exception ex)
  75. {
  76. await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogMessageDialogErrorExceptionMessage], ex));
  77. dialogCloseEvent.Set();
  78. }
  79. });
  80. dialogCloseEvent.WaitOne();
  81. return okPressed;
  82. }
  83. public bool DisplayInputDialog(SoftwareKeyboardUiArgs args, out string userText)
  84. {
  85. ManualResetEvent dialogCloseEvent = new(false);
  86. bool okPressed = false;
  87. bool error = false;
  88. string inputText = args.InitialText ?? "";
  89. Dispatcher.UIThread.Post(async () =>
  90. {
  91. try
  92. {
  93. var response = await SwkbdAppletDialog.ShowInputDialog(_parent, LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args);
  94. if (response.Result == UserResult.Ok)
  95. {
  96. inputText = response.Input;
  97. okPressed = true;
  98. }
  99. }
  100. catch (Exception ex)
  101. {
  102. error = true;
  103. await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogSoftwareKeyboardErrorExceptionMessage], ex));
  104. }
  105. finally
  106. {
  107. dialogCloseEvent.Set();
  108. }
  109. });
  110. dialogCloseEvent.WaitOne();
  111. userText = error ? null : inputText;
  112. return error || okPressed;
  113. }
  114. public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
  115. {
  116. device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
  117. if (_parent.ViewModel.AppHost != null)
  118. {
  119. _parent.ViewModel.AppHost.Stop();
  120. }
  121. }
  122. public bool DisplayErrorAppletDialog(string title, string message, string[] buttons)
  123. {
  124. ManualResetEvent dialogCloseEvent = new(false);
  125. bool showDetails = false;
  126. Dispatcher.UIThread.Post(async () =>
  127. {
  128. try
  129. {
  130. ErrorAppletWindow msgDialog = new(_parent, buttons, message)
  131. {
  132. Title = title,
  133. WindowStartupLocation = WindowStartupLocation.CenterScreen,
  134. Width = 400
  135. };
  136. object response = await msgDialog.Run();
  137. if (response != null && buttons != null && buttons.Length > 1 && (int)response != buttons.Length - 1)
  138. {
  139. showDetails = true;
  140. }
  141. dialogCloseEvent.Set();
  142. msgDialog.Close();
  143. }
  144. catch (Exception ex)
  145. {
  146. dialogCloseEvent.Set();
  147. await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogErrorAppletErrorExceptionMessage], ex));
  148. }
  149. });
  150. dialogCloseEvent.WaitOne();
  151. return showDetails;
  152. }
  153. public IDynamicTextInputHandler CreateDynamicTextInputHandler()
  154. {
  155. return new AvaloniaDynamicTextInputHandler(_parent);
  156. }
  157. }
  158. }