feat: add navigation key handling.
This commit is contained in:
@@ -10,7 +10,9 @@
|
||||
mc:Ignorable="d">
|
||||
<StackPanel HorizontalAlignment="Left">
|
||||
<TextBlock />
|
||||
<u:IPv4Box />
|
||||
<u:IPv4Box Name="box" />
|
||||
<u:IPv4Box ShowPort="True" />
|
||||
<TextBlock Text="IP: " />
|
||||
<TextBlock Text="{Binding #box.IPAddress}" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
MinWidth="48"
|
||||
VerticalAlignment="Center"
|
||||
Cursor="IBeam"
|
||||
SelectionBrush="Blue"
|
||||
SelectionForegroundBrush="White"
|
||||
Text="123"
|
||||
TextAlignment="Center" />
|
||||
<TextBlock
|
||||
@@ -42,6 +44,8 @@
|
||||
MinWidth="48"
|
||||
VerticalAlignment="Center"
|
||||
Cursor="IBeam"
|
||||
SelectionBrush="Blue"
|
||||
SelectionForegroundBrush="White"
|
||||
Text="123" />
|
||||
<TextBlock
|
||||
Grid.Column="3"
|
||||
@@ -53,7 +57,9 @@
|
||||
Grid.Column="4"
|
||||
MinWidth="48"
|
||||
VerticalAlignment="Center"
|
||||
Cursor="IBeam" />
|
||||
Cursor="IBeam"
|
||||
SelectionBrush="Blue"
|
||||
SelectionForegroundBrush="White" />
|
||||
<TextBlock
|
||||
Grid.Column="5"
|
||||
Margin="0,4"
|
||||
@@ -64,7 +70,9 @@
|
||||
Grid.Column="6"
|
||||
MinWidth="48"
|
||||
VerticalAlignment="Center"
|
||||
Cursor="IBeam" />
|
||||
Cursor="IBeam"
|
||||
SelectionBrush="Blue"
|
||||
SelectionForegroundBrush="White" />
|
||||
<Rectangle
|
||||
Grid.Column="7"
|
||||
Width="1"
|
||||
@@ -78,7 +86,9 @@
|
||||
MinWidth="30"
|
||||
VerticalAlignment="Center"
|
||||
Cursor="IBeam"
|
||||
IsVisible="{TemplateBinding ShowPort}" />
|
||||
IsVisible="{TemplateBinding ShowPort}"
|
||||
SelectionBrush="Blue"
|
||||
SelectionForegroundBrush="White" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
|
||||
@@ -7,6 +7,7 @@ using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media.TextFormatting;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
@@ -29,10 +30,11 @@ public class IPv4Box: TemplatedControl
|
||||
private TextPresenter? _portText;
|
||||
private byte _firstByte;
|
||||
private byte _secondByte;
|
||||
private byte _thridByte;
|
||||
private byte _thirdByte;
|
||||
private byte _fourthByte;
|
||||
private int _port;
|
||||
private TextPresenter?[] _presenters = new TextPresenter?[5];
|
||||
private byte[] _bytes = new byte[4];
|
||||
private TextPresenter? _currentActivePresenter;
|
||||
|
||||
public static readonly StyledProperty<bool> ShowPortProperty = AvaloniaProperty.Register<IPv4Box, bool>(
|
||||
@@ -65,11 +67,6 @@ public class IPv4Box: TemplatedControl
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
ClearTextPresenterEvents(_firstText);
|
||||
ClearTextPresenterEvents(_secondText);
|
||||
ClearTextPresenterEvents(_thirdText);
|
||||
ClearTextPresenterEvents(_fourthText);
|
||||
ClearTextPresenterEvents(_portText);
|
||||
_firstText = e.NameScope.Find<TextPresenter>(PART_FirstTextPresenter);
|
||||
_secondText = e.NameScope.Find<TextPresenter>(PART_SecondTextPresenter);
|
||||
_thirdText = e.NameScope.Find<TextPresenter>(PART_ThirdTextPresenter);
|
||||
@@ -80,36 +77,138 @@ public class IPv4Box: TemplatedControl
|
||||
_presenters[2] = _secondText;
|
||||
_presenters[3] = _thirdText;
|
||||
_presenters[4] = _fourthText;
|
||||
RegisterTextPresenterEvents(_firstText);
|
||||
RegisterTextPresenterEvents(_secondText);
|
||||
RegisterTextPresenterEvents(_thirdText);
|
||||
RegisterTextPresenterEvents(_fourthText);
|
||||
RegisterTextPresenterEvents(_portText);
|
||||
}
|
||||
|
||||
private void ClearTextPresenterEvents(TextPresenter? presenter)
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Tab)
|
||||
{
|
||||
_currentActivePresenter?.HideCaret();
|
||||
ClearSelection(_currentActivePresenter);
|
||||
if (Equals(_currentActivePresenter, _fourthText))
|
||||
{
|
||||
base.OnKeyDown(e);
|
||||
return;
|
||||
}
|
||||
MoveToNextPresenter(_currentActivePresenter, true);
|
||||
_currentActivePresenter?.ShowCaret();
|
||||
SetIPAddress();
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.Back)
|
||||
{
|
||||
DeleteCurrentCharacter(_currentActivePresenter);
|
||||
}
|
||||
else if (e.Key == Key.Right )
|
||||
{
|
||||
if (_currentActivePresenter != null)
|
||||
{
|
||||
if (_currentActivePresenter.CaretIndex >= _currentActivePresenter.Text?.Length)
|
||||
{
|
||||
_currentActivePresenter.HideCaret();
|
||||
MoveToNextPresenter(_currentActivePresenter, false);
|
||||
_currentActivePresenter.SelectionStart = 0;
|
||||
_currentActivePresenter.SelectionEnd = 0;
|
||||
_currentActivePresenter?.ShowCaret();
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentActivePresenter.CaretIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e.Key == Key.Left)
|
||||
{
|
||||
if (_currentActivePresenter != null)
|
||||
{
|
||||
if (_currentActivePresenter.CaretIndex == 0)
|
||||
{
|
||||
_currentActivePresenter.HideCaret();
|
||||
bool success = MoveToPreviousTextPresenter(_currentActivePresenter);
|
||||
_currentActivePresenter.ShowCaret();
|
||||
if (success)
|
||||
{
|
||||
_currentActivePresenter.CaretIndex = _currentActivePresenter.Text?.Length ?? 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentActivePresenter.CaretIndex--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
base.OnKeyDown(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SelectAll(TextPresenter? presenter)
|
||||
{
|
||||
if(presenter is null) return;
|
||||
presenter.LostFocus -= OnTextPresenterLostFocus;
|
||||
presenter.SelectionStart = 0;
|
||||
presenter.SelectionEnd = presenter.Text?.Length+1??0;
|
||||
}
|
||||
|
||||
private void RegisterTextPresenterEvents(TextPresenter? presenter)
|
||||
protected override void OnTextInput(TextInputEventArgs e)
|
||||
{
|
||||
if (e.Handled) return;
|
||||
string? s = e.Text;
|
||||
if (string.IsNullOrEmpty(s)) return;
|
||||
if (_currentActivePresenter != null)
|
||||
{
|
||||
int index = _currentActivePresenter.CaretIndex;
|
||||
string? oldText = _currentActivePresenter.Text;
|
||||
if (oldText is null)
|
||||
{
|
||||
_currentActivePresenter.Text = s;
|
||||
_currentActivePresenter.MoveCaretHorizontal();
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteSelection(_currentActivePresenter);
|
||||
ClearSelection(_currentActivePresenter);
|
||||
oldText = _currentActivePresenter.Text;
|
||||
|
||||
string? newText = string.IsNullOrEmpty(oldText)
|
||||
? s
|
||||
: (oldText?.Substring(0, index) + s + oldText?.Substring(index));
|
||||
_currentActivePresenter.Text = newText;
|
||||
_currentActivePresenter.MoveCaretHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteSelection(TextPresenter? presenter)
|
||||
{
|
||||
if (presenter is null) return;
|
||||
presenter.LostFocus += OnTextPresenterLostFocus;
|
||||
int selectionStart = presenter.SelectionStart;
|
||||
int selectionEnd = presenter.SelectionEnd;
|
||||
if (selectionStart != selectionEnd)
|
||||
{
|
||||
var start = Math.Min(selectionStart, selectionEnd);
|
||||
var end = Math.Max(selectionStart, selectionEnd);
|
||||
var text = presenter.Text;
|
||||
|
||||
string newText = text is null ? string.Empty : text.Substring(0, start) + text.Substring(end);
|
||||
presenter.Text = newText;
|
||||
presenter.MoveCaretToTextPosition(start);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextPresenterLostFocus(object? sender, RoutedEventArgs args)
|
||||
private void ClearSelection(TextPresenter? presenter)
|
||||
{
|
||||
if (sender is TextPresenter p)
|
||||
{
|
||||
p.HideCaret();
|
||||
}
|
||||
if(presenter is null) return;
|
||||
presenter.SelectionStart = 0;
|
||||
presenter.SelectionEnd = 0;
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
var source = e.Source;
|
||||
PointerPoint? clickInfo = e.GetCurrentPoint(this);
|
||||
Point position = e.GetPosition(_firstText);
|
||||
foreach (var presenter in _presenters)
|
||||
{
|
||||
@@ -117,10 +216,14 @@ public class IPv4Box: TemplatedControl
|
||||
{
|
||||
presenter?.ShowCaret();
|
||||
_currentActivePresenter = presenter;
|
||||
var caretPosition = position.WithX(position.X - presenter.Bounds.X);
|
||||
SetIPAddress();
|
||||
presenter?.MoveCaretToPoint(caretPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
presenter?.HideCaret();
|
||||
ClearSelection(presenter);
|
||||
}
|
||||
}
|
||||
Debug.WriteLine(_currentActivePresenter?.Name);
|
||||
@@ -129,11 +232,81 @@ public class IPv4Box: TemplatedControl
|
||||
|
||||
protected override void OnLostFocus(RoutedEventArgs e)
|
||||
{
|
||||
_firstText?.HideCaret();
|
||||
_secondText?.HideCaret();
|
||||
_thirdText?.HideCaret();
|
||||
_fourthText?.HideCaret();
|
||||
_portText?.HideCaret();
|
||||
foreach (var pre in _presenters)
|
||||
{
|
||||
pre?.HideCaret();
|
||||
ClearSelection(pre);
|
||||
}
|
||||
_currentActivePresenter = null;
|
||||
SetIPAddress();
|
||||
}
|
||||
|
||||
protected override void OnGotFocus(GotFocusEventArgs e)
|
||||
{
|
||||
_currentActivePresenter = _firstText;
|
||||
_currentActivePresenter?.ShowCaret();
|
||||
base.OnGotFocus(e);
|
||||
}
|
||||
|
||||
private void MoveToNextPresenter(TextPresenter? presenter, bool selectAllAfterMove)
|
||||
{
|
||||
if (presenter is null) return;
|
||||
if (Equals(presenter, _firstText)) _currentActivePresenter = _secondText;
|
||||
else if (Equals(presenter, _secondText)) _currentActivePresenter = _thirdText;
|
||||
else if (Equals(presenter, _thirdText)) _currentActivePresenter = _fourthText;
|
||||
else if (Equals(presenter, _fourthText))
|
||||
{
|
||||
if (ShowPort)
|
||||
{
|
||||
_currentActivePresenter = _portText;
|
||||
}
|
||||
}
|
||||
if(selectAllAfterMove) SelectAll(_currentActivePresenter);
|
||||
}
|
||||
|
||||
private bool MoveToPreviousTextPresenter(TextPresenter? presenter)
|
||||
{
|
||||
if (presenter is null) return false;
|
||||
if (Equals(presenter, _firstText)) return false;
|
||||
if (Equals(presenter, _portText)) _currentActivePresenter = _fourthText;
|
||||
else if (Equals(presenter, _fourthText)) _currentActivePresenter = _thirdText;
|
||||
else if (Equals(presenter, _thirdText)) _currentActivePresenter = _secondText;
|
||||
else if (Equals(presenter, _secondText)) _currentActivePresenter = _firstText;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var presenter in _presenters)
|
||||
{
|
||||
if (presenter != null) presenter.Text = null;
|
||||
}
|
||||
IPAddress = null;
|
||||
}
|
||||
|
||||
private void SetIPAddress()
|
||||
{
|
||||
long address = 0;
|
||||
address += _firstByte;
|
||||
address += _secondByte << 8;
|
||||
address += _thirdByte << 16;
|
||||
address += _fourthByte << 24;
|
||||
IPAddress = new IPAddress(address);
|
||||
}
|
||||
|
||||
private void DeleteCurrentCharacter(TextPresenter? presenter)
|
||||
{
|
||||
if(presenter is null) return;
|
||||
var oldText = presenter.Text;
|
||||
if (string.IsNullOrWhiteSpace(oldText))
|
||||
{
|
||||
MoveToPreviousTextPresenter(presenter);
|
||||
return;
|
||||
}
|
||||
int index = presenter.CaretIndex;
|
||||
if (index == 0) return;
|
||||
string newText = oldText?.Substring(0, index - 1) + oldText?.Substring(index);
|
||||
presenter.MoveCaretHorizontal(LogicalDirection.Backward);
|
||||
presenter.Text = newText;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user