ContentDialogHelper.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. using Avalonia.Controls;
  2. using Avalonia.Threading;
  3. using FluentAvalonia.UI.Controls;
  4. using Ryujinx.Ava.Common.Locale;
  5. using Ryujinx.Ava.Ui.Models;
  6. using Ryujinx.Ava.Ui.Windows;
  7. using Ryujinx.Common.Logging;
  8. using System;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. namespace Ryujinx.Ava.Ui.Controls
  12. {
  13. public static class ContentDialogHelper
  14. {
  15. private static bool _isChoiceDialogOpen;
  16. private async static Task<UserResult> ShowContentDialog(
  17. string title,
  18. string primaryText,
  19. string secondaryText,
  20. string primaryButton,
  21. string secondaryButton,
  22. string closeButton,
  23. int iconSymbol,
  24. UserResult primaryButtonResult = UserResult.Ok)
  25. {
  26. UserResult result = UserResult.None;
  27. ContentDialog contentDialog = new ContentDialog();
  28. await ShowDialog();
  29. async Task ShowDialog()
  30. {
  31. contentDialog.Title = title;
  32. contentDialog.PrimaryButtonText = primaryButton;
  33. contentDialog.SecondaryButtonText = secondaryButton;
  34. contentDialog.CloseButtonText = closeButton;
  35. contentDialog.Content = CreateDialogTextContent(primaryText, secondaryText, iconSymbol);
  36. contentDialog.PrimaryButtonCommand = MiniCommand.Create(() =>
  37. {
  38. result = primaryButtonResult;
  39. });
  40. contentDialog.SecondaryButtonCommand = MiniCommand.Create(() =>
  41. {
  42. result = UserResult.No;
  43. });
  44. contentDialog.CloseButtonCommand = MiniCommand.Create(() =>
  45. {
  46. result = UserResult.Cancel;
  47. });
  48. await contentDialog.ShowAsync(ContentDialogPlacement.Popup);
  49. }
  50. return result;
  51. }
  52. public async static Task<UserResult> ShowDeferredContentDialog(
  53. StyleableWindow window,
  54. string title,
  55. string primaryText,
  56. string secondaryText,
  57. string primaryButton,
  58. string secondaryButton,
  59. string closeButton,
  60. int iconSymbol,
  61. ManualResetEvent deferResetEvent,
  62. Func<Window, Task> doWhileDeferred = null)
  63. {
  64. bool startedDeferring = false;
  65. UserResult result = UserResult.None;
  66. ContentDialog contentDialog = new ContentDialog
  67. {
  68. Title = title,
  69. PrimaryButtonText = primaryButton,
  70. SecondaryButtonText = secondaryButton,
  71. CloseButtonText = closeButton,
  72. Content = CreateDialogTextContent(primaryText, secondaryText, iconSymbol),
  73. PrimaryButtonCommand = MiniCommand.Create(() =>
  74. {
  75. result = primaryButton == LocaleManager.Instance["InputDialogYes"] ? UserResult.Yes : UserResult.Ok;
  76. }),
  77. };
  78. contentDialog.SecondaryButtonCommand = MiniCommand.Create(() =>
  79. {
  80. contentDialog.PrimaryButtonClick -= DeferClose;
  81. result = UserResult.No;
  82. });
  83. contentDialog.CloseButtonCommand = MiniCommand.Create(() =>
  84. {
  85. contentDialog.PrimaryButtonClick -= DeferClose;
  86. result = UserResult.Cancel;
  87. });
  88. contentDialog.PrimaryButtonClick += DeferClose;
  89. await contentDialog.ShowAsync(ContentDialogPlacement.Popup);
  90. return result;
  91. async void DeferClose(ContentDialog sender, ContentDialogButtonClickEventArgs args)
  92. {
  93. if (startedDeferring)
  94. {
  95. return;
  96. }
  97. contentDialog.PrimaryButtonClick -= DeferClose;
  98. startedDeferring = true;
  99. var deferral = args.GetDeferral();
  100. result = primaryButton == LocaleManager.Instance["InputDialogYes"] ? UserResult.Yes : UserResult.Ok;
  101. contentDialog.PrimaryButtonClick -= DeferClose;
  102. #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
  103. Task.Run(() =>
  104. {
  105. deferResetEvent.WaitOne();
  106. Dispatcher.UIThread.Post(() =>
  107. {
  108. deferral.Complete();
  109. });
  110. });
  111. #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
  112. if (doWhileDeferred != null)
  113. {
  114. await doWhileDeferred(window);
  115. deferResetEvent.Set();
  116. }
  117. }
  118. }
  119. private static Grid CreateDialogTextContent(string primaryText, string secondaryText, int symbol)
  120. {
  121. Grid content = new Grid();
  122. content.RowDefinitions = new RowDefinitions() { new RowDefinition(), new RowDefinition() };
  123. content.ColumnDefinitions = new ColumnDefinitions() { new ColumnDefinition(GridLength.Auto), new ColumnDefinition() };
  124. content.MinHeight = 80;
  125. SymbolIcon icon = new SymbolIcon { Symbol = (Symbol)symbol, Margin = new Avalonia.Thickness(10) };
  126. icon.FontSize = 40;
  127. icon.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center;
  128. Grid.SetColumn(icon, 0);
  129. Grid.SetRowSpan(icon, 2);
  130. Grid.SetRow(icon, 0);
  131. TextBlock primaryLabel = new TextBlock()
  132. {
  133. Text = primaryText,
  134. Margin = new Avalonia.Thickness(5),
  135. TextWrapping = Avalonia.Media.TextWrapping.Wrap,
  136. MaxWidth = 450
  137. };
  138. TextBlock secondaryLabel = new TextBlock()
  139. {
  140. Text = secondaryText,
  141. Margin = new Avalonia.Thickness(5),
  142. TextWrapping = Avalonia.Media.TextWrapping.Wrap,
  143. MaxWidth = 450
  144. };
  145. Grid.SetColumn(primaryLabel, 1);
  146. Grid.SetColumn(secondaryLabel, 1);
  147. Grid.SetRow(primaryLabel, 0);
  148. Grid.SetRow(secondaryLabel, 1);
  149. content.Children.Add(icon);
  150. content.Children.Add(primaryLabel);
  151. content.Children.Add(secondaryLabel);
  152. return content;
  153. }
  154. public static async Task<UserResult> CreateInfoDialog(
  155. string primary,
  156. string secondaryText,
  157. string acceptButton,
  158. string closeButton,
  159. string title)
  160. {
  161. return await ShowContentDialog(
  162. title,
  163. primary,
  164. secondaryText,
  165. acceptButton,
  166. "",
  167. closeButton,
  168. (int)Symbol.Important);
  169. }
  170. internal static async Task<UserResult> CreateConfirmationDialog(
  171. string primaryText,
  172. string secondaryText,
  173. string acceptButtonText,
  174. string cancelButtonText,
  175. string title,
  176. UserResult primaryButtonResult = UserResult.Yes)
  177. {
  178. return await ShowContentDialog(
  179. string.IsNullOrWhiteSpace(title) ? LocaleManager.Instance["DialogConfirmationTitle"] : title,
  180. primaryText,
  181. secondaryText,
  182. acceptButtonText,
  183. "",
  184. cancelButtonText,
  185. (int)Symbol.Help,
  186. primaryButtonResult);
  187. }
  188. internal static UpdateWaitWindow CreateWaitingDialog(string mainText, string secondaryText)
  189. {
  190. return new(mainText, secondaryText);
  191. }
  192. internal static async Task CreateUpdaterInfoDialog(string primary, string secondaryText)
  193. {
  194. await ShowContentDialog(
  195. LocaleManager.Instance["DialogUpdaterTitle"],
  196. primary,
  197. secondaryText,
  198. "",
  199. "",
  200. LocaleManager.Instance["InputDialogOk"],
  201. (int)Symbol.Important);
  202. }
  203. internal static async Task CreateWarningDialog(string primary, string secondaryText)
  204. {
  205. await ShowContentDialog(
  206. LocaleManager.Instance["DialogWarningTitle"],
  207. primary,
  208. secondaryText,
  209. "",
  210. "",
  211. LocaleManager.Instance["InputDialogOk"],
  212. (int)Symbol.Important);
  213. }
  214. internal static async Task CreateErrorDialog(string errorMessage, string secondaryErrorMessage = "")
  215. {
  216. Logger.Error?.Print(LogClass.Application, errorMessage);
  217. await ShowContentDialog(
  218. LocaleManager.Instance["DialogErrorTitle"],
  219. LocaleManager.Instance["DialogErrorMessage"],
  220. errorMessage,
  221. secondaryErrorMessage,
  222. "",
  223. LocaleManager.Instance["InputDialogOk"],
  224. (int)Symbol.Dismiss);
  225. }
  226. internal static async Task<bool> CreateChoiceDialog(string title, string primary, string secondaryText)
  227. {
  228. if (_isChoiceDialogOpen)
  229. {
  230. return false;
  231. }
  232. _isChoiceDialogOpen = true;
  233. UserResult response =
  234. await ShowContentDialog(
  235. title,
  236. primary,
  237. secondaryText,
  238. LocaleManager.Instance["InputDialogYes"],
  239. "",
  240. LocaleManager.Instance["InputDialogNo"],
  241. (int)Symbol.Help,
  242. UserResult.Yes);
  243. _isChoiceDialogOpen = false;
  244. return response == UserResult.Yes;
  245. }
  246. internal static async Task<bool> CreateExitDialog()
  247. {
  248. return await CreateChoiceDialog(
  249. LocaleManager.Instance["DialogExitTitle"],
  250. LocaleManager.Instance["DialogExitMessage"],
  251. LocaleManager.Instance["DialogExitSubMessage"]);
  252. }
  253. internal static async Task<bool> CreateStopEmulationDialog()
  254. {
  255. return await CreateChoiceDialog(
  256. LocaleManager.Instance["DialogStopEmulationTitle"],
  257. LocaleManager.Instance["DialogStopEmulationMessage"],
  258. LocaleManager.Instance["DialogExitSubMessage"]);
  259. }
  260. internal static async Task<string> CreateInputDialog(
  261. string title,
  262. string mainText,
  263. string subText,
  264. uint maxLength = int.MaxValue,
  265. string input = "")
  266. {
  267. var result = await InputDialog.ShowInputDialog(
  268. title,
  269. mainText,
  270. input,
  271. subText,
  272. maxLength);
  273. if (result.Result == UserResult.Ok)
  274. {
  275. return result.Input;
  276. }
  277. return string.Empty;
  278. }
  279. }
  280. }