|
|
@@ -4,24 +4,34 @@ using Android.Text;
|
|
|
using Android.Views;
|
|
|
using Android.Views.InputMethods;
|
|
|
using Avalonia.Android.Platform.SkiaPlatform;
|
|
|
+using Avalonia.Controls.Presenters;
|
|
|
using Avalonia.Input;
|
|
|
using Avalonia.Input.Raw;
|
|
|
+using Avalonia.Input.TextInput;
|
|
|
using Java.Lang;
|
|
|
using static System.Net.Mime.MediaTypeNames;
|
|
|
|
|
|
namespace Avalonia.Android
|
|
|
{
|
|
|
- internal class InputEditable : SpannableStringBuilder
|
|
|
+ internal class InputEditable : SpannableStringBuilder, IDisposable, ITextEditable
|
|
|
{
|
|
|
private readonly TopLevelImpl _topLevel;
|
|
|
private readonly IAndroidInputMethod _inputMethod;
|
|
|
+ private readonly AvaloniaInputConnection _avaloniaInputConnection;
|
|
|
private int _currentBatchLevel;
|
|
|
private string _previousText;
|
|
|
+ private int _previousSelectionStart;
|
|
|
+ private int _previousSelectionEnd;
|
|
|
+ private TextPresenter _presenter;
|
|
|
|
|
|
- public InputEditable(TopLevelImpl topLevel, IAndroidInputMethod inputMethod)
|
|
|
+ public event EventHandler TextChanged;
|
|
|
+ public event EventHandler SelectionChanged;
|
|
|
+
|
|
|
+ public InputEditable(TopLevelImpl topLevel, IAndroidInputMethod inputMethod, AvaloniaInputConnection avaloniaInputConnection)
|
|
|
{
|
|
|
_topLevel = topLevel;
|
|
|
_inputMethod = inputMethod;
|
|
|
+ _avaloniaInputConnection = avaloniaInputConnection;
|
|
|
}
|
|
|
|
|
|
public InputEditable(ICharSequence text) : base(text)
|
|
|
@@ -46,47 +56,80 @@ namespace Avalonia.Android
|
|
|
|
|
|
public bool IsInBatchEdit => _currentBatchLevel > 0;
|
|
|
|
|
|
+ public TextPresenter Presenter { get => _presenter; }
|
|
|
+
|
|
|
+
|
|
|
+ public int SelectionStart
|
|
|
+ {
|
|
|
+ get => Selection.GetSelectionStart(this); set
|
|
|
+ {
|
|
|
+ var end = SelectionEnd < 0 ? 0 : SelectionEnd;
|
|
|
+ _avaloniaInputConnection.SetSelection(value, end);
|
|
|
+ _inputMethod.IMM.UpdateSelection(_topLevel.View, value, end, value, end);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public int SelectionEnd
|
|
|
+ {
|
|
|
+ get => Selection.GetSelectionEnd(this); set
|
|
|
+ {
|
|
|
+ var start = SelectionStart < 0 ? 0 : SelectionStart;
|
|
|
+ _avaloniaInputConnection.SetSelection(start, value);
|
|
|
+ _inputMethod.IMM.UpdateSelection(_topLevel.View, start, value, start, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public string? Text
|
|
|
+ {
|
|
|
+ get => ToString(); set
|
|
|
+ {
|
|
|
+ if (Text != value)
|
|
|
+ {
|
|
|
+ Clear();
|
|
|
+ Insert(0, value ?? "");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void BeginBatchEdit()
|
|
|
{
|
|
|
_currentBatchLevel++;
|
|
|
|
|
|
- if(_currentBatchLevel == 1)
|
|
|
+ if (_currentBatchLevel == 1)
|
|
|
{
|
|
|
_previousText = ToString();
|
|
|
+ _previousSelectionStart = SelectionStart;
|
|
|
+ _previousSelectionEnd = SelectionEnd;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public void EndBatchEdit()
|
|
|
{
|
|
|
- if (_currentBatchLevel == 1)
|
|
|
+ if (_currentBatchLevel == 1 && _presenter != null)
|
|
|
{
|
|
|
- _inputMethod.Client.SelectInSurroundingText(-1, _previousText.Length);
|
|
|
- var time = DateTime.Now.TimeOfDay;
|
|
|
- var currentText = ToString();
|
|
|
-
|
|
|
- if (string.IsNullOrEmpty(currentText))
|
|
|
+ if(_previousText != Text)
|
|
|
{
|
|
|
- _inputMethod.View.DispatchKeyEvent(new KeyEvent(KeyEventActions.Down, Keycode.ForwardDel));
|
|
|
+ TextChanged?.Invoke(this, EventArgs.Empty);
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ if (_previousSelectionStart != SelectionStart || _previousSelectionEnd != SelectionEnd)
|
|
|
{
|
|
|
- var rawTextEvent = new RawTextInputEventArgs(KeyboardDevice.Instance, (ulong)time.Ticks, _topLevel.InputRoot, currentText);
|
|
|
- _topLevel.Input(rawTextEvent);
|
|
|
+ SelectionChanged?.Invoke(this, EventArgs.Empty);
|
|
|
}
|
|
|
- _inputMethod.Client.SelectInSurroundingText(Selection.GetSelectionStart(this), Selection.GetSelectionEnd(this));
|
|
|
-
|
|
|
- _previousText = "";
|
|
|
}
|
|
|
|
|
|
_currentBatchLevel--;
|
|
|
}
|
|
|
|
|
|
- public void UpdateString(string? text)
|
|
|
+ void IDisposable.Dispose()
|
|
|
+ {
|
|
|
+ _presenter = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SetPresenter(TextPresenter presenter)
|
|
|
{
|
|
|
- if(text != ToString())
|
|
|
+ if (_presenter == null)
|
|
|
{
|
|
|
- Clear();
|
|
|
- Insert(0, text);
|
|
|
+ _presenter = presenter;
|
|
|
}
|
|
|
}
|
|
|
}
|