diff --git a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
index 998198cc1c..0c4f8249ce 100644
--- a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
+++ b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
@@ -163,6 +163,10 @@
+
-
-
+ x:Class="Avalonia.Diagnostics.Views.EventsPageView"
+ Margin="2">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/EventsPageView.xaml.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/EventsPageView.xaml.cs
index c1c78d38f6..687a20c5f6 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/EventsPageView.xaml.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/EventsPageView.xaml.cs
@@ -1,7 +1,14 @@
-using System.Linq;
+using System;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
using Avalonia.Controls;
+using Avalonia.Diagnostics.Models;
using Avalonia.Diagnostics.ViewModels;
+using Avalonia.Input;
+using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
+using Avalonia.Threading;
namespace Avalonia.Diagnostics.Views
{
@@ -12,13 +19,53 @@ namespace Avalonia.Diagnostics.Views
public EventsPageView()
{
InitializeComponent();
- _events = this.FindControl("events");
+ _events = this.FindControl("EventsList");
}
- private void RecordedEvents_CollectionChanged(object sender,
- System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ public void NavigateTo(object sender, TappedEventArgs e)
{
- _events.ScrollIntoView(_events.Items.OfType().LastOrDefault());
+ if (DataContext is EventsPageViewModel vm && sender is Control control)
+ {
+ switch (control.Tag)
+ {
+ case EventChainLink chainLink:
+ {
+ vm.RequestTreeNavigateTo(chainLink);
+ break;
+ }
+ case RoutedEvent evt:
+ {
+ vm.SelectEventByType(evt);
+
+ break;
+ }
+ }
+ }
+ }
+
+ protected override void OnDataContextChanged(EventArgs e)
+ {
+ base.OnDataContextChanged(e);
+
+ if (DataContext is EventsPageViewModel vm)
+ {
+ vm.RecordedEvents.CollectionChanged += OnRecordedEventsChanged;
+ }
+ }
+
+ private void OnRecordedEventsChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (sender is ObservableCollection events)
+ {
+ var evt = events.LastOrDefault();
+
+ if (evt is null)
+ {
+ return;
+ }
+
+ Dispatcher.UIThread.Post(() => _events.ScrollIntoView(evt));
+ }
}
private void InitializeComponent()
diff --git a/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml b/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml
index f83af266c2..b513fd5eae 100644
--- a/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml
@@ -1,44 +1,102 @@
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs b/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs
index 300d61f81d..6533c34ba0 100644
--- a/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs
+++ b/src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs
@@ -422,7 +422,7 @@ namespace Avalonia.Media.TextFormatting
}
else
{
- currentPosition = currentLength + lineBreaker.Current.PositionWrap;
+ currentPosition = currentLength + measuredLength;
}
breakFound = true;
diff --git a/src/Skia/Avalonia.Skia/TextShaperImpl.cs b/src/Skia/Avalonia.Skia/TextShaperImpl.cs
index 31724bfee9..5cf72e2ce8 100644
--- a/src/Skia/Avalonia.Skia/TextShaperImpl.cs
+++ b/src/Skia/Avalonia.Skia/TextShaperImpl.cs
@@ -87,7 +87,7 @@ namespace Avalonia.Skia
{
var nextCodepoint = Codepoint.ReadAt(text, i + 1, out _);
- if (nextCodepoint == '\r' && codepoint == '\n' || nextCodepoint == '\n' && codepoint == '\r')
+ if (nextCodepoint == '\n' && codepoint == '\r')
{
count++;
diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
index 05dd32b84d..97af874238 100644
--- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
+++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
@@ -401,6 +401,24 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal(expectedOffset, textLine.Start);
}
}
+
+ [Fact]
+ public void Should_FormatLine_With_Emergency_Breaks()
+ {
+ using (Start())
+ {
+ var defaultProperties = new GenericTextRunProperties(Typeface.Default);
+ var paragraphProperties = new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.Wrap);
+
+ var textSource = new SingleBufferTextSource("0123456789_0123456789_0123456789_0123456789", defaultProperties);
+ var formatter = new TextFormatterImpl();
+
+ var textLine =
+ formatter.FormatLine(textSource, 0, 33, paragraphProperties);
+
+ Assert.NotNull(textLine.TextLineBreak?.RemainingCharacters);
+ }
+ }
public static IDisposable Start()
{
diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextShaperTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextShaperTests.cs
new file mode 100644
index 0000000000..62d2c54ffe
--- /dev/null
+++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextShaperTests.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Globalization;
+using Avalonia.Media;
+using Avalonia.Media.TextFormatting;
+using Avalonia.UnitTests;
+using Xunit;
+
+namespace Avalonia.Skia.UnitTests.Media.TextFormatting
+{
+ public class TextShaperTests
+ {
+ [Fact]
+ public void Should_Form_Clusters_For_BreakPairs()
+ {
+ using (Start())
+ {
+ var text = "\n\r\n".AsMemory();
+
+ var glyphRun = TextShaper.Current.ShapeText(
+ text,
+ Typeface.Default,
+ 12,
+ CultureInfo.CurrentCulture);
+
+ Assert.Equal(glyphRun.Characters.Length, text.Length);
+ Assert.Equal(glyphRun.GlyphClusters.Length, text.Length);
+ Assert.Equal(0, glyphRun.GlyphClusters[0]);
+ Assert.Equal(1, glyphRun.GlyphClusters[1]);
+ Assert.Equal(1, glyphRun.GlyphClusters[2]);
+ }
+ }
+
+ private static IDisposable Start()
+ {
+ var disposable = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface
+ .With(renderInterface: new PlatformRenderInterface(null),
+ textShaperImpl: new TextShaperImpl(),
+ fontManagerImpl: new CustomFontManagerImpl()));
+
+ return disposable;
+ }
+ }
+}