From 760c6749d0186026607b358e50bf1a3f0a8fbfb2 Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Fri, 23 Feb 2024 08:15:54 +0100 Subject: [PATCH] Recreate TextLayout on measure to make sure constraint is updated (#14705) * Recreate TextLayout on measure to make sure constraint is updated * Add failing test --- src/Avalonia.Controls/TextBlock.cs | 13 +++++++--- .../TextBlockTests.cs | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs index 92f0b18127..acbbb55d02 100644 --- a/src/Avalonia.Controls/TextBlock.cs +++ b/src/Avalonia.Controls/TextBlock.cs @@ -677,7 +677,6 @@ namespace Avalonia.Controls { _textLayout?.Dispose(); _textLayout = null; - _textRuns = null; base.OnMeasureInvalidated(); @@ -690,6 +689,10 @@ namespace Avalonia.Controls _constraint = availableSize.Deflate(padding); + //Reset TextLayout otherwise constraint might be outdated. + _textLayout?.Dispose(); + _textLayout = null; + var inlines = Inlines; if (HasComplexContent) @@ -819,15 +822,19 @@ namespace Avalonia.Controls { oldValue.LogicalChildren = null; oldValue.InlineHost = null; - oldValue.Invalidated -= (s, e) => InvalidateMeasure(); + oldValue.Invalidated -= Invalidated; } if (newValue is not null) { newValue.LogicalChildren = LogicalChildren; newValue.InlineHost = this; - newValue.Invalidated += (s, e) => InvalidateMeasure(); + newValue.Invalidated += Invalidated; } + + return; + + void Invalidated(object? sender, EventArgs e) => InvalidateMeasure(); } void IInlineHost.Invalidate() diff --git a/tests/Avalonia.Controls.UnitTests/TextBlockTests.cs b/tests/Avalonia.Controls.UnitTests/TextBlockTests.cs index 4e1379c5c2..a260757d5f 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBlockTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBlockTests.cs @@ -30,6 +30,27 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(null, textBlock.Text); } + [Fact] + public void Calling_Measure_Should_Update_Constraint_And_TextLayout() + { + using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface)) + { + var textBlock = new TestTextBlock { Text = "Hello World" }; + + textBlock.Measure(new Size(100, 100)); + + var textLayout = textBlock.TextLayout; + + Assert.Equal(new Size(100,100), textBlock.Constraint); + + textBlock.Measure(new Size(50, 100)); + + Assert.Equal(new Size(50, 100), textBlock.Constraint); + + Assert.NotEqual(textLayout, textBlock.TextLayout); + } + } + [Fact] public void Changing_InlinesCollection_Should_Invalidate_Measure() { @@ -328,5 +349,10 @@ namespace Avalonia.Controls.UnitTests Assert.NotEqual(count, count1); } } + + private class TestTextBlock : TextBlock + { + public Size Constraint => _constraint; + } } }