Merge pull request #752 from yangjieshao/main
修复了NumPad对NumericUpDown和IPv4Box的支持
This commit is contained in:
@@ -1,10 +1,14 @@
|
|||||||
using System;
|
using Avalonia;
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Dialogs;
|
using Avalonia.Dialogs;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ursa.Demo.Desktop;
|
namespace Ursa.Demo.Desktop;
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
[SupportedOSPlatform("linux")]
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||||
|
|||||||
@@ -21,11 +21,21 @@
|
|||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
u:NumPad.Attach="True"
|
u:NumPad.Attach="True"
|
||||||
Watermark="Invoke NumPad" />
|
Watermark="Invoke NumPad" />
|
||||||
<u:IPv4Box Width="200" u:NumPad.Attach="True" />
|
<u:IPv4Box
|
||||||
|
Width="200"
|
||||||
|
u:NumPad.Attach="True"
|
||||||
|
InputMode="Fast"
|
||||||
|
ShowLeadingZero="False" />
|
||||||
<u:NumericIntUpDown
|
<u:NumericIntUpDown
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
u:NumPad.Attach="True"
|
u:NumPad.Attach="True"
|
||||||
Watermark="Invoke NumPad" />
|
Watermark="Invoke u:NumericIntUpDown" />
|
||||||
|
|
||||||
|
<NumericUpDown
|
||||||
|
u:NumPad.Attach="True"
|
||||||
|
ButtonSpinnerLocation="Left"
|
||||||
|
Watermark="NumericUpDown" />
|
||||||
|
|
||||||
<Border Theme="{DynamicResource CardBorder}">
|
<Border Theme="{DynamicResource CardBorder}">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBox Name="text" Width="200" />
|
<TextBox Name="text" Width="200" />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<ResourceDictionary
|
<ResourceDictionary
|
||||||
xmlns="https://github.com/avaloniaui"
|
xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:u="https://irihi.tech/ursa">
|
xmlns:u="https://irihi.tech/ursa">
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
</u:NumPadButton>
|
</u:NumPadButton>
|
||||||
<u:NumPadButton
|
<u:NumPadButton
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.RowSpan="2"
|
Grid.RowSpan="1"
|
||||||
Grid.Column="3"
|
Grid.Column="3"
|
||||||
Height="{x:Static x:Double.NaN}"
|
Height="{x:Static x:Double.NaN}"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
@@ -100,6 +100,16 @@
|
|||||||
FunctionKey="Add"
|
FunctionKey="Add"
|
||||||
NumContent="+"
|
NumContent="+"
|
||||||
NumKey="Add" />
|
NumKey="Add" />
|
||||||
|
<u:NumPadButton
|
||||||
|
Grid.Row="2"
|
||||||
|
Grid.RowSpan="1"
|
||||||
|
Grid.Column="3"
|
||||||
|
Height="{x:Static x:Double.NaN}"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
FunctionContent="←"
|
||||||
|
FunctionKey="Back"
|
||||||
|
NumContent="←"
|
||||||
|
NumKey="Back" />
|
||||||
<u:NumPadButton
|
<u:NumPadButton
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Metadata;
|
using Avalonia.Controls.Metadata;
|
||||||
@@ -108,6 +108,24 @@ public class IPv4Box: TemplatedControl
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否使用小键盘输入
|
||||||
|
/// </summary>
|
||||||
|
internal bool IsTargetByNumPad
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(_isTargetByNumPad
|
||||||
|
&&!value)
|
||||||
|
{
|
||||||
|
SetLostFocus();
|
||||||
|
}
|
||||||
|
_isTargetByNumPad =value;
|
||||||
|
}
|
||||||
|
get => _isTargetByNumPad;
|
||||||
|
}
|
||||||
|
private bool _isTargetByNumPad;
|
||||||
|
|
||||||
#region Overrides
|
#region Overrides
|
||||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
{
|
{
|
||||||
@@ -308,6 +326,15 @@ public class IPv4Box: TemplatedControl
|
|||||||
protected override void OnLostFocus(RoutedEventArgs e)
|
protected override void OnLostFocus(RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnLostFocus(e);
|
base.OnLostFocus(e);
|
||||||
|
if (IsTargetByNumPad)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SetLostFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetLostFocus()
|
||||||
|
{
|
||||||
foreach (var pre in _presenters)
|
foreach (var pre in _presenters)
|
||||||
{
|
{
|
||||||
pre?.HideCaret();
|
pre?.HideCaret();
|
||||||
@@ -318,6 +345,7 @@ public class IPv4Box: TemplatedControl
|
|||||||
SetIPAddressInternal();
|
SetIPAddressInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void OnGotFocus(GotFocusEventArgs e)
|
protected override void OnGotFocus(GotFocusEventArgs e)
|
||||||
{
|
{
|
||||||
_currentActivePresenter = _firstText;
|
_currentActivePresenter = _firstText;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
|
using Avalonia.LogicalTree;
|
||||||
using Irihi.Avalonia.Shared.Helpers;
|
using Irihi.Avalonia.Shared.Helpers;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
@@ -16,6 +19,11 @@ public class NumPad: TemplatedControl
|
|||||||
set => SetValue(TargetProperty, value);
|
set => SetValue(TargetProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Target 目标内部的 TextBox 控件
|
||||||
|
/// </summary>
|
||||||
|
private TextBox? _targetInnerText;
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> NumModeProperty = AvaloniaProperty.Register<NumPad, bool>(
|
public static readonly StyledProperty<bool> NumModeProperty = AvaloniaProperty.Register<NumPad, bool>(
|
||||||
nameof(NumMode), defaultValue: true);
|
nameof(NumMode), defaultValue: true);
|
||||||
|
|
||||||
@@ -54,10 +62,24 @@ public class NumPad: TemplatedControl
|
|||||||
var existing = OverlayDialog.Recall<NumPad>(null);
|
var existing = OverlayDialog.Recall<NumPad>(null);
|
||||||
if (existing is not null)
|
if (existing is not null)
|
||||||
{
|
{
|
||||||
|
if(existing.Target is IPv4Box pv4Box)
|
||||||
|
{
|
||||||
|
pv4Box.IsTargetByNumPad = false; // 取消 IPv4Box 的 NumPad 输入模式
|
||||||
|
}
|
||||||
existing.Target = sender as InputElement;
|
existing.Target = sender as InputElement;
|
||||||
|
existing._targetInnerText = FindTextBoxInTarget((sender as InputElement)!);
|
||||||
|
|
||||||
|
if (existing.Target is IPv4Box pv4Box2)
|
||||||
|
{
|
||||||
|
pv4Box2.IsTargetByNumPad = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var numPad = new NumPad() { Target = sender as InputElement };
|
var numPad = new NumPad()
|
||||||
|
{
|
||||||
|
Target = sender as InputElement ,
|
||||||
|
_targetInnerText = FindTextBoxInTarget((sender as InputElement)!)
|
||||||
|
};
|
||||||
OverlayDialog.Show(numPad, new object(), options: new OverlayDialogOptions() { Buttons = DialogButton.None });
|
OverlayDialog.Show(numPad, new object(), options: new OverlayDialogOptions() { Buttons = DialogButton.None });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,9 +106,12 @@ public class NumPad: TemplatedControl
|
|||||||
{
|
{
|
||||||
if (Target is null || o is not NumPadButton b) return;
|
if (Target is null || o is not NumPadButton b) return;
|
||||||
var key = (b.NumMode ? b.NumKey : b.FunctionKey)?? Key.None;
|
var key = (b.NumMode ? b.NumKey : b.FunctionKey)?? Key.None;
|
||||||
|
|
||||||
|
// 如果存在内部为 TextBox 的目标控件,则使用该 TextBox 作为输入目标
|
||||||
|
var realTarget = _targetInnerText ?? Target;
|
||||||
if (KeyInputMapping.TryGetValue(key, out var s))
|
if (KeyInputMapping.TryGetValue(key, out var s))
|
||||||
{
|
{
|
||||||
Target.RaiseEvent(new TextInputEventArgs()
|
realTarget.RaiseEvent(new TextInputEventArgs()
|
||||||
{
|
{
|
||||||
Source = this,
|
Source = this,
|
||||||
RoutedEvent = TextInputEvent,
|
RoutedEvent = TextInputEvent,
|
||||||
@@ -95,7 +120,7 @@ public class NumPad: TemplatedControl
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Target.RaiseEvent(new KeyEventArgs()
|
realTarget.RaiseEvent(new KeyEventArgs()
|
||||||
{
|
{
|
||||||
Source = this,
|
Source = this,
|
||||||
RoutedEvent = KeyDownEvent,
|
RoutedEvent = KeyDownEvent,
|
||||||
@@ -103,4 +128,33 @@ public class NumPad: TemplatedControl
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 在目标控件中查找 TextBox 控件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">目标控件</param>
|
||||||
|
/// <returns>找到的 TextBox,如果没有找到则返回 null</returns>
|
||||||
|
private static TextBox? FindTextBoxInTarget(InputElement target)
|
||||||
|
{
|
||||||
|
// 如果目标本身就是 TextBox
|
||||||
|
if (target is TextBox textBox)
|
||||||
|
return textBox;
|
||||||
|
|
||||||
|
// 如果目标是 TemplatedControl,并且已经应用了模板
|
||||||
|
if (target is TemplatedControl templatedControl && templatedControl.IsInitialized)
|
||||||
|
{
|
||||||
|
// 尝试通过模板查找 PART_TextBox
|
||||||
|
if (templatedControl.GetTemplateChildren().FirstOrDefault(c => c is TextBox) is TextBox partTextBox)
|
||||||
|
return partTextBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果目标是 ILogical,使用 LogicalTree 扩展方法查找
|
||||||
|
if (target is ILogical logical)
|
||||||
|
{
|
||||||
|
// 使用 GetLogicalDescendants 方法查找所有逻辑子控件
|
||||||
|
var textBoxes = logical.GetLogicalDescendants().OfType<TextBox>();
|
||||||
|
return textBoxes.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -32,6 +32,10 @@ public class NumericIntUpDown : NumericUpDownBase<int>
|
|||||||
var result = a - b;
|
var result = a - b;
|
||||||
return result > Value ? Minimum : result;
|
return result > Value ? Minimum : result;
|
||||||
}
|
}
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericUIntUpDown : NumericUpDownBase<uint>
|
public class NumericUIntUpDown : NumericUpDownBase<uint>
|
||||||
@@ -68,6 +72,10 @@ public class NumericUIntUpDown : NumericUpDownBase<uint>
|
|||||||
var result = a - b;
|
var result = a - b;
|
||||||
return result > Value ? Minimum : result;
|
return result > Value ? Minimum : result;
|
||||||
}
|
}
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericDoubleUpDown : NumericUpDownBase<double>
|
public class NumericDoubleUpDown : NumericUpDownBase<double>
|
||||||
@@ -91,6 +99,10 @@ public class NumericDoubleUpDown : NumericUpDownBase<double>
|
|||||||
protected override double? Add(double? a, double? b) => a + b;
|
protected override double? Add(double? a, double? b) => a + b;
|
||||||
|
|
||||||
protected override double? Minus(double? a, double? b) => a - b;
|
protected override double? Minus(double? a, double? b) => a - b;
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericByteUpDown : NumericUpDownBase<byte>
|
public class NumericByteUpDown : NumericUpDownBase<byte>
|
||||||
@@ -122,6 +134,10 @@ public class NumericByteUpDown : NumericUpDownBase<byte>
|
|||||||
var result = a - b;
|
var result = a - b;
|
||||||
return (byte?)(result > Value ? Minimum : result);
|
return (byte?)(result > Value ? Minimum : result);
|
||||||
}
|
}
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericSByteUpDown : NumericUpDownBase<sbyte>
|
public class NumericSByteUpDown : NumericUpDownBase<sbyte>
|
||||||
@@ -153,6 +169,10 @@ public class NumericSByteUpDown : NumericUpDownBase<sbyte>
|
|||||||
var result = a - b;
|
var result = a - b;
|
||||||
return (sbyte?)(result > Value ? Minimum : result);
|
return (sbyte?)(result > Value ? Minimum : result);
|
||||||
}
|
}
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericShortUpDown : NumericUpDownBase<short>
|
public class NumericShortUpDown : NumericUpDownBase<short>
|
||||||
@@ -184,6 +204,10 @@ public class NumericShortUpDown : NumericUpDownBase<short>
|
|||||||
var result = a - b;
|
var result = a - b;
|
||||||
return (short?)(result > Value ? Minimum : result);
|
return (short?)(result > Value ? Minimum : result);
|
||||||
}
|
}
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericUShortUpDown : NumericUpDownBase<ushort>
|
public class NumericUShortUpDown : NumericUpDownBase<ushort>
|
||||||
@@ -215,6 +239,10 @@ public class NumericUShortUpDown : NumericUpDownBase<ushort>
|
|||||||
var result = a - b;
|
var result = a - b;
|
||||||
return (ushort?)(result > Value ? Minimum : result);
|
return (ushort?)(result > Value ? Minimum : result);
|
||||||
}
|
}
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericLongUpDown : NumericUpDownBase<long>
|
public class NumericLongUpDown : NumericUpDownBase<long>
|
||||||
@@ -246,6 +274,10 @@ public class NumericLongUpDown : NumericUpDownBase<long>
|
|||||||
var result = a - b;
|
var result = a - b;
|
||||||
return result > Value ? Minimum : result;
|
return result > Value ? Minimum : result;
|
||||||
}
|
}
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericULongUpDown : NumericUpDownBase<ulong>
|
public class NumericULongUpDown : NumericUpDownBase<ulong>
|
||||||
@@ -269,6 +301,10 @@ public class NumericULongUpDown : NumericUpDownBase<ulong>
|
|||||||
protected override ulong? Add(ulong? a, ulong? b) => a + b;
|
protected override ulong? Add(ulong? a, ulong? b) => a + b;
|
||||||
|
|
||||||
protected override ulong? Minus(ulong? a, ulong? b) => a - b;
|
protected override ulong? Minus(ulong? a, ulong? b) => a - b;
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericFloatUpDown : NumericUpDownBase<float>
|
public class NumericFloatUpDown : NumericUpDownBase<float>
|
||||||
@@ -292,6 +328,10 @@ public class NumericFloatUpDown : NumericUpDownBase<float>
|
|||||||
protected override float? Add(float? a, float? b) => a + b;
|
protected override float? Add(float? a, float? b) => a + b;
|
||||||
|
|
||||||
protected override float? Minus(float? a, float? b) => a - b;
|
protected override float? Minus(float? a, float? b) => a - b;
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NumericDecimalUpDown : NumericUpDownBase<decimal>
|
public class NumericDecimalUpDown : NumericUpDownBase<decimal>
|
||||||
@@ -315,4 +355,9 @@ public class NumericDecimalUpDown : NumericUpDownBase<decimal>
|
|||||||
protected override decimal? Add(decimal? a, decimal? b) => a + b;
|
protected override decimal? Add(decimal? a, decimal? b) => a + b;
|
||||||
|
|
||||||
protected override decimal? Minus(decimal? a, decimal? b) => a - b;
|
protected override decimal? Minus(decimal? a, decimal? b) => a - b;
|
||||||
|
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
base.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user