Skip to content

Commit

Permalink
Fix TextBlock re-measure in infinite container (#17638)
Browse files Browse the repository at this point in the history
* Add failing test for TextBlock

* Fix TextBlock re-measure in infinite container

* Fix outdated test

---------

Co-authored-by: Max Katz <[email protected]>
  • Loading branch information
MrJul and maxkatz6 authored Nov 30, 2024
1 parent 1583de3 commit f4633e2
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 6 deletions.
6 changes: 4 additions & 2 deletions src/Avalonia.Controls/SelectableTextBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,14 @@ protected override TextLayout CreateTextLayout(string? text)
textSource = new FormattedTextSource(text ?? "", defaultProperties, textStyleOverrides);
}

var maxSize = GetMaxSizeFromConstraint();

return new TextLayout(
textSource,
paragraphProperties,
TextTrimming,
_constraint.Width,
_constraint.Height,
maxSize.Width,
maxSize.Height,
MaxLines);
}

Expand Down
15 changes: 12 additions & 3 deletions src/Avalonia.Controls/TextBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public class TextBlock : Control, IInlineHost
nameof(Inlines), t => t.Inlines, (t, v) => t.Inlines = v);

private TextLayout? _textLayout;
protected Size _constraint = Size.Infinity;
protected Size _constraint = new(double.NaN, double.NaN);
protected IReadOnlyList<TextRun>? _textRuns;
private InlineCollection? _inlines;

Expand Down Expand Up @@ -366,6 +366,13 @@ public InlineCollection? Inlines

internal bool HasComplexContent => Inlines != null && Inlines.Count > 0;

private protected Size GetMaxSizeFromConstraint()
{
var maxWidth = double.IsNaN(_constraint.Width) ? 0.0 : _constraint.Width;
var maxHeight = double.IsNaN(_constraint.Height) ? 0.0 : _constraint.Height;
return new Size(maxWidth, maxHeight);
}

/// <summary>
/// The BaselineOffset property provides an adjustment to baseline offset
/// </summary>
Expand Down Expand Up @@ -670,12 +677,14 @@ protected virtual TextLayout CreateTextLayout(string? text)
textSource = new SimpleTextSource(text ?? "", defaultProperties);
}

var maxSize = GetMaxSizeFromConstraint();

return new TextLayout(
textSource,
paragraphProperties,
TextTrimming,
_constraint.Width,
_constraint.Height,
maxSize.Width,
maxSize.Height,
MaxLines);
}

Expand Down
23 changes: 22 additions & 1 deletion tests/Avalonia.Controls.UnitTests/TextBlockTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using Avalonia.Controls.Documents;
using Avalonia.Controls.Templates;
using Avalonia.Data;
Expand Down Expand Up @@ -33,7 +34,9 @@ public void Calling_Measure_Should_Update_TextLayout()
{
var textBlock = new TestTextBlock { Text = "Hello World" };

Assert.Equal(Size.Infinity, textBlock.Constraint);
var constraint = textBlock.Constraint;
Assert.True(double.IsNaN(constraint.Width));
Assert.True(double.IsNaN(constraint.Height));

textBlock.Measure(new Size(100, 100));

Expand Down Expand Up @@ -413,6 +416,24 @@ public void TextBlock_TextLines_Should_Be_Empty()
}
}

[Fact]
public void TextBlock_With_Infinite_Size_Should_Be_Remeasured_After_TextLayout_Created()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);

var target = new TextBlock { Text = "" };
var layout = target.TextLayout;

Assert.Equal(0.0, layout.MaxWidth);
Assert.Equal(0.0, layout.MaxHeight);

target.Text = "foo";
target.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));

Assert.True(target.DesiredSize.Width > 0);
Assert.True(target.DesiredSize.Height > 0);
}

private class TestTextBlock : TextBlock
{
public Size Constraint => _constraint;
Expand Down

0 comments on commit f4633e2

Please sign in to comment.