Browse Source

fix(SelectableTextBlock): fix SelectableTextBlock selection for centered and right-aligned text (#21369)

* fix(SelectableTextBlock): fix SelectableTextBlock selection for centered and right-aligned text

* Fix failing unit tests

* Let TextLayout handle out-of-bounds hit testing

---------

Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
pull/21953/head
Yoyo 2 months ago
committed by GitHub
parent
commit
faf7137b2a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 23
      samples/ControlCatalog/Pages/TextBlockPage.xaml
  2. 4
      src/Avalonia.Controls/SelectableTextBlock.cs
  3. 43
      tests/Avalonia.Controls.UnitTests/SelectableTextBlockTests.cs

23
samples/ControlCatalog/Pages/TextBlockPage.xaml

@ -119,15 +119,20 @@
</StackPanel>
</Border>
<Border>
<SelectableTextBlock Margin="10" TextWrapping="Wrap">
This <Span FontWeight="Bold">is</Span> a
<Span Background="Silver" Foreground="Maroon">TextBlock</Span>
with <Span TextDecorations="Underline">several</Span>
<Span FontStyle="Italic">Span</Span> elements,
<Span Foreground="Blue">
using a <Bold>variety</Bold> of <Italic>styles</Italic>
</Span>.
</SelectableTextBlock>
<StackPanel Spacing="8">
<SelectableTextBlock Margin="10" TextWrapping="Wrap">
This <Span FontWeight="Bold">is</Span> a
<Span Background="Silver" Foreground="Maroon">TextBlock</Span>
with <Span TextDecorations="Underline">several</Span>
<Span FontStyle="Italic">Span</Span> elements,
<Span Foreground="Blue">
using a <Bold>variety</Bold> of <Italic>styles</Italic>
</Span>.
</SelectableTextBlock>
<SelectableTextBlock Text="Left aligned text" TextAlignment="Left" />
<SelectableTextBlock Text="Center aligned text" TextAlignment="Center" />
<SelectableTextBlock Text="Right aligned text and wrap text" TextAlignment="Right" TextWrapping="Wrap" />
</StackPanel>
</Border>
<Border>
<TextBlock FontFamily="Times New Roman">

4
src/Avalonia.Controls/SelectableTextBlock.cs

@ -451,10 +451,6 @@ namespace Avalonia.Controls
var point = e.GetPosition(this) - new Point(padding.Left, padding.Top);
point = new Point(
MathUtilities.Clamp(point.X, 0, Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0)),
MathUtilities.Clamp(point.Y, 0, Math.Max(TextLayout.Height, 0)));
var hit = TextLayout.HitTestPoint(point);
var textPosition = hit.TextPosition;

43
tests/Avalonia.Controls.UnitTests/SelectableTextBlockTests.cs

@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using Avalonia.Controls.Documents;
using Avalonia.Media;
using Avalonia.Media.TextFormatting;
@ -49,6 +50,46 @@ namespace Avalonia.Controls.UnitTests
}
}
[Theory]
[InlineData(TextAlignment.Center)]
[InlineData(TextAlignment.Right)]
public void Dragging_Selection_Should_Reach_End_Of_Text_When_Text_Is_Aligned(TextAlignment textAlignment)
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var target = new SelectableTextBlock
{
Width = 200,
Text = "Aligned text",
TextAlignment = textAlignment
};
var root = new TestRoot(target)
{
ClientSize = new Size(300, 100)
};
root.Measure(root.ClientSize);
root.Arrange(new Rect(root.ClientSize));
root.ExecuteInitialLayoutPass();
var firstCharacterBounds = target.TextLayout.HitTestTextPosition(0);
var lastCharacterBounds = target.TextLayout.HitTestTextPosition(target.Text!.Length - 1);
var mouse = new MouseTestHelper();
var startPoint = new Point(
firstCharacterBounds.X + firstCharacterBounds.Width / 2,
firstCharacterBounds.Y + firstCharacterBounds.Height / 2);
var endPoint = new Point(
Math.Min(target.Bounds.Width - 1, lastCharacterBounds.Right + 10),
lastCharacterBounds.Y + lastCharacterBounds.Height / 2);
mouse.Down(target, position: target.TranslatePoint(startPoint, root));
mouse.Move(target, position: target.TranslatePoint(endPoint, root).GetValueOrDefault());
Assert.Equal(target.Text!.Length, Math.Max(target.SelectionStart, target.SelectionEnd));
}
}
[Fact]
public void SelectionForeground_Should_Not_Reset_Run_Typeface_And_Style()
{

Loading…
Cancel
Save