committed by
GitHub
21 changed files with 505 additions and 566 deletions
@ -1,127 +0,0 @@ |
|||||
using System; |
|
||||
using Android.Runtime; |
|
||||
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, 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; |
|
||||
|
|
||||
public event EventHandler TextChanged; |
|
||||
public event EventHandler SelectionChanged; |
|
||||
public event EventHandler CompositionChanged; |
|
||||
|
|
||||
public InputEditable(TopLevelImpl topLevel, IAndroidInputMethod inputMethod, AvaloniaInputConnection avaloniaInputConnection) |
|
||||
{ |
|
||||
_topLevel = topLevel; |
|
||||
_inputMethod = inputMethod; |
|
||||
_avaloniaInputConnection = avaloniaInputConnection; |
|
||||
} |
|
||||
|
|
||||
public InputEditable(ICharSequence text) : base(text) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public InputEditable(string text) : base(text) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public InputEditable(ICharSequence text, int start, int end) : base(text, start, end) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public InputEditable(string text, int start, int end) : base(text, start, end) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
protected InputEditable(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
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 int CompositionStart => BaseInputConnection.GetComposingSpanStart(this); |
|
||||
|
|
||||
public int CompositionEnd => BaseInputConnection.GetComposingSpanEnd(this); |
|
||||
|
|
||||
public void BeginBatchEdit() |
|
||||
{ |
|
||||
_currentBatchLevel++; |
|
||||
|
|
||||
if (_currentBatchLevel == 1) |
|
||||
{ |
|
||||
_previousText = ToString(); |
|
||||
_previousSelectionStart = SelectionStart; |
|
||||
_previousSelectionEnd = SelectionEnd; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public void EndBatchEdit() |
|
||||
{ |
|
||||
if (_currentBatchLevel == 1) |
|
||||
{ |
|
||||
if(_previousText != Text) |
|
||||
{ |
|
||||
TextChanged?.Invoke(this, EventArgs.Empty); |
|
||||
} |
|
||||
|
|
||||
if (_previousSelectionStart != SelectionStart || _previousSelectionEnd != SelectionEnd) |
|
||||
{ |
|
||||
SelectionChanged?.Invoke(this, EventArgs.Empty); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
_currentBatchLevel--; |
|
||||
} |
|
||||
|
|
||||
public void RaiseCompositionChanged() |
|
||||
{ |
|
||||
CompositionChanged?.Invoke(this, EventArgs.Empty); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,23 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Text; |
|
||||
using System.Threading.Tasks; |
|
||||
using Avalonia.Metadata; |
|
||||
|
|
||||
namespace Avalonia.Input.TextInput |
|
||||
{ |
|
||||
[NotClientImplementable] |
|
||||
public interface ITextEditable |
|
||||
{ |
|
||||
event EventHandler TextChanged; |
|
||||
event EventHandler SelectionChanged; |
|
||||
event EventHandler CompositionChanged; |
|
||||
int SelectionStart { get; set; } |
|
||||
int SelectionEnd { get; set; } |
|
||||
int CompositionStart { get; } |
|
||||
int CompositionEnd { get; } |
|
||||
|
|
||||
string? Text { get; set; } |
|
||||
} |
|
||||
} |
|
||||
@ -1,66 +0,0 @@ |
|||||
using System; |
|
||||
using Avalonia.Media.TextFormatting; |
|
||||
using Avalonia.VisualTree; |
|
||||
|
|
||||
namespace Avalonia.Input.TextInput |
|
||||
{ |
|
||||
public interface ITextInputMethodClient |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// The cursor rectangle relative to the TextViewVisual
|
|
||||
/// </summary>
|
|
||||
Rect CursorRectangle { get; } |
|
||||
/// <summary>
|
|
||||
/// Should be fired when cursor rectangle is changed inside the TextViewVisual
|
|
||||
/// </summary>
|
|
||||
event EventHandler? CursorRectangleChanged; |
|
||||
/// <summary>
|
|
||||
/// The visual that's showing the text
|
|
||||
/// </summary>
|
|
||||
Visual TextViewVisual { get; } |
|
||||
/// <summary>
|
|
||||
/// Should be fired when text-hosting visual is changed
|
|
||||
/// </summary>
|
|
||||
event EventHandler? TextViewVisualChanged; |
|
||||
/// <summary>
|
|
||||
/// Indicates if TextViewVisual is capable of displaying non-committed input on the cursor position
|
|
||||
/// </summary>
|
|
||||
bool SupportsPreedit { get; } |
|
||||
/// <summary>
|
|
||||
/// Sets the non-committed input string
|
|
||||
/// </summary>
|
|
||||
void SetPreeditText(string? text); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Sets the current composing region. This doesn't remove the composing text from the commited text.
|
|
||||
/// </summary>
|
|
||||
void SetComposingRegion(TextRange? region); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Indicates if text input client is capable of providing the text around the cursor
|
|
||||
/// </summary>
|
|
||||
bool SupportsSurroundingText { get; } |
|
||||
/// <summary>
|
|
||||
/// Returns the text around the cursor, usually the current paragraph, the cursor position inside that text and selection start position
|
|
||||
/// </summary>
|
|
||||
TextInputMethodSurroundingText SurroundingText { get; } |
|
||||
/// <summary>
|
|
||||
/// Should be fired when surrounding text changed
|
|
||||
/// </summary>
|
|
||||
event EventHandler? SurroundingTextChanged; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets or sets a platform editable. Text and selection changes made in the editable are forwarded to the IM client.
|
|
||||
/// </summary>
|
|
||||
ITextEditable? TextEditable { get; set; } |
|
||||
|
|
||||
void SelectInSurroundingText(int start, int end); |
|
||||
} |
|
||||
|
|
||||
public record struct TextInputMethodSurroundingText |
|
||||
{ |
|
||||
public string Text { get; set; } |
|
||||
public int CursorOffset { get; set; } |
|
||||
public int AnchorOffset { get; set; } |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,84 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Avalonia.Input.TextInput |
||||
|
{ |
||||
|
public abstract class TextInputMethodClient |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Fires when the text view visual has changed
|
||||
|
/// </summary>
|
||||
|
public event EventHandler? TextViewVisualChanged; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Fires when the cursor rectangle has changed
|
||||
|
/// </summary>
|
||||
|
public event EventHandler? CursorRectangleChanged; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Fires when the surrounding text has changed
|
||||
|
/// </summary>
|
||||
|
public event EventHandler? SurroundingTextChanged; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Fires when the selection has changed
|
||||
|
/// </summary>
|
||||
|
public event EventHandler? SelectionChanged; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The visual that's showing the text
|
||||
|
/// </summary>
|
||||
|
public abstract Visual TextViewVisual { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Indicates if TextViewVisual is capable of displaying non-committed input on the cursor position
|
||||
|
/// </summary>
|
||||
|
public abstract bool SupportsPreedit { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Indicates if text input client is capable of providing the text around the cursor
|
||||
|
/// </summary>
|
||||
|
public abstract bool SupportsSurroundingText { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the text around the cursor, usually the current paragraph
|
||||
|
/// </summary>
|
||||
|
public abstract string SurroundingText { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the cursor rectangle relative to the TextViewVisual
|
||||
|
/// </summary>
|
||||
|
public abstract Rect CursorRectangle { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the curent selection range within current surrounding text.
|
||||
|
/// </summary>
|
||||
|
public abstract TextSelection Selection { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the non-committed input string
|
||||
|
/// </summary>
|
||||
|
public virtual void SetPreeditText(string? preeditText) { } |
||||
|
|
||||
|
protected virtual void RaiseTextViewVisualChanged() |
||||
|
{ |
||||
|
TextViewVisualChanged?.Invoke(this, EventArgs.Empty); |
||||
|
} |
||||
|
|
||||
|
protected virtual void RaiseCursorRectangleChanged() |
||||
|
{ |
||||
|
CursorRectangleChanged?.Invoke(this, EventArgs.Empty); |
||||
|
} |
||||
|
|
||||
|
protected virtual void RaiseSurroundingTextChanged() |
||||
|
{ |
||||
|
SurroundingTextChanged?.Invoke(this, EventArgs.Empty); |
||||
|
} |
||||
|
|
||||
|
protected virtual void RaiseSelectionChanged() |
||||
|
{ |
||||
|
SelectionChanged?.Invoke(this, EventArgs.Empty); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public record struct TextSelection(int Start, int End); |
||||
|
} |
||||
Loading…
Reference in new issue