浏览代码

Adjust TextInputMethodClient

Benedikt Stebner 2 年之前
父节点
当前提交
037bbd3ca0

+ 1 - 0
samples/MobileSandbox.Android/MainActivity.cs

@@ -1,6 +1,7 @@
 using System;
 using Android.App;
 using Android.Content.PM;
+using Android.OS;
 using Avalonia;
 using Avalonia.Android;
 

+ 9 - 61
src/Avalonia.Base/Input/TextInput/TextInputMethodClient.cs

@@ -4,10 +4,6 @@ namespace Avalonia.Input.TextInput
 {
     public abstract class TextInputMethodClient
     {
-        private Rect _cursorRectangle;
-        private string _surroundingText = "";
-        private TextSelection _selection;
-
         /// <summary>
         /// Fires when the text view visual has changed
         /// </summary>
@@ -46,87 +42,39 @@ namespace Avalonia.Input.TextInput
         /// <summary>
         /// Returns the text around the cursor, usually the current paragraph
         /// </summary>
-        public string SurroundingText
-        {
-            get => _surroundingText;
-            set
-            {
-                var oldValue = _surroundingText;
-
-                if (oldValue == value)
-                {
-                    return;
-                }
-
-                _surroundingText = value;
-
-                OnSurroundingTextChanged(oldValue, value);
-            }
-        }
+        public abstract string SurroundingText { get; }
 
         /// <summary>
         /// Gets the cursor rectangle relative to the TextViewVisual
         /// </summary>
-        public Rect CursorRectangle
-        {
-            get => _cursorRectangle;
-            protected set
-            {
-                var oldvalue = _cursorRectangle;
-
-                if (oldvalue == value)
-                {
-                    return;
-                }
-
-                _cursorRectangle = value;
-
-                OnCursorRectangleChanged(oldvalue, value);
-            }
-        }
+        public abstract Rect CursorRectangle { get; }
 
         /// <summary>
         /// Gets or sets the curent selection range within current surrounding text.
         /// </summary>
-        public TextSelection Selection
-        {
-            get => _selection;
-            set
-            {
-                var oldValue = _selection;
-
-                if (oldValue == value)
-                {
-                    return;
-                }
-
-                _selection = value;
-
-                OnSelectionChanged(oldValue, value);
-            }
-        }
+        public abstract TextSelection Selection { get; set; }
 
         /// <summary>
         /// Sets the non-committed input string
         /// </summary>
         public virtual void SetPreeditText(string? preeditText) { }
 
-        protected virtual void OnCursorRectangleChanged(Rect oldValue, Rect newValue)
+        protected virtual void OnTextViewVisualChanged(Visual? oldValue, Visual? newValue)
         {
-            CursorRectangleChanged?.Invoke(this, EventArgs.Empty);
+            TextViewVisualChanged?.Invoke(this, EventArgs.Empty);
         }
 
-        protected virtual void OnTextViewVisualChanged(Visual? oldValue, Visual? newValue)
+        protected virtual void OnCursorRectangleChanged()
         {
-            TextViewVisualChanged?.Invoke(this, EventArgs.Empty);
+            CursorRectangleChanged?.Invoke(this, EventArgs.Empty);
         }
 
-        protected virtual void OnSurroundingTextChanged(string? oldValue, string? newValue)
+        protected virtual void OnSurroundingTextChanged()
         {
             SurroundingTextChanged?.Invoke(this, EventArgs.Empty);
         }
 
-        protected virtual void OnSelectionChanged(TextSelection oldValue, TextSelection newValue)
+        protected virtual void OnSelectionChanged()
         {
             SelectionChanged?.Invoke(this, EventArgs.Empty);
         }

+ 100 - 116
src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

@@ -10,10 +10,104 @@ namespace Avalonia.Controls
     {
         private TextBox? _parent;
         private TextPresenter? _presenter;
-        private bool _isPropertyChange;
 
         public override Visual TextViewVisual => _presenter!;
 
+        public override string SurroundingText
+        {
+            get
+            {
+                if (_presenter is null || _parent is null)
+                {
+                    return "";
+                }
+
+#if DEBUG
+                if (_parent.CaretIndex != _presenter.CaretIndex)
+                {
+                    throw new InvalidOperationException("TextBox and TextPresenter are out of sync");
+                }
+
+                if (_parent.Text != _presenter.Text)
+                {
+                    throw new InvalidOperationException("TextBox and TextPresenter are out of sync");
+                }
+#endif
+
+                var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_presenter.CaretIndex, false);
+
+                var textLine = _presenter.TextLayout.TextLines[lineIndex];
+
+                var lineText = GetTextLineText(textLine);
+
+                return lineText;
+            }
+        }
+
+        public override Rect CursorRectangle
+        {
+            get
+            {
+                if (_parent == null || _presenter == null)
+                {
+                    return default;
+                }
+
+                var transform = _presenter.TransformToVisual(_parent);
+
+                if (transform == null)
+                {
+                    return default;
+                }
+
+                return _presenter.GetCursorRectangle().TransformToAABB(transform.Value);
+            }
+        }
+
+        public override TextSelection Selection
+        {
+            get
+            {
+                if (_presenter is null || _parent is null)
+                {
+                    return default;
+                }
+
+                var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_parent.CaretIndex, false);
+
+                var textLine = _presenter.TextLayout.TextLines[lineIndex];
+
+                var lineStart = textLine.FirstTextSourceIndex;
+
+                var selectionStart = Math.Max(0, _parent.SelectionStart - lineStart);
+
+                var selectionEnd = Math.Max(0, _parent.SelectionEnd - lineStart);
+
+                return new TextSelection(selectionStart, selectionEnd);
+            }
+            set
+            {
+                if (_parent is null || _presenter is null)
+                {
+                    return;
+                }
+
+                var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_parent.CaretIndex, false);
+
+                var textLine = _presenter.TextLayout.TextLines[lineIndex];
+
+                var lineStart = textLine.FirstTextSourceIndex;
+
+                var selectionStart = lineStart + value.Start;
+                var selectionEnd = lineStart + value.End;
+
+                _parent.SelectionStart = selectionStart;
+                _parent.SelectionEnd = selectionEnd;
+
+                OnSelectionChanged();
+            }
+        }
+
         public override bool SupportsPreedit => true;
 
         public override bool SupportsSurroundingText => true;
