Browse Source

Fix GetTextLineText

pull/8963/head
Benedikt Stebner 4 years ago
parent
commit
169480e74d
  1. 5
      src/Android/Avalonia.Android/AndroidInputMethod.cs
  2. 16
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  3. 7
      src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs
  4. 34
      src/Avalonia.Controls/Presenters/TextPresenter.cs
  5. 5
      src/Avalonia.Controls/TextBox.cs
  6. 40
      src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
  7. 4
      src/Windows/Avalonia.Win32/Input/Imm32InputMethod.cs

5
src/Android/Avalonia.Android/AndroidInputMethod.cs

@ -100,12 +100,13 @@ namespace Avalonia.Android
{
var surroundingText = Client.SurroundingText;
_imm.UpdateSelection(_host, surroundingText.AnchorOffset, surroundingText.CursorOffset, _inputConnection.ComposingRegion.Start, _inputConnection.ComposingRegion.End);
_imm.UpdateSelection(_host, surroundingText.AnchorOffset, surroundingText.CursorOffset, surroundingText.AnchorOffset, surroundingText.CursorOffset);
}
}
public void SetCursorRect(Rect rect)
{
}
public void SetOptions(TextInputOptions options)
@ -114,7 +115,7 @@ namespace Avalonia.Android
_host.InitEditorInfo((_host, outAttrs) =>
{
_inputConnection?.FinishComposingText();
//_inputConnection?.FinishComposingText();
outAttrs.InputType = options.ContentType switch
{

16
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -276,7 +276,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public View View { get; }
public ComposingRegion ComposingRegion { get; private set; }
public ComposingRegion ComposingRegion { get; internal set; }
public string CompositionText { get; private set; }
@ -365,14 +365,18 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{
_inputMethod.Client.SetPreeditText(null);
var textLength = text.Length();
if (string.IsNullOrEmpty(CompositionText) && ComposingRegion.End > 0)
if (string.IsNullOrEmpty(CompositionText))
{
_inputMethod.Client.SelectInSurroundingText(ComposingRegion.Start, ComposingRegion.Start + textLength);
var surroundingText = _inputMethod.Client.SurroundingText;
var composingRegionLength = ComposingRegion.End - ComposingRegion.Start;
var composingRegionText = surroundingText.Text?.Substring(ComposingRegion.Start, composingRegionLength);
_inputMethod.Client.SelectInSurroundingText(ComposingRegion.Start, ComposingRegion.End);
}
ComposingRegion = new ComposingRegion(ComposingRegion.Start, ComposingRegion.Start + textLength);
ComposingRegion = new ComposingRegion(ComposingRegion.End, ComposingRegion.End);
}
return base.CommitText(text, newCursorPosition);

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

@ -42,13 +42,6 @@ namespace Avalonia.Input.TextInput
/// </summary>
event EventHandler? SurroundingTextChanged;
/// <summary>
/// Deletes specified length before and after current selection.
/// </summary>
/// <param name="beforeLength">The length before current selection.</param>
/// <param name="afterLength">The length after current selection.</param>
void DeleteSurroundingText(int beforeLength, int afterLength);
void SelectInSurroundingText(int start, int end);
}

34
src/Avalonia.Controls/Presenters/TextPresenter.cs

@ -847,12 +847,21 @@ namespace Avalonia.Controls.Presenters
_caretTimer.Tick -= CaretTimerTick;
}
protected void OnPreeditTextChanged(string? preeditText)
protected void OnPreeditTextChanged(string? oldValue, string? newValue)
{
InvalidateTextLayout();
if (preeditText is null)
if (string.IsNullOrEmpty(newValue))
{
if (!string.IsNullOrEmpty(oldValue))
{
var textPosition = _compositionStartHit.FirstCharacterIndex + _compositionStartHit.TrailingLength + newValue?.Length ?? 0;
var characterHit = GetCharacterHitFromTextPosition(textPosition);
UpdateCaret(characterHit, true);
}
_compositionStartHit = new CharacterHit(-1);
}
else
@ -865,18 +874,25 @@ namespace Avalonia.Controls.Presenters
if (_compositionStartHit.FirstCharacterIndex != -1)
{
var textPosition = _compositionStartHit.FirstCharacterIndex + _compositionStartHit.TrailingLength + preeditText?.Length ?? 0;
var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(textPosition, true);
var textLine = TextLayout.TextLines[lineIndex];
var textPosition = _compositionStartHit.FirstCharacterIndex + _compositionStartHit.TrailingLength + newValue?.Length ?? 0;
var characterHit = textLine.GetNextCaretCharacterHit(new CharacterHit(textPosition - 1));
var characterHit = GetCharacterHitFromTextPosition(textPosition);
UpdateCaret(characterHit, false);
}
}
private CharacterHit GetCharacterHitFromTextPosition(int textPosition)
{
var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(textPosition, true);
var textLine = TextLayout.TextLines[lineIndex];
var characterHit = textLine.GetNextCaretCharacterHit(new CharacterHit(textPosition - 1));
return characterHit;
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
@ -885,7 +901,7 @@ namespace Avalonia.Controls.Presenters
{
case nameof(PreeditText):
{
OnPreeditTextChanged(change.NewValue as string);
OnPreeditTextChanged(change.OldValue as string, change.NewValue as string);
break;
}

5
src/Avalonia.Controls/TextBox.cs

@ -831,6 +831,11 @@ namespace Avalonia.Controls
return;
}
if (!string.IsNullOrEmpty(_presenter.PreeditText))
{
return;
}
var text = Text ?? string.Empty;
var caretIndex = CaretIndex;
var movement = false;

40
src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

@ -1,7 +1,9 @@
using System;
using Avalonia.Controls.Presenters;
using Avalonia.Input.TextInput;
using Avalonia.Media.TextFormatting;
using Avalonia.Threading;
using Avalonia.Utilities;
using Avalonia.VisualTree;
namespace Avalonia.Controls
@ -54,7 +56,7 @@ namespace Avalonia.Controls
var lineStart = textLine.FirstTextSourceIndex;
var lineText = _presenter.Text?.Substring(lineStart, textLine.Length);
var lineText = GetTextLineText(textLine);
var anchorOffset = Math.Max(0, _parent.SelectionStart - lineStart);
@ -69,6 +71,29 @@ namespace Avalonia.Controls
}
}
private static string GetTextLineText(TextLine textLine)
{
var builder = StringBuilderCache.Acquire(textLine.Length);
foreach (var run in textLine.TextRuns)
{
if(run.Text.Length > 0)
{
#if NET6_0
builder.Append(run.Text.Span);
#else
builder.Append(run.Text.Span.ToArray());
#endif
}
}
var lineText = builder.ToString();
StringBuilderCache.Release(builder);
return lineText;
}
public event EventHandler? TextViewVisualChanged;
public event EventHandler? CursorRectangleChanged;
@ -149,19 +174,6 @@ namespace Avalonia.Controls
}
}
public void DeleteSurroundingText(int beforeLength, int afterLength)
{
if (_parent != null && _presenter != null && string.IsNullOrEmpty(_presenter.PreeditText))
{
var start = _presenter.SelectionStart;
_parent.SelectionStart = start - beforeLength;
_parent.SelectionEnd = start + afterLength;
_parent.DeleteSelection(true);
}
}
private void OnCaretBoundsChanged(object? sender, EventArgs e)
{
Dispatcher.UIThread.Post(() =>

4
src/Windows/Avalonia.Win32/Input/Imm32InputMethod.cs

@ -1,5 +1,4 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using Avalonia.Input.TextInput;
using Avalonia.Threading;
@ -79,9 +78,7 @@ namespace Avalonia.Win32.Input
{
HWND = hwnd;
_parent = parent;
_active = false;
_langId = PRIMARYLANGID(LGID(HKL));
_showCompositionWindow = true;
_parent = parent;
@ -105,7 +102,6 @@ namespace Avalonia.Win32.Input
_parent = null;
_client = null;
_langId = 0;
_showCompositionWindow = false;
IsComposing = false;
}

Loading…
Cancel
Save