Merge pull request #148 from irihitech/numpad

Numpad
This commit is contained in:
Dong Bin
2024-03-15 23:36:05 +08:00
committed by GitHub
13 changed files with 455 additions and 5 deletions

View File

@@ -211,6 +211,12 @@ public static class OverlayDialog
control.CanLightDismiss = options.CanLightDismiss;
control.CanDragMove = options.CanDragMove;
}
internal static T? Recall<T>(string? hostId) where T: Control
{
var host = OverlayDialogManager.GetHost(hostId);
if (host is null) return null;
var item = host.Recall<T>();
return item;
}
}

View File

@@ -0,0 +1,109 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
using Irihi.Avalonia.Shared.Helpers;
namespace Ursa.Controls;
public class NumPad: TemplatedControl
{
public static readonly StyledProperty<InputElement?> TargetProperty = AvaloniaProperty.Register<NumPad, InputElement?>(
nameof(Target));
public InputElement? Target
{
get => GetValue(TargetProperty);
set => SetValue(TargetProperty, value);
}
public static readonly StyledProperty<bool> NumModeProperty = AvaloniaProperty.Register<NumPad, bool>(
nameof(NumMode), defaultValue: true);
public bool NumMode
{
get => GetValue(NumModeProperty);
set => SetValue(NumModeProperty, value);
}
public static readonly AttachedProperty<bool> AttachProperty =
AvaloniaProperty.RegisterAttached<NumPad, InputElement, bool>("Attach");
public static void SetAttach(InputElement obj, bool value) => obj.SetValue(AttachProperty, value);
public static bool GetAttach(InputElement obj) => obj.GetValue(AttachProperty);
static NumPad()
{
AttachProperty.Changed.AddClassHandler<InputElement, bool>(OnAttachNumPad);
}
private static void OnAttachNumPad(InputElement input, AvaloniaPropertyChangedEventArgs<bool> args)
{
if (args.NewValue.Value)
{
GotFocusEvent.AddHandler(OnTargetGotFocus, input);
}
else
{
GotFocusEvent.RemoveHandler(OnTargetGotFocus, input);
}
}
private static void OnTargetGotFocus(object sender, GotFocusEventArgs e)
{
if (sender is not InputElement) return;
var existing = OverlayDialog.Recall<NumPad>(null);
if (existing is not null)
{
existing.Target = sender as InputElement;
return;
}
var numPad = new NumPad() { Target = sender as InputElement };
OverlayDialog.Show(numPad, new object(), options: new OverlayDialogOptions() { Buttons = DialogButton.None });
}
private static readonly Dictionary<Key, string> KeyInputMapping = new()
{
[Key.NumPad0] = "0",
[Key.NumPad1] = "1",
[Key.NumPad2] = "2",
[Key.NumPad3] = "3",
[Key.NumPad4] = "4",
[Key.NumPad5] = "5",
[Key.NumPad6] = "6",
[Key.NumPad7] = "7",
[Key.NumPad8] = "8",
[Key.NumPad9] = "9",
[Key.Add] = "+",
[Key.Subtract] = "-",
[Key.Multiply] = "*",
[Key.Divide] = "/",
[Key.Decimal] = ".",
};
public void ProcessClick(object o)
{
if (Target is null || o is not NumPadButton b) return;
var key = (b.NumMode ? b.NumKey : b.FunctionKey)?? Key.None;
if (KeyInputMapping.TryGetValue(key, out string s))
{
Target.RaiseEvent(new TextInputEventArgs()
{
Source = this,
RoutedEvent = TextInputEvent,
Text = s,
});
}
else
{
Target.RaiseEvent(new KeyEventArgs()
{
Source = this,
RoutedEvent = KeyDownEvent,
Key = key,
});
}
}
}

View File

@@ -0,0 +1,54 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
namespace Ursa.Controls;
public class NumPadButton: RepeatButton
{
public static readonly StyledProperty<Key?> NumKeyProperty = AvaloniaProperty.Register<NumPadButton, Key?>(
nameof(NumKey));
public Key? NumKey
{
get => GetValue(NumKeyProperty);
set => SetValue(NumKeyProperty, value);
}
public static readonly StyledProperty<Key?> FunctionKeyProperty = AvaloniaProperty.Register<NumPadButton, Key?>(
nameof(FunctionKey));
public Key? FunctionKey
{
get => GetValue(FunctionKeyProperty);
set => SetValue(FunctionKeyProperty, value);
}
public static readonly StyledProperty<bool> NumModeProperty = AvaloniaProperty.Register<NumPadButton, bool>(
nameof(NumMode));
public bool NumMode
{
get => GetValue(NumModeProperty);
set => SetValue(NumModeProperty, value);
}
public static readonly StyledProperty<object?> NumContentProperty = AvaloniaProperty.Register<NumPadButton, object?>(
nameof(NumContent));
public object? NumContent
{
get => GetValue(NumContentProperty);
set => SetValue(NumContentProperty, value);
}
public static readonly StyledProperty<object?> FunctionContentProperty = AvaloniaProperty.Register<NumPadButton, object?>(
nameof(FunctionContent));
public object? FunctionContent
{
get => GetValue(FunctionContentProperty);
set => SetValue(FunctionContentProperty, value);
}
}

View File

@@ -213,9 +213,13 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
_textBox?.Focus();
_textBox!.IsReadOnly = true;
}
}
protected override void OnTextInput(TextInputEventArgs e)
{
_textBox?.RaiseEvent(e);
}
private void OnDragPanelPointerReleased(object sender, PointerReleasedEventArgs e)
{
_point = null;

View File

@@ -189,4 +189,10 @@ public partial class OverlayDialogHost: Canvas
}
return result;
}
internal T? Recall<T>()
{
var element = _layers.LastOrDefault(a => a.Element.Content?.GetType() == typeof(T));
return element?.Element.Content is T t ? t : default;
}
}