Merge pull request #503 from Soar360/pin-code-command

优化 PinCode 类
This commit is contained in:
Dong Bin
2024-12-05 21:31:08 +08:00
committed by GitHub
2 changed files with 26 additions and 8 deletions

View File

@@ -11,12 +11,12 @@ using Irihi.Avalonia.Shared.Helpers;
namespace Ursa.Controls; namespace Ursa.Controls;
[TemplatePart(PART_ItemsControl, typeof(ItemsControl))] [TemplatePart(PART_ItemsControl, typeof(ItemsControl))]
public class PinCode: TemplatedControl public class PinCode : TemplatedControl
{ {
public const string PART_ItemsControl = "PART_ItemsControl"; public const string PART_ItemsControl = "PART_ItemsControl";
private ItemsControl? _itemsControl; private ItemsControl? _itemsControl;
private int _currentIndex; private int _currentIndex;
public static readonly StyledProperty<ICommand?> CompleteCommandProperty = AvaloniaProperty.Register<PinCode, ICommand?>( public static readonly StyledProperty<ICommand?> CompleteCommandProperty = AvaloniaProperty.Register<PinCode, ICommand?>(
nameof(CompleteCommand)); nameof(CompleteCommand));
@@ -57,18 +57,18 @@ public class PinCode: TemplatedControl
public static readonly DirectProperty<PinCode, IList<string>> DigitsProperty = AvaloniaProperty.RegisterDirect<PinCode, IList<string>>( public static readonly DirectProperty<PinCode, IList<string>> DigitsProperty = AvaloniaProperty.RegisterDirect<PinCode, IList<string>>(
nameof(Digits), o => o.Digits); nameof(Digits), o => o.Digits);
private IList<string> _digits = []; private IList<string> _digits = [];
public IList<string> Digits public IList<string> Digits
{ {
get => _digits; get => _digits;
private set => SetAndRaise(DigitsProperty, ref _digits, value); private set => SetAndRaise(DigitsProperty, ref _digits, value);
} }
public static readonly RoutedEvent<PinCodeCompleteEventArgs> CompleteEvent = public static readonly RoutedEvent<PinCodeCompleteEventArgs> CompleteEvent =
RoutedEvent.Register<PinCode, PinCodeCompleteEventArgs>( RoutedEvent.Register<PinCode, PinCodeCompleteEventArgs>(
nameof(Complete), RoutingStrategies.Bubble); nameof(Complete), RoutingStrategies.Bubble);
public event EventHandler<PinCodeCompleteEventArgs> Complete public event EventHandler<PinCodeCompleteEventArgs> Complete
{ {
add => AddHandler(CompleteEvent, value); add => AddHandler(CompleteEvent, value);
@@ -79,7 +79,7 @@ public class PinCode: TemplatedControl
{ {
CountProperty.Changed.AddClassHandler<PinCode, int>((code, args) => code.OnCountOfDigitChanged(args)); CountProperty.Changed.AddClassHandler<PinCode, int>((code, args) => code.OnCountOfDigitChanged(args));
FocusableProperty.OverrideDefaultValue<PinCode>(true); FocusableProperty.OverrideDefaultValue<PinCode>(true);
KeyDownEvent.AddClassHandler<PinCode>((o,e)=>o.OnPreviewKeyDown(e), RoutingStrategies.Tunnel); KeyDownEvent.AddClassHandler<PinCode>((o, e) => o.OnPreviewKeyDown(e), RoutingStrategies.Tunnel);
} }
public PinCode() public PinCode()
@@ -119,7 +119,7 @@ public class PinCode: TemplatedControl
_currentIndex = MathHelpers.SafeClamp(_currentIndex, 0, Count - 1); _currentIndex = MathHelpers.SafeClamp(_currentIndex, 0, Count - 1);
_itemsControl?.ContainerFromIndex(_currentIndex)?.Focus(); _itemsControl?.ContainerFromIndex(_currentIndex)?.Focus();
} }
} }
e.Handled = true; e.Handled = true;
} }
@@ -181,6 +181,11 @@ public class PinCode: TemplatedControl
presenter.Text = newText[i].ToString(); presenter.Text = newText[i].ToString();
} }
} }
if (newText.Length == Count)
{
CompleteCommand?.Execute(Digits);
RaiseEvent(new PinCodeCompleteEventArgs(Digits, CompleteEvent));
}
} }
return; return;
} }
@@ -210,7 +215,7 @@ public class PinCode: TemplatedControl
_currentIndex = MathHelpers.SafeClamp(_currentIndex, 0, Count - 1); _currentIndex = MathHelpers.SafeClamp(_currentIndex, 0, Count - 1);
_itemsControl?.ContainerFromIndex(_currentIndex)?.Focus(); _itemsControl?.ContainerFromIndex(_currentIndex)?.Focus();
} }
else if(e.Key is Key.Right or Key.FnRightArrow) else if (e.Key is Key.Right or Key.FnRightArrow)
{ {
_currentIndex++; _currentIndex++;
_currentIndex = MathHelpers.SafeClamp(_currentIndex, 0, Count - 1); _currentIndex = MathHelpers.SafeClamp(_currentIndex, 0, Count - 1);

View File

@@ -3,6 +3,7 @@ using Avalonia.Headless;
using Avalonia.Headless.XUnit; using Avalonia.Headless.XUnit;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.Input;
using Ursa.Controls; using Ursa.Controls;
namespace HeadlessTest.Ursa.Controls.PinCodeTests; namespace HeadlessTest.Ursa.Controls.PinCodeTests;
@@ -13,9 +14,11 @@ public class PasteTest
public async void Paste_Should_Insert_Text() public async void Paste_Should_Insert_Text()
{ {
var window = new Window(); var window = new Window();
bool commandInvoked = false;
var pinCode = new PinCode() var pinCode = new PinCode()
{ {
Count = 4, Count = 4,
CompleteCommand = new RelayCommand(() => commandInvoked = true),
}; };
window.Content = pinCode; window.Content = pinCode;
window.Show(); window.Show();
@@ -27,15 +30,18 @@ public class PasteTest
// add await for clipboard processing. // add await for clipboard processing.
await Task.Delay(1); await Task.Delay(1);
Assert.Equal("abcd", string.Join("", pinCode.Digits)); Assert.Equal("abcd", string.Join("", pinCode.Digits));
Assert.True(commandInvoked);
} }
[AvaloniaFact] [AvaloniaFact]
public async void Paste_Should_Insert_Text_When_Text_Is_Shorter() public async void Paste_Should_Insert_Text_When_Text_Is_Shorter()
{ {
var window = new Window(); var window = new Window();
bool commandInvoked = false;
var pinCode = new PinCode() var pinCode = new PinCode()
{ {
Count = 4, Count = 4,
CompleteCommand = new RelayCommand(() => commandInvoked = true),
}; };
window.Content = pinCode; window.Content = pinCode;
window.Show(); window.Show();
@@ -46,15 +52,18 @@ public class PasteTest
window.KeyPressQwerty(PhysicalKey.V, RawInputModifiers.Control); window.KeyPressQwerty(PhysicalKey.V, RawInputModifiers.Control);
await Task.Delay(1); await Task.Delay(1);
Assert.Equal("abc", string.Join("", pinCode.Digits)); Assert.Equal("abc", string.Join("", pinCode.Digits));
Assert.False(commandInvoked);
} }
[AvaloniaFact] [AvaloniaFact]
public async void Paste_Should_Insert_Text_When_Text_Is_Longer() public async void Paste_Should_Insert_Text_When_Text_Is_Longer()
{ {
var window = new Window(); var window = new Window();
bool commandInvoked = false;
var pinCode = new PinCode() var pinCode = new PinCode()
{ {
Count = 4, Count = 4,
CompleteCommand = new RelayCommand(() => commandInvoked = true),
}; };
window.Content = pinCode; window.Content = pinCode;
window.Show(); window.Show();
@@ -65,16 +74,19 @@ public class PasteTest
window.KeyPressQwerty(PhysicalKey.V, RawInputModifiers.Control); window.KeyPressQwerty(PhysicalKey.V, RawInputModifiers.Control);
await Task.Delay(1); await Task.Delay(1);
Assert.Equal("abcd", string.Join("", pinCode.Digits)); Assert.Equal("abcd", string.Join("", pinCode.Digits));
Assert.True(commandInvoked);
} }
[AvaloniaFact] [AvaloniaFact]
public async void Paste_Should_Not_Insert_Text_When_Text_Is_In_Invalid_Mode() public async void Paste_Should_Not_Insert_Text_When_Text_Is_In_Invalid_Mode()
{ {
var window = new Window(); var window = new Window();
var commandInvoked = false;
var pinCode = new PinCode() var pinCode = new PinCode()
{ {
Count = 4, Count = 4,
Mode = PinCodeMode.Digit, Mode = PinCodeMode.Digit,
CompleteCommand = new RelayCommand(() => commandInvoked = true),
}; };
window.Content = pinCode; window.Content = pinCode;
window.Show(); window.Show();
@@ -85,5 +97,6 @@ public class PasteTest
window.KeyPressQwerty(PhysicalKey.V, RawInputModifiers.Control); window.KeyPressQwerty(PhysicalKey.V, RawInputModifiers.Control);
await Task.Delay(1); await Task.Delay(1);
Assert.Equal("", string.Join("", pinCode.Digits)); Assert.Equal("", string.Join("", pinCode.Digits));
Assert.False(commandInvoked);
} }
} }