Browse Source

Remove TextBefore, TextAfter

Set surroundingText relative to current line
Raise SurroundingTextChanged on CursorRectangleChanged
pull/8963/head
Benedikt Stebner 3 years ago
parent
commit
91ca55964f
  1. 11
      src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs
  2. 116
      src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
  3. 19
      src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs

11
src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs

@ -49,16 +49,7 @@ namespace Avalonia.Input.TextInput
/// <param name="afterLength">The length after current selection.</param>
void DeleteSurroundingText(int beforeLength, int afterLength);
/// <summary>
/// Returns the text before the cursor. Must return a non-empty string if cursor is not at the beginning of the text entry
/// </summary>
string? TextBeforeCursor { get; }
/// <summary>
/// Returns the text before the cursor. Must return a non-empty string if cursor is not at the end of the text entry
/// </summary>
string? TextAfterCursor { get; }
public void SelectInSurroundingText(int start, int end);
void SelectInSurroundingText(int start, int end);
}
public struct TextInputMethodSurroundingText

116
src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

@ -1,9 +1,6 @@
using System;
using System.Diagnostics;
using Avalonia.Controls.Presenters;
using Avalonia.Input;
using Avalonia.Input.TextInput;
using Avalonia.Media;
using Avalonia.Threading;
using Avalonia.VisualTree;
@ -14,6 +11,12 @@ namespace Avalonia.Controls
private TextBox? _parent;
private TextPresenter? _presenter;
public IVisual TextViewVisual => _presenter!;
public bool SupportsPreedit => true;
public bool SupportsSurroundingText => true;
public Rect CursorRectangle
{
get
@ -36,10 +39,41 @@ namespace Avalonia.Controls
}
}
public event EventHandler? CursorRectangleChanged;
public IVisual TextViewVisual => _presenter!;
public TextInputMethodSurroundingText SurroundingText
{
get
{
if(_presenter is null)
{
return default;
}
var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_presenter.CaretIndex, false);
var textLine = _presenter.TextLayout.TextLines[lineIndex];
var lineStart = textLine.FirstTextSourceIndex;
var lineText = _presenter.Text?.Substring(lineStart, textLine.Length);
var anchorOffset = Math.Max(0, _presenter.SelectionStart - lineStart);
var cursorOffset = Math.Max(0, _presenter.SelectionEnd - lineStart);
return new TextInputMethodSurroundingText
{
Text = lineText ?? "",
AnchorOffset = anchorOffset,
CursorOffset = cursorOffset
};
}
}
public event EventHandler? TextViewVisualChanged;
public bool SupportsPreedit => true;
public event EventHandler? CursorRectangleChanged;
public event EventHandler? SurroundingTextChanged;
public void SetPreeditText(string? text)
{
@ -51,58 +85,27 @@ namespace Avalonia.Controls
_presenter.PreeditText = text;
}
public bool SupportsSurroundingText => true;
public event EventHandler? SurroundingTextChanged;
public TextInputMethodSurroundingText SurroundingText => new()
{
Text = _presenter?.Text ?? "",
CursorOffset = _presenter?.CaretIndex ?? 0,
AnchorOffset = _presenter?.SelectionStart ?? 0
};
public string? TextBeforeCursor => null;
public string? TextAfterCursor => null;
public void SelectInSurroundingText(int start, int end)
{
if(_parent == null)
return;
// TODO: Account for the offset
_parent.SelectionStart = start;
_parent.SelectionEnd = end;
}
private void OnCaretBoundsChanged(object? sender, EventArgs e) =>
Dispatcher.UIThread.Post(() => CursorRectangleChanged?.Invoke(this, EventArgs.Empty), DispatcherPriority.Input);
private void OnTextBoxPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == TextBox.TextProperty || e.Property == TextBox.SelectionStartProperty ||
e.Property == TextBox.SelectionEndProperty)
{
if (string.IsNullOrEmpty(_presenter?.PreeditText))
{
SurroundingTextChanged?.Invoke(this, EventArgs.Empty);
}
return;
}
}
//start and end are relative to surroundingText
var surroundingText = SurroundingText;
var selectionStart = surroundingText.AnchorOffset + start;
var selectionEnd = surroundingText.AnchorOffset + end;
_parent.SelectionStart = selectionStart;
_parent.SelectionEnd = selectionEnd;
}
public void SetPresenter(TextPresenter? presenter, TextBox? parent)
{
if (_parent != null)
{
_parent.PropertyChanged -= OnTextBoxPropertyChanged;
}
_parent = parent;
if (_parent != null)
{
_parent.PropertyChanged += OnTextBoxPropertyChanged;
}
if (_presenter != null)
{
_presenter.PreeditText = null;
@ -118,7 +121,8 @@ namespace Avalonia.Controls
}
TextViewVisualChanged?.Invoke(this, EventArgs.Empty);
CursorRectangleChanged?.Invoke(this, EventArgs.Empty);
OnCaretBoundsChanged(this, EventArgs.Empty);
}
public void DeleteSurroundingText(int beforeLength, int afterLength)
@ -133,5 +137,19 @@ namespace Avalonia.Controls
_parent.DeleteSelection(true);
}
}
private void OnCaretBoundsChanged(object? sender, EventArgs e)
{
Dispatcher.UIThread.Post(() =>
{
if (SupportsSurroundingText)
{
SurroundingTextChanged?.Invoke(sender, e);
}
CursorRectangleChanged?.Invoke(sender, e);
}, DispatcherPriority.Input);
}
}
}

19
src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs

@ -349,12 +349,12 @@ namespace Avalonia.Web.Blazor
IsComposing = true;
break;
case WebCompositionEventArgs.WebCompositionEventType.Update:
_client?.SetPreeditText(e.Data);
_client.SetPreeditText(e.Data);
break;
case WebCompositionEventArgs.WebCompositionEventType.End:
IsComposing = false;
_client?.SetPreeditText(null);
_topLevelImpl.RawTextEvent(e.Data);
_client.SetPreeditText(null);
_topLevelImpl.RawTextEvent(e.Data);
break;
}
}
@ -471,7 +471,7 @@ namespace Avalonia.Web.Blazor
private void SurroundingTextChanged(object? sender, EventArgs e)
{
if(_client != null && IsComposing)
if(_client != null)
{
var surroundingText = _client.SurroundingText;
@ -484,15 +484,8 @@ namespace Avalonia.Web.Blazor
_inputHelper?.Focus();
var bounds = new PixelRect((int)rect.X, (int) rect.Y, (int) rect.Width, (int) rect.Height);
if (_client != null)
{
var surroundingText = _client.SurroundingText;
_inputHelper?.SetSurroundingText(surroundingText.Text, surroundingText.AnchorOffset,
surroundingText.CursorOffset);
_inputHelper?.SetBounds(bounds, surroundingText.CursorOffset);
}
_inputHelper?.SetBounds(bounds, _client?.SurroundingText.CursorOffset ?? 0);
_inputHelper?.Focus();
}
public void SetOptions(TextInputOptions options)

Loading…
Cancel
Save