浏览代码

Add TextBox.ScrollToLine (#13274)

* Add TextBox.ScrollToLine #3036

* Test data in arabic for RTL testing
Magnus Lindhe 2 年之前
父节点
当前提交
c261a60018
共有 2 个文件被更改,包括 63 次插入0 次删除
  1. 22 0
      src/Avalonia.Controls/TextBox.cs
  2. 41 0
      tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

+ 22 - 0
src/Avalonia.Controls/TextBox.cs

@@ -1877,6 +1877,28 @@ namespace Avalonia.Controls
             _scrollViewer?.PageDown();
         }
 
+        /// <summary>
+        /// Scroll the <see cref="TextBox"/> to the specified line index.
+        /// </summary>
+        /// <param name="lineIndex">The line index to scroll to.</param>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="lineIndex"/> is less than zero. -or - <paramref name="lineIndex"/> is larger than or equal to the line count.</exception>
+        public void ScrollToLine(int lineIndex)
+        {
+            if (_presenter is null)
+            {
+                return;
+            }
+
+            if (lineIndex < 0 || lineIndex >= _presenter.TextLayout.TextLines.Count)
+            {
+                throw new ArgumentOutOfRangeException(nameof(lineIndex));
+            }
+
+            var textLine = _presenter.TextLayout.TextLines[lineIndex];
+            _presenter.MoveCaretToTextPosition(textLine.FirstTextSourceIndex);
+
+        }
+
         /// <summary>
         /// Select all text in the TextBox
         /// </summary>

+ 41 - 0
tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

@@ -1182,6 +1182,47 @@ namespace Avalonia.Controls.UnitTests
             }
         }
 
+        [Theory]
+        [InlineData("A\nBB\nCCC\nDDDD", 0, 0)]
+        [InlineData("A\nBB\nCCC\nDDDD", 1, 2)]
+        [InlineData("A\nBB\nCCC\nDDDD", 2, 5)]
+        [InlineData("A\nBB\nCCC\nDDDD", 3, 9)]
+        [InlineData("واحد\nاثنين\nثلاثة\nأربعة", 0, 0)]
+        [InlineData("واحد\nاثنين\nثلاثة\nأربعة", 1, 5)]
+        [InlineData("واحد\nاثنين\nثلاثة\nأربعة", 2, 11)]
+        [InlineData("واحد\nاثنين\nثلاثة\nأربعة", 3, 17)]
+        public void Should_Scroll_Caret_To_Line(string text, int targetLineIndex, int expectedCaretIndex)
+        {
+            using (UnitTestApplication.Start(Services))
+            {
+                var tb = new TextBox
+                {
+                    Template = CreateTemplate(),
+                    Text = text
+                };
+                tb.ApplyTemplate();
+                tb.ScrollToLine(targetLineIndex);
+                Assert.Equal(expectedCaretIndex, tb.CaretIndex);
+            }
+        }
+
+        [Fact]
+        public void Should_Throw_ArgumentOutOfRange()
+        {
+            using (UnitTestApplication.Start(Services))
+            {
+                var tb = new TextBox
+                {
+                    Template = CreateTemplate(),
+                    Text = string.Empty
+                };
+                tb.ApplyTemplate();
+
+                Assert.Throws<ArgumentOutOfRangeException>(() => tb.ScrollToLine(-1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => tb.ScrollToLine(1));
+            }
+        }
+
         private static TestServices FocusServices => TestServices.MockThreadingInterface.With(
             focusManager: new FocusManager(),
             keyboardDevice: () => new KeyboardDevice(),