forked from Mirror/Ryujinx
Check KeyboardMode in GUI (#4343)
* Update SoftwareKeyboard to send KeyboardMode to UI * Update GTK UI to check text against KeyboardMode * Update Ava UI to check text against KeyboardMode * Restructure input validation * true when text is not empty * Add English validation text for SoftwareKeyboardMode * Add Chinese validation text for SoftwareKeyboardMode * Update base on feedback --------- Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
This commit is contained in:
parent
21c9ac6240
commit
d511c845b7
9 changed files with 109 additions and 22 deletions
|
@ -544,6 +544,9 @@
|
||||||
"SwkbdMinCharacters": "Must be at least {0} characters long",
|
"SwkbdMinCharacters": "Must be at least {0} characters long",
|
||||||
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
|
"SwkbdMinRangeCharacters": "Must be {0}-{1} characters long",
|
||||||
"SoftwareKeyboard": "Software Keyboard",
|
"SoftwareKeyboard": "Software Keyboard",
|
||||||
|
"SoftwareKeyboardModeNumbersOnly": "Must be numbers only",
|
||||||
|
"SoftwareKeyboardModeAlphabet": "Must be alphabets only",
|
||||||
|
"SoftwareKeyboardModeASCII": "Must be ASCII text only",
|
||||||
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
||||||
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
|
||||||
"DialogControllerAppletDockModeSet": "Docked mode set. Handheld is also invalid.\n\n",
|
"DialogControllerAppletDockModeSet": "Docked mode set. Handheld is also invalid.\n\n",
|
||||||
|
|
|
@ -527,6 +527,9 @@
|
||||||
"SwkbdMinCharacters": "至少应为 {0} 个字长",
|
"SwkbdMinCharacters": "至少应为 {0} 个字长",
|
||||||
"SwkbdMinRangeCharacters": "必须为 {0}-{1} 个字长",
|
"SwkbdMinRangeCharacters": "必须为 {0}-{1} 个字长",
|
||||||
"SoftwareKeyboard": "软件键盘",
|
"SoftwareKeyboard": "软件键盘",
|
||||||
|
"SoftwareKeyboardModeNumbersOnly": "只接受数字",
|
||||||
|
"SoftwareKeyboardModeAlphabet": "只接受英文字母",
|
||||||
|
"SoftwareKeyboardModeASCII": "只接受 ASCII 符号",
|
||||||
"DialogControllerAppletMessagePlayerRange": "游戏需要 {0} 个玩家并满足以下要求:\n\n手柄类型:{1}\n\n玩家类型:{2}\n\n{3}请打开设置窗口,重新配置手柄输入;或者关闭返回。",
|
"DialogControllerAppletMessagePlayerRange": "游戏需要 {0} 个玩家并满足以下要求:\n\n手柄类型:{1}\n\n玩家类型:{2}\n\n{3}请打开设置窗口,重新配置手柄输入;或者关闭返回。",
|
||||||
"DialogControllerAppletMessage": "游戏需要刚好 {0} 个玩家并满足以下要求:\n\n手柄类型:{1}\n\n玩家类型:{2}\n\n{3}请打开设置窗口,重新配置手柄输入;或者关闭返回。",
|
"DialogControllerAppletMessage": "游戏需要刚好 {0} 个玩家并满足以下要求:\n\n手柄类型:{1}\n\n玩家类型:{2}\n\n{3}请打开设置窗口,重新配置手柄输入;或者关闭返回。",
|
||||||
"DialogControllerAppletDockModeSet": "目前处于主机模式,无法使用掌机操作方式",
|
"DialogControllerAppletDockModeSet": "目前处于主机模式,无法使用掌机操作方式",
|
||||||
|
|
|
@ -527,6 +527,9 @@
|
||||||
"SwkbdMinCharacters": "至少應為 {0} 個字長",
|
"SwkbdMinCharacters": "至少應為 {0} 個字長",
|
||||||
"SwkbdMinRangeCharacters": "必須為 {0}-{1} 個字長",
|
"SwkbdMinRangeCharacters": "必須為 {0}-{1} 個字長",
|
||||||
"SoftwareKeyboard": "軟體鍵盤",
|
"SoftwareKeyboard": "軟體鍵盤",
|
||||||
|
"SoftwareKeyboardModeNumbersOnly": "只接受數字",
|
||||||
|
"SoftwareKeyboardModeAlphabet": "只接受英文字母",
|
||||||
|
"SoftwareKeyboardModeASCII": "只接受 ASCII 符號",
|
||||||
"DialogControllerAppletMessagePlayerRange": "本遊戲需要 {0} 個玩家持有:\n\n類型:{1}\n\n玩家:{2}\n\n{3}請打開設定畫面,配置手把,或者關閉本視窗。",
|
"DialogControllerAppletMessagePlayerRange": "本遊戲需要 {0} 個玩家持有:\n\n類型:{1}\n\n玩家:{2}\n\n{3}請打開設定畫面,配置手把,或者關閉本視窗。",
|
||||||
"DialogControllerAppletMessage": "本遊戲需要剛好 {0} 個玩家持有:\n\n類型:{1}\n\n玩家:{2}\n\n{3}請打開設定畫面,配置手把,或者關閉本視窗。",
|
"DialogControllerAppletMessage": "本遊戲需要剛好 {0} 個玩家持有:\n\n類型:{1}\n\n玩家:{2}\n\n{3}請打開設定畫面,配置手把,或者關閉本視窗。",
|
||||||
"DialogControllerAppletDockModeSet": "現在處於主機模式,無法使用掌機操作方式\n\n",
|
"DialogControllerAppletDockModeSet": "現在處於主機模式,無法使用掌機操作方式\n\n",
|
||||||
|
|
|
@ -9,14 +9,17 @@ using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.Windows;
|
using Ryujinx.Ava.UI.Windows;
|
||||||
using Ryujinx.HLE.HOS.Applets;
|
using Ryujinx.HLE.HOS.Applets;
|
||||||
|
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Controls
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
internal partial class SwkbdAppletDialog : UserControl
|
internal partial class SwkbdAppletDialog : UserControl
|
||||||
{
|
{
|
||||||
private Predicate<int> _checkLength;
|
private Predicate<int> _checkLength = _ => true;
|
||||||
|
private Predicate<string> _checkInput = _ => true;
|
||||||
private int _inputMax;
|
private int _inputMax;
|
||||||
private int _inputMin;
|
private int _inputMin;
|
||||||
private string _placeholder;
|
private string _placeholder;
|
||||||
|
@ -35,8 +38,6 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
Input.Watermark = _placeholder;
|
Input.Watermark = _placeholder;
|
||||||
|
|
||||||
Input.AddHandler(TextInputEvent, Message_TextInput, RoutingStrategies.Tunnel, true);
|
Input.AddHandler(TextInputEvent, Message_TextInput, RoutingStrategies.Tunnel, true);
|
||||||
|
|
||||||
SetInputLengthValidation(0, int.MaxValue); // Disable by default.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SwkbdAppletDialog()
|
public SwkbdAppletDialog()
|
||||||
|
@ -67,6 +68,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
string input = string.Empty;
|
string input = string.Empty;
|
||||||
|
|
||||||
content.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
|
content.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
|
||||||
|
content.SetInputValidation(args.KeyboardMode);
|
||||||
|
|
||||||
content._host = contentDialog;
|
content._host = contentDialog;
|
||||||
contentDialog.Title = title;
|
contentDialog.Title = title;
|
||||||
|
@ -91,6 +93,12 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
return (result, input);
|
return (result, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ApplyValidationInfo(string text)
|
||||||
|
{
|
||||||
|
Error.IsVisible = !string.IsNullOrEmpty(text);
|
||||||
|
Error.Text = text;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetInputLengthValidation(int min, int max)
|
public void SetInputLengthValidation(int min, int max)
|
||||||
{
|
{
|
||||||
_inputMin = Math.Min(min, max);
|
_inputMin = Math.Min(min, max);
|
||||||
|
@ -99,6 +107,8 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
Error.IsVisible = false;
|
Error.IsVisible = false;
|
||||||
Error.FontStyle = FontStyle.Italic;
|
Error.FontStyle = FontStyle.Italic;
|
||||||
|
|
||||||
|
string validationInfoText = "";
|
||||||
|
|
||||||
if (_inputMin <= 0 && _inputMax == int.MaxValue) // Disable.
|
if (_inputMin <= 0 && _inputMax == int.MaxValue) // Disable.
|
||||||
{
|
{
|
||||||
Error.IsVisible = false;
|
Error.IsVisible = false;
|
||||||
|
@ -107,21 +117,48 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
}
|
}
|
||||||
else if (_inputMin > 0 && _inputMax == int.MaxValue)
|
else if (_inputMin > 0 && _inputMax == int.MaxValue)
|
||||||
{
|
{
|
||||||
Error.IsVisible = true;
|
validationInfoText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinCharacters, _inputMin);
|
||||||
|
|
||||||
Error.Text = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinCharacters, _inputMin);
|
|
||||||
|
|
||||||
_checkLength = length => _inputMin <= length;
|
_checkLength = length => _inputMin <= length;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Error.IsVisible = true;
|
validationInfoText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinRangeCharacters, _inputMin, _inputMax);
|
||||||
|
|
||||||
Error.Text = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SwkbdMinRangeCharacters, _inputMin, _inputMax);
|
|
||||||
|
|
||||||
_checkLength = length => _inputMin <= length && length <= _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.NumbersOnly:
|
||||||
|
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeNumbersOnly);
|
||||||
|
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
|
||||||
|
_checkInput = text => text.All(char.IsDigit);
|
||||||
|
break;
|
||||||
|
case KeyboardMode.Alphabet:
|
||||||
|
localeText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SoftwareKeyboardModeAlphabet);
|
||||||
|
validationInfoText = string.IsNullOrEmpty(validationInfoText) ? localeText : string.Join("\n", validationInfoText, localeText);
|
||||||
|
_checkInput = text => text.All(char.IsAsciiLetter);
|
||||||
|
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());
|
Message_TextInput(this, new TextInputEventArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +166,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
if (_host != null)
|
if (_host != null)
|
||||||
{
|
{
|
||||||
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length);
|
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length) && _checkInput(Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +178,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length);
|
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length) && _checkInput(Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Identifies the variant of keyboard displayed on screen.
|
/// Identifies the variant of keyboard displayed on screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
enum KeyboardMode : uint
|
public enum KeyboardMode : uint
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A full alpha-numeric keyboard.
|
/// A full alpha-numeric keyboard.
|
||||||
|
|
|
@ -209,6 +209,7 @@ namespace Ryujinx.HLE.HOS.Applets
|
||||||
// Call the configured GUI handler to get user's input.
|
// Call the configured GUI handler to get user's input.
|
||||||
var args = new SoftwareKeyboardUiArgs
|
var args = new SoftwareKeyboardUiArgs
|
||||||
{
|
{
|
||||||
|
KeyboardMode = _keyboardForegroundConfig.Mode,
|
||||||
HeaderText = StripUnicodeControlCodes(_keyboardForegroundConfig.HeaderText),
|
HeaderText = StripUnicodeControlCodes(_keyboardForegroundConfig.HeaderText),
|
||||||
SubtitleText = StripUnicodeControlCodes(_keyboardForegroundConfig.SubtitleText),
|
SubtitleText = StripUnicodeControlCodes(_keyboardForegroundConfig.SubtitleText),
|
||||||
GuideText = StripUnicodeControlCodes(_keyboardForegroundConfig.GuideText),
|
GuideText = StripUnicodeControlCodes(_keyboardForegroundConfig.GuideText),
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Applets
|
namespace Ryujinx.HLE.HOS.Applets
|
||||||
{
|
{
|
||||||
public struct SoftwareKeyboardUiArgs
|
public struct SoftwareKeyboardUiArgs
|
||||||
{
|
{
|
||||||
|
public KeyboardMode KeyboardMode;
|
||||||
public string HeaderText;
|
public string HeaderText;
|
||||||
public string SubtitleText;
|
public string SubtitleText;
|
||||||
public string InitialText;
|
public string InitialText;
|
||||||
|
|
|
@ -106,6 +106,7 @@ namespace Ryujinx.Ui.Applet
|
||||||
swkbdDialog.OkButton.Label = args.SubmitText;
|
swkbdDialog.OkButton.Label = args.SubmitText;
|
||||||
|
|
||||||
swkbdDialog.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
|
swkbdDialog.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
|
||||||
|
swkbdDialog.SetInputValidation(args.KeyboardMode);
|
||||||
|
|
||||||
if (swkbdDialog.Run() == (int)ResponseType.Ok)
|
if (swkbdDialog.Run() == (int)ResponseType.Ok)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using Gtk;
|
using Gtk;
|
||||||
|
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Ui.Applet
|
namespace Ryujinx.Ui.Applet
|
||||||
{
|
{
|
||||||
|
@ -7,8 +9,12 @@ namespace Ryujinx.Ui.Applet
|
||||||
{
|
{
|
||||||
private int _inputMin;
|
private int _inputMin;
|
||||||
private int _inputMax;
|
private int _inputMax;
|
||||||
|
private KeyboardMode _mode;
|
||||||
|
|
||||||
private Predicate<int> _checkLength;
|
private string _validationInfoText = "";
|
||||||
|
|
||||||
|
private Predicate<int> _checkLength = _ => true;
|
||||||
|
private Predicate<string> _checkInput = _ => true;
|
||||||
|
|
||||||
private readonly Label _validationInfo;
|
private readonly Label _validationInfo;
|
||||||
|
|
||||||
|
@ -38,8 +44,12 @@ namespace Ryujinx.Ui.Applet
|
||||||
|
|
||||||
((Box)MessageArea).PackEnd(_validationInfo, true, true, 0);
|
((Box)MessageArea).PackEnd(_validationInfo, true, true, 0);
|
||||||
((Box)MessageArea).PackEnd(InputEntry, true, true, 4);
|
((Box)MessageArea).PackEnd(InputEntry, true, true, 4);
|
||||||
|
}
|
||||||
|
|
||||||
SetInputLengthValidation(0, int.MaxValue); // Disable by default.
|
private void ApplyValidationInfo()
|
||||||
|
{
|
||||||
|
_validationInfo.Visible = !string.IsNullOrEmpty(_validationInfoText);
|
||||||
|
_validationInfo.Markup = _validationInfoText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetInputLengthValidation(int min, int max)
|
public void SetInputLengthValidation(int min, int max)
|
||||||
|
@ -53,23 +63,49 @@ namespace Ryujinx.Ui.Applet
|
||||||
{
|
{
|
||||||
_validationInfo.Visible = false;
|
_validationInfo.Visible = false;
|
||||||
|
|
||||||
_checkLength = (length) => true;
|
_checkLength = _ => true;
|
||||||
}
|
}
|
||||||
else if (_inputMin > 0 && _inputMax == int.MaxValue)
|
else if (_inputMin > 0 && _inputMax == int.MaxValue)
|
||||||
{
|
{
|
||||||
_validationInfo.Visible = true;
|
_validationInfoText = $"<i>Must be at least {_inputMin} characters long.</i> ";
|
||||||
_validationInfo.Markup = $"<i>Must be at least {_inputMin} characters long</i>";
|
|
||||||
|
|
||||||
_checkLength = (length) => _inputMin <= length;
|
_checkLength = length => _inputMin <= length;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_validationInfo.Visible = true;
|
_validationInfoText = $"<i>Must be {_inputMin}-{_inputMax} characters long.</i> ";
|
||||||
_validationInfo.Markup = $"<i>Must be {_inputMin}-{_inputMax} characters long</i>";
|
|
||||||
|
|
||||||
_checkLength = (length) => _inputMin <= length && length <= _inputMax;
|
_checkLength = length => _inputMin <= length && length <= _inputMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApplyValidationInfo();
|
||||||
|
OnInputChanged(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetInputValidation(KeyboardMode mode)
|
||||||
|
{
|
||||||
|
_mode = mode;
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case KeyboardMode.NumbersOnly:
|
||||||
|
_validationInfoText += "<i>Must be numbers only.</i>";
|
||||||
|
_checkInput = text => text.All(char.IsDigit);
|
||||||
|
break;
|
||||||
|
case KeyboardMode.Alphabet:
|
||||||
|
_validationInfoText += "<i>Must be alphabets only.</i>";
|
||||||
|
_checkInput = text => text.All(char.IsAsciiLetter);
|
||||||
|
break;
|
||||||
|
case KeyboardMode.ASCII:
|
||||||
|
_validationInfoText += "<i>Must be ASCII text only.</i>";
|
||||||
|
_checkInput = text => text.All(char.IsAscii);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_checkInput = _ => true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyValidationInfo();
|
||||||
OnInputChanged(this, EventArgs.Empty);
|
OnInputChanged(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +119,7 @@ namespace Ryujinx.Ui.Applet
|
||||||
|
|
||||||
private void OnInputChanged(object sender, EventArgs e)
|
private void OnInputChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
OkButton.Sensitive = _checkLength(InputEntry.Text.Length);
|
OkButton.Sensitive = _checkLength(InputEntry.Text.Length) && _checkInput(InputEntry.Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue