csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
4.5 KiB
130 lines
4.5 KiB
using System;
|
|
using Android.Text;
|
|
using Android.Views;
|
|
using Android.Views.InputMethods;
|
|
using Avalonia.Android.Platform.SkiaPlatform;
|
|
using Avalonia.Input.TextInput;
|
|
|
|
namespace Avalonia.Android.Platform.Input
|
|
{
|
|
internal class TextEditBuffer
|
|
{
|
|
private readonly IAndroidInputMethod _textInputMethod;
|
|
private readonly TopLevelImpl _topLevel;
|
|
private TextSelection? _composition;
|
|
|
|
public TextEditBuffer(IAndroidInputMethod textInputMethod, TopLevelImpl topLevel)
|
|
{
|
|
_textInputMethod = textInputMethod;
|
|
_topLevel = topLevel;
|
|
}
|
|
|
|
public bool HasComposition => Composition is { } composition && composition.Start != composition.End;
|
|
|
|
public TextSelection Selection
|
|
{
|
|
get
|
|
{
|
|
var selection = _textInputMethod.Client?.Selection ?? default;
|
|
return new TextSelection(Math.Min(selection.Start, selection.End), Math.Max(selection.Start, selection.End));
|
|
}
|
|
|
|
set
|
|
{
|
|
if (_textInputMethod.Client is { } client)
|
|
client.Selection = value;
|
|
}
|
|
}
|
|
|
|
public TextSelection? Composition
|
|
{
|
|
get => _composition; set
|
|
{
|
|
if (value is { } v)
|
|
{
|
|
var text = Text;
|
|
var start = Math.Clamp(v.Start, 0, text.Length);
|
|
var end = Math.Clamp(v.End, 0, text.Length);
|
|
_composition = new TextSelection(Math.Min(start, end), Math.Max(start, end));
|
|
}
|
|
else
|
|
_composition = null;
|
|
}
|
|
}
|
|
|
|
public string? SelectedText
|
|
{
|
|
get
|
|
{
|
|
if(_textInputMethod.Client is not { } client || Selection.Start < 0 || Selection.End >= client.SurroundingText.Length)
|
|
{
|
|
return "";
|
|
}
|
|
|
|
var selection = Selection;
|
|
|
|
return client.SurroundingText.Substring(selection.Start, selection.End - selection.Start);
|
|
}
|
|
}
|
|
|
|
public string? ComposingText
|
|
{
|
|
get => !HasComposition ? null : Text?.Substring(Composition!.Value.Start, Composition!.Value.End - Composition!.Value.Start); set
|
|
{
|
|
if (HasComposition)
|
|
{
|
|
var start = Composition!.Value.Start;
|
|
Replace(Composition!.Value.Start, Composition!.Value.End, value ?? "");
|
|
Composition = new TextSelection(start, start + (value?.Length ?? 0));
|
|
}
|
|
else
|
|
{
|
|
var selection = Selection;
|
|
Replace(selection.Start, selection.End, value ?? "");
|
|
Composition = new TextSelection(selection.Start, selection.Start + (value?.Length ?? 0));
|
|
}
|
|
}
|
|
}
|
|
|
|
public string Text => _textInputMethod.Client?.SurroundingText ?? "";
|
|
|
|
public ExtractedText? ExtractedText => new ExtractedText
|
|
{
|
|
Flags = Text.Contains('\n') ? 0 : ExtractedTextFlags.SingleLine,
|
|
PartialStartOffset = -1,
|
|
PartialEndOffset = Text.Length,
|
|
SelectionStart = Selection.Start,
|
|
SelectionEnd = Selection.End,
|
|
StartOffset = 0,
|
|
Text = new Java.Lang.String(Text)
|
|
};
|
|
|
|
internal void Remove(int index, int length)
|
|
{
|
|
if (_textInputMethod.Client is { } client)
|
|
{
|
|
client.Selection = new TextSelection(index, index + length);
|
|
if (length > 0)
|
|
_textInputMethod?.View.DispatchKeyEvent(new KeyEvent(KeyEventActions.Down, Keycode.ForwardDel));
|
|
}
|
|
}
|
|
|
|
internal void Replace(int start, int end, string text)
|
|
{
|
|
if (_textInputMethod.Client is { } client)
|
|
{
|
|
var realStart = Math.Min(start, end);
|
|
var realEnd = Math.Max(start, end);
|
|
if (realEnd > realStart)
|
|
{
|
|
client.Selection = new TextSelection(realStart, realEnd);
|
|
_textInputMethod?.View.DispatchKeyEvent(new KeyEvent(KeyEventActions.Down, Keycode.ForwardDel));
|
|
}
|
|
_topLevel.TextInput(text);
|
|
var index = realStart + text.Length;
|
|
client.Selection = new TextSelection(index, index);
|
|
Composition = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|