@@ -38,19 +132,19 @@ namespace Avalonia.Controls
             {
                 oldPresenter.ClearValue(TextPresenter.PreeditTextProperty);
 
-                oldPresenter.CaretBoundsChanged -= OnPresenterCursorRectangleChanged;
+                oldPresenter.CaretBoundsChanged -= (s,e) => OnCursorRectangleChanged();
             }
 
             _presenter = presenter;
 
             if (_presenter != null)
             {
-                _presenter.CaretBoundsChanged += OnPresenterCursorRectangleChanged;
+                _presenter.CaretBoundsChanged += (s, e) => OnCursorRectangleChanged();
             }
 
             OnTextViewVisualChanged(oldPresenter, presenter);
 
-            OnPresenterCursorRectangleChanged(this, EventArgs.Empty);
+            OnCursorRectangleChanged();
         }
 
         public override void SetPreeditText(string? preeditText)
@@ -63,21 +157,6 @@ namespace Avalonia.Controls
             _presenter.SetCurrentValue(TextPresenter.PreeditTextProperty, preeditText);
         }
 
-        protected override void OnSelectionChanged(TextSelection oldValue, TextSelection newValue)
-        {
-            base.OnSelectionChanged(oldValue, newValue);
-
-            if (_isPropertyChange)
-            {
-                return;
-            }
-
-            if (oldValue != newValue)
-            {
-                SetParentSelection(newValue);
-            }
-        }
-
         private static string GetTextLineText(TextLine textLine)
         {
             var builder = StringBuilderCache.Acquire(textLine.Length);
@@ -101,112 +180,17 @@ namespace Avalonia.Controls
             return lineText;
         }
 
-        private void OnParentTextChanged()
-        {
-            if (_presenter is null || _parent is null)
-            {
-                SurroundingText = "";
-
-                return;
-            }
-
-#if DEBUG
-            if (_parent.CaretIndex != _presenter.CaretIndex)
-            {
-                throw new InvalidOperationException("TextBox and TextPresenter are out of sync");
-            }
-
-            if (_parent.Text != _presenter.Text)
-            {
-                throw new InvalidOperationException("TextBox and TextPresenter are out of sync");
-            }
-#endif
-
-            var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_presenter.CaretIndex, false);
-
-            var textLine = _presenter.TextLayout.TextLines[lineIndex];
-
-            var lineText = GetTextLineText(textLine);
-
-            SurroundingText = lineText;
-        }
-
-        private void OnPresenterCursorRectangleChanged(object? sender, EventArgs e)
-        {
-            if (_parent == null || _presenter == null)
-            {
-                CursorRectangle = default;
-
-                return;
-            }
-
-            var transform = _presenter.TransformToVisual(_parent);
-
-            if (transform == null)
-            {
-                CursorRectangle = default;
-
-                return;
-            }
-
-            CursorRectangle = _presenter.GetCursorRectangle().TransformToAABB(transform.Value);
-        }
-
         private void OnParentPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
         {
-            _isPropertyChange = true;
-
             if (e.Property == TextBox.TextProperty)
             {
-                OnParentTextChanged();
+                OnSurroundingTextChanged();
             }
 
             if (e.Property == TextBox.SelectionStartProperty || e.Property == TextBox.SelectionEndProperty)
             {
-                Selection = GetParentSelection();
-            }
-
-            _isPropertyChange = false;
-        }
-
-        private TextSelection GetParentSelection()
-        {
-            if (_presenter is null || _parent is null)
-            {
-                return default;
-            }
-
-            var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_parent.CaretIndex, false);
-
-            var textLine = _presenter.TextLayout.TextLines[lineIndex];
-
-            var lineStart = textLine.FirstTextSourceIndex;
-
-            var selectionStart = Math.Max(0, _parent.SelectionStart - lineStart);
-
-            var selectionEnd = Math.Max(0, _parent.SelectionEnd - lineStart);
-
-            return new TextSelection(selectionStart, selectionEnd);
-        }
-
-        private void SetParentSelection(TextSelection selection)
-        {
-            if (_parent is null || _presenter is null)
-            {
-                return;
+                OnSelectionChanged();
             }
-
-            var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_parent.CaretIndex, false);
-
-            var textLine = _presenter.TextLayout.TextLines[lineIndex];
-
-            var lineStart = textLine.FirstTextSourceIndex;
-
-            var selectionStart = lineStart + selection.Start;
-            var selectionEnd = lineStart + selection.End;
-
-            _parent.SelectionStart = selectionStart;
-            _parent.SelectionEnd = selectionEnd;
         }
     }
 }