Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix TextBlock re-measure in infinite container #17638

Merged
merged 4 commits into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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