diff --git a/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs b/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs index dbfc8c9596..f0d5e5d1ef 100644 --- a/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs +++ b/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs @@ -43,16 +43,11 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput } private string _markedText = ""; - private readonly IUITextInputDelegate _inputDelegate; private ITextInputMethodClient? _client; private NSDictionary? _markedTextStyle; private readonly UITextPosition _beginningOfDocument = new AvaloniaTextPosition(0); private readonly UITextInputStringTokenizer _tokenizer; - private class TextInputHandler : UITextInputDelegate - { - } - public ITextInputMethodClient? Client => _client; public bool IsActive => _client != null; @@ -63,10 +58,17 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput void ITextInputMethodImpl.SetClient(ITextInputMethodClient? client) { + if (_client != null) + { + _client.CursorRectangleChanged -= ClientOnCursorRectangleChanged; + } + _client = client; if (_client is { }) { + _client.CursorRectangleChanged += ClientOnCursorRectangleChanged; + _client.SurroundingTextChanged += ClientOnSurroundingTextChanged; BecomeFirstResponder(); } else @@ -75,6 +77,23 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput } } + private void ClientOnSurroundingTextChanged(object? sender, EventArgs e) + { + var _inputDelegate = UITextInputDelegate.FromObject(((IUITextInput)this).WeakInputDelegate) as IUITextInputDelegate; + + _inputDelegate?.TextWillChange(this); + _inputDelegate?.TextDidChange(this); + } + + private void ClientOnCursorRectangleChanged(object? sender, EventArgs e) + { + var _inputDelegate = Runtime.GetINativeObject(((IUITextInput)this).WeakInputDelegate.Handle.Handle, true); + + + _inputDelegate?.SelectionWillChange(this); + _inputDelegate?.SelectionDidChange(this); + } + void ITextInputMethodImpl.SetCursorRect(Rect rect) { // maybe this will be cursor / selection rect? @@ -139,6 +158,7 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput } ReturnKeyType = (UIReturnKeyType)options.ReturnKeyType; + AutocorrectionType = UITextAutocorrectionType.Yes; } @@ -148,11 +168,36 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput } // Traits (Optional) + [Export("autocapitalizationType")] public UITextAutocapitalizationType AutocapitalizationType { get; private set; } + + [Export("autocorrectionType")] public UITextAutocorrectionType AutocorrectionType { get; private set; } [Export("keyboardType")] public UIKeyboardType KeyboardType { get; private set; } = UIKeyboardType.Default; + [Export("keyboardAppearance")] + public UIKeyboardAppearance KeyboardAppearance { get; private set; } = UIKeyboardAppearance.Default; + + [Export("returnKeyType")] public UIReturnKeyType ReturnKeyType { get; set; } + + [Export("enablesReturnKeyAutomatically")] public bool EnablesReturnKeyAutomatically { get; set; } [Export("isSecureTextEntry")] public bool IsSecureEntry { get; private set; } - [Export("returnKeyType")] public UIReturnKeyType ReturnKeyType { get; set; } + [Export("spellCheckingType")] + public UITextSpellCheckingType SpellCheckingType { get; set; } = UITextSpellCheckingType.Default; + + [Export("textContentType")] + public NSString TextContentType { get; set; } + + [Export("smartQuotesType")] + public UITextSmartQuotesType SmartQuotesType { get; set; } = UITextSmartQuotesType.Default; + + [Export("smartDashesType")] + public UITextSmartDashesType SmartDashesType { get; set; } = UITextSmartDashesType.Default; + + [Export("smartInsertDeleteType")] + public UITextSmartInsertDeleteType SmartInsertDeleteType { get; set; } = UITextSmartInsertDeleteType.Default; + + [Export("passwordRules")] + public UITextInputPasswordRules PasswordRules { get; set; } void IUIKeyInput.InsertText(string text) { @@ -213,7 +258,9 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput var start = (range.Start as AvaloniaTextPosition).Offset; int end = (range.End as AvaloniaTextPosition).Offset; - return text[start .. end]; + var result = text[start .. end]; + + return result; } void IUITextInput.ReplaceText(UITextRange range, string text) @@ -246,7 +293,7 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput _markedText = ""; } - UITextRange IUITextInput.GetTextRange(UITextPosition fromPosition, UITextPosition toPosition) + public UITextRange GetTextRange(UITextPosition fromPosition, UITextPosition toPosition) { if (fromPosition is AvaloniaTextPosition f && toPosition is AvaloniaTextPosition t) { @@ -273,7 +320,7 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput return new AvaloniaTextPosition(posPlusIndex); } - throw new Exception(); + return null; } UITextPosition IUITextInput.GetPosition(UITextPosition fromPosition, UITextLayoutDirection inDirection, nint offset) @@ -311,14 +358,19 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput return NSComparisonResult.Same; } - throw new Exception(); + return NSComparisonResult.Descending; } nint IUITextInput.GetOffsetFromPosition(UITextPosition fromPosition, UITextPosition toPosition) { - if (fromPosition is AvaloniaTextPosition f && toPosition is AvaloniaTextPosition t) + if (fromPosition is AvaloniaTextPosition f) { - return t.Offset - f.Offset; + if (toPosition is AvaloniaTextPosition t) + { + return t.Offset - f.Offset; + } + + return f.Offset; } throw new Exception(); @@ -452,10 +504,11 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput } } + NSObject? IUITextInput.WeakInputDelegate { - get => _inputDelegate as TextInputHandler; - set => throw new NotSupportedException(); + get; + set; } NSObject IUITextInput.WeakTokenizer => _tokenizer; @@ -466,10 +519,15 @@ public partial class AvaloniaView : ITextInputMethodImpl, IUITextInput { if (string.IsNullOrWhiteSpace(_markedText)) { - return null; + //return null; } - return new AvaloniaTextRange(0, _markedText.Length); + if (_client == null) + { + return null; + } + + return new AvaloniaTextRange(Math.Min(_client.SurroundingText.CursorOffset, _client.SurroundingText.AnchorOffset), Math.Max(_client.SurroundingText.CursorOffset, _client.SurroundingText.AnchorOffset)); } } } diff --git a/src/iOS/Avalonia.iOS/AvaloniaView.cs b/src/iOS/Avalonia.iOS/AvaloniaView.cs index 77363aef7b..06201e366b 100644 --- a/src/iOS/Avalonia.iOS/AvaloniaView.cs +++ b/src/iOS/Avalonia.iOS/AvaloniaView.cs @@ -31,7 +31,7 @@ namespace Avalonia.iOS _topLevelImpl = new TopLevelImpl(this); _touches = new TouchHandler(this, _topLevelImpl); _topLevel = new EmbeddableControlRoot(_topLevelImpl); - _inputDelegate = new TextInputHandler(); + _tokenizer = new UITextInputStringTokenizer(this); _topLevel.Prepare();