Skip to content

Commit

Permalink
fix: [TextBlock] Prevent Text value overriding when it isn't necessary
Browse files Browse the repository at this point in the history
- Once the Inlines collection is initialized, changes to Text via binding no longer causes the binding to be overridden.
- The inlines text cached on the TextBlock is no longer updated when non-Text properties change on Runs.
- WASM Inlines collections now properly invalidate their owners when changed.
  • Loading branch information
mikernet committed May 19, 2022
1 parent dcb83be commit 3808c00
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 30 deletions.
46 changes: 33 additions & 13 deletions src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public partial class TextBlock : DependencyObject
private string _inlinesText; // Text derived from the content of Inlines
private readonly SerialDisposable _foregroundChanged = new SerialDisposable();

private bool _skipInlinesChangedTextSetter;

#if !UNO_REFERENCE_API
public TextBlock()
Expand Down Expand Up @@ -87,15 +88,29 @@ public InlineCollection Inlines
}
}

internal void InvalidateInlines() => OnInlinesChanged();

private void OnInlinesChanged()
{
Text = _inlinesText = string.Concat(Inlines.Select(InlineExtensions.GetText));
UpdateHyperlinks();
internal void InvalidateInlines(bool updateText)
{
if (updateText)
{
if (Inlines.Count == 1 && Inlines[0] is Run run)
{
_inlinesText = run.Text;
}
else
{
_inlinesText = string.Concat(Inlines.Select(InlineExtensions.GetText));
}

if (!_skipInlinesChangedTextSetter)
{
Text = _inlinesText;
}

UpdateHyperlinks();
}

OnInlinesChangedPartial();
InvalidateTextBlock();
InvalidateTextBlock();
}

partial void OnInlinesChangedPartial();
Expand Down Expand Up @@ -700,16 +715,21 @@ private void UpdateInlines(string text)
}

if (ReadLocalValue(TextProperty) is UnsetValue)
{
Inlines.Clear();
{
_skipInlinesChangedTextSetter = true;
Inlines.Clear();
_skipInlinesChangedTextSetter = false;
ClearTextPartial();
}
else if (text != _inlinesText)
{
// Inlines must be updated
{
// Inlines must be updated
_skipInlinesChangedTextSetter = true;
Inlines.Clear();
ClearTextPartial();
Inlines.Add(new Run { Text = text });
ClearTextPartial();
_skipInlinesChangedTextSetter = true;
Inlines.Add(new Run { Text = text });
_skipInlinesChangedTextSetter = false;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public TextBlock()

private int GetCharacterIndexAtPoint(Point point)
{
throw new NotSupportedException();
return -1; // Not supported yet
}

protected override Size MeasureOverride(Size availableSize)
Expand Down
6 changes: 3 additions & 3 deletions src/Uno.UI/UI/Xaml/Documents/Inline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ namespace Windows.UI.Xaml.Documents
{
public abstract partial class Inline : TextElement
{
internal void InvalidateInlines()
internal void InvalidateInlines(bool updateText)
{
#if !NET461
switch (this.GetParent())
{
case Span span:
span.InvalidateInlines();
span.InvalidateInlines(updateText);
break;
case TextBlock textBlock:
textBlock.InvalidateInlines();
textBlock.InvalidateInlines(updateText);
break;
default:
break;
Expand Down
4 changes: 2 additions & 2 deletions src/Uno.UI/UI/Xaml/Documents/InlineCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ private void OnCollectionChanged()
switch (_collection.GetParent())
{
case TextBlock textBlock:
textBlock.InvalidateInlines();
textBlock.InvalidateInlines(true);
break;
case Inline inline:
inline.InvalidateInlines();
inline.InvalidateInlines(true);
break;
default:
break;
Expand Down
21 changes: 19 additions & 2 deletions src/Uno.UI/UI/Xaml/Documents/InlineCollection.wasm.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using Windows.UI.Xaml.Controls;

Expand All @@ -13,8 +14,24 @@ partial class InlineCollection : IList<Inline>, IEnumerable<Inline>
internal InlineCollection(UIElement containerElement)
{
_collection = new UIElementCollection(containerElement);
}

_collection.CollectionChanged += OnCollectionChanged;
}

private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (_collection.Owner)
{
case TextBlock textBlock:
textBlock.InvalidateInlines(true);
break;
case Inline inline:
inline.InvalidateInlines(true);
break;
default:
break;
}
}

/// <inheritdoc />
public IEnumerator<Inline> GetEnumerator() => _collection.OfType<Inline>().GetEnumerator();

Expand Down
18 changes: 9 additions & 9 deletions src/Uno.UI/UI/Xaml/Documents/Run.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public string Text
public void OnTextChanged()
{
OnTextChangedPartial();
InvalidateInlines();
InvalidateInlines(true);
InvalidateSegmentsPartial();
}

Expand All @@ -44,54 +44,54 @@ public void OnTextChanged()
protected override void OnForegroundChanged()
{
base.OnForegroundChanged();
InvalidateInlines();
InvalidateInlines(false);
}

protected override void OnFontFamilyChanged()
{
base.OnFontFamilyChanged();
InvalidateInlines();
InvalidateInlines(false);
InvalidateSegmentsPartial();
}

protected override void OnFontSizeChanged()
{
base.OnFontSizeChanged();
InvalidateInlines();
InvalidateInlines(false);
InvalidateSegmentsPartial();
}

protected override void OnFontStyleChanged()
{
base.OnFontStyleChanged();
InvalidateInlines();
InvalidateInlines(false);
InvalidateSegmentsPartial();
}

protected override void OnFontWeightChanged()
{
base.OnFontWeightChanged();
InvalidateInlines();
InvalidateInlines(false);
InvalidateSegmentsPartial();
}

protected override void OnBaseLineAlignmentChanged()
{
base.OnBaseLineAlignmentChanged();
InvalidateInlines();
InvalidateInlines(false);
}

protected override void OnCharacterSpacingChanged()
{
base.OnCharacterSpacingChanged();
InvalidateInlines();
InvalidateInlines(false);
InvalidateSegmentsPartial();
}

protected override void OnTextDecorationsChanged()
{
base.OnTextDecorationsChanged();
InvalidateInlines();
InvalidateInlines(false);
}

partial void InvalidateSegmentsPartial();
Expand Down

0 comments on commit 3808c00

Please sign in to comment.