aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx/UI/Applet/SwkbdAppletDialog.axaml.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx/UI/Applet/SwkbdAppletDialog.axaml.cs')
-rw-r--r--src/Ryujinx/UI/Applet/SwkbdAppletDialog.axaml.cs183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/Ryujinx/UI/Applet/SwkbdAppletDialog.axaml.cs b/src/Ryujinx/UI/Applet/SwkbdAppletDialog.axaml.cs
new file mode 100644
index 00000000..af3837e4
--- /dev/null
+++ b/src/Ryujinx/UI/Applet/SwkbdAppletDialog.axaml.cs
@@ -0,0 +1,183 @@
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Interactivity;
+using Avalonia.Media;
+using FluentAvalonia.UI.Controls;
+using Ryujinx.Ava.Common.Locale;
+using Ryujinx.Ava.UI.Helpers;
+using Ryujinx.HLE.HOS.Applets;
+using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Ryujinx.Ava.UI.Controls
+{
+ internal partial class SwkbdAppletDialog : UserControl
+ {
+ private Predicate<int> _checkLength = _ => true;
+ private Predicate<string> _checkInput = _ => true;
+ private int _inputMax;
+ private int _inputMin;
+ private readonly string _placeholder;
+
+ private ContentDialog _host;
+
+ public SwkbdAppletDialog(string mainText, string secondaryText, string placeholder, string message)
+ {
+ MainText = mainText;
+ SecondaryText = secondaryText;
+ Message = message ?? "";
+ DataContext = this;
+ _placeholder = placeholder;
+ InitializeComponent();
+
+ Input.Watermark = _placeholder;
+
+ Input.AddHandler(TextInputEvent, Message_TextInput, RoutingStrategies.Tunnel, true);
+ }
+
+ public SwkbdAppletDialog()
+ {
+ DataContext = this;
+ InitializeComponent();
+ }
+
+ protected override void OnGotFocus(GotFocusEventArgs e)
+ {
+ // FIXME: This does not work. Might be a bug in Avalonia with DialogHost
+ // Currently focus will be redirected to the overlay window instead.
+ Input.Focus();
+ }
+
+ public string Message { get; set; } = "";
+ public string MainText { get; set; } = "";
+ public string SecondaryText { get; set; } = "";
+
+ public static async Task<(UserResult Result, string Input)> ShowInputDialog(string title, SoftwareKeyboardUIArgs args)
+ {
+ ContentDialog contentDialog = new();
+
+ UserResult result = UserResult.Cancel;
+
+ SwkbdAppletDialog content = new(args.HeaderText, args.SubtitleText, args.GuideText, args.InitialText);
+
+ string input = string.Empty;
+
+ content.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
+ content.SetInputValidation(args.KeyboardMode);
+
+ content._host = contentDialog;
+ contentDialog.Title = title;
+ contentDialog.PrimaryButtonText = args.SubmitText;
+ contentDialog.IsPrimaryButtonEnabled = content._checkLength(content.Message.Length);
+ contentDialog.SecondaryButtonText = "";
+ contentDialog.CloseButtonText = LocaleManager.Instance[LocaleKeys.InputDialogCancel];
+ contentDialog.Content = content;
+
+ void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs)
+ {
+ if (eventArgs.Result == ContentDialogResult.Primary)
+ {
+ result = UserResult.Ok;
+ input = content.Input.Text;
+ }
+ }
+
+ contentDialog.Closed += Handler;
+
+ await ContentDialogHelper.ShowAsync(contentDialog);
+
+ return (result, input);
+ }
+
+ private void ApplyValidationInfo(string text)
+ {
+ Error.IsVisible = !string.IsNullOrEmpty(text);
+ Error.Text = text;
+ }
+
+ public void SetInputLengthValidation(int min, int max)
+ {
+ _inputMin = Math.Min(min, max);
+ _inputMax = Math.Max(min, max);
+
+ Error.IsVisible = false;
+ Error.FontStyle = FontStyle.Italic;
+
+ string validationInfoText = "";
+
+ if (_inputMin <= 0 && _inputMax == int.MaxValue) // Disable.
+ {
+ Error.IsVisible = false;
+
+ _checkLength = length => true;
+ }
+ else if (_inputMin > 0 && _inputMax == int.MaxValue)
+ {
+ validationInfoText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinCharacters, _inputMin);
+
+ _checkLength = length => _inputMin <= length;
+ }
+ else
+ {
+ validationInfoText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinRangeCharacters, _inputMin, _inputMax);
+
+ _checkLength = length => _inputMin <= length && length <= _inputMax;
+ }
+
+ ApplyValidationInfo(validationInfoText);
+ Message_TextInput(this, new TextInputEventArgs());
+ }
+
+ private void SetInputValidation(KeyboardMode mode)
+ {
+ string validationInfoText = Error.Text;
+ string localeText;
+ switch (mode)
+ {
+ case KeyboardMode.Numeric:
+ localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeNumeric);
+ validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
+ _checkInput = text => text.All(NumericCharacterValidation.IsNumeric);
+ break;
+ case KeyboardMode.Alphabet:
+ localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeAlphabet);
+ validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
+ _checkInput = text => text.All(value => !CJKCharacterValidation.IsCJK(value));
+ break;
+ case KeyboardMode.ASCII:
+ localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeASCII);
+ validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
+ _checkInput = text => text.All(char.IsAscii);
+ break;
+ default:
+ _checkInput = _ => true;
+ break;
+ }
+
+ ApplyValidationInfo(validationInfoText);
+ Message_TextInput(this, new TextInputEventArgs());
+ }
+
+ private void Message_TextInput(object sender, TextInputEventArgs e)
+ {
+ if (_host != null)
+ {
+ _host.IsPrimaryButtonEnabled = _checkLength(Message.Length) && _checkInput(Message);
+ }
+ }
+
+ private void Message_KeyUp(object sender, KeyEventArgs e)
+ {
+ if (e.Key == Key.Enter && _host.IsPrimaryButtonEnabled)
+ {
+ _host.Hide(ContentDialogResult.Primary);
+ }
+ else
+ {
+ _host.IsPrimaryButtonEnabled = _checkLength(Message.Length) && _checkInput(Message);
+ }
+ }
+ }
+}