diff --git a/.editorconfig b/.editorconfig
index ff7ac5d69e..3620896f34 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -169,6 +169,8 @@ dotnet_diagnostic.CA1828.severity = warning
dotnet_diagnostic.CA1829.severity = warning
#CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
dotnet_diagnostic.CA1847.severity = warning
+#CACA2211:Non-constant fields should not be visible
+dotnet_diagnostic.CA2211.severity = error
# Wrapping preferences
csharp_wrap_before_ternary_opsigns = false
diff --git a/Directory.Build.props b/Directory.Build.props
index 42daa2df7f..c19a55e8ea 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -7,5 +7,6 @@
false
false
False
+ 11
diff --git a/NOTICE.md b/NOTICE.md
index e97fc654c9..bd26b65d70 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -303,3 +303,34 @@ https://github.com/chromium/chromium
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Flutter
+
+https://github.com/flutter/flutter
+
+//Copyright 2014 The Flutter Authors. All rights reserved.
+
+//Redistribution and use in source and binary forms, with or without modification,
+//are permitted provided that the following conditions are met:
+
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+//ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//LOSS OF USE, DATA, OR PROFITS;
+//OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/azure-pipelines-integrationtests.yml b/azure-pipelines-integrationtests.yml
index 43253ac6be..5735da19ab 100644
--- a/azure-pipelines-integrationtests.yml
+++ b/azure-pipelines-integrationtests.yml
@@ -13,14 +13,14 @@ jobs:
steps:
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 6.0.401'
+ displayName: 'Use .NET Core SDK 6.0.404'
inputs:
- version: 6.0.401
+ version: 6.0.404
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0.100'
+ displayName: 'Use .NET Core SDK 7.0.101'
inputs:
- version: 7.0.100
+ version: 7.0.101
- script: system_profiler SPDisplaysDataType |grep Resolution
@@ -51,14 +51,14 @@ jobs:
steps:
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 6.0.401'
+ displayName: 'Use .NET Core SDK 6.0.404'
inputs:
- version: 6.0.401
+ version: 6.0.404
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0.100'
+ displayName: 'Use .NET Core SDK 7.0.101'
inputs:
- version: 7.0.100
+ version: 7.0.101
- task: Windows Application Driver@0
inputs:
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index a3bbc33418..8bab6e68e2 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -30,14 +30,14 @@ jobs:
vmImage: 'ubuntu-20.04'
steps:
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 6.0.401'
+ displayName: 'Use .NET Core SDK 6.0.404'
inputs:
- version: 6.0.401
+ version: 6.0.404
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0'
+ displayName: 'Use .NET Core SDK 7.0.101'
inputs:
- version: 7.0.100
+ version: 7.0.101
- task: CmdLine@2
displayName: 'Install Workloads'
@@ -67,14 +67,14 @@ jobs:
vmImage: 'macos-12'
steps:
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 6.0.401'
+ displayName: 'Use .NET Core SDK 6.0.404'
inputs:
- version: 6.0.401
+ version: 6.0.404
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0.100'
+ displayName: 'Use .NET Core SDK 7.0.101'
inputs:
- version: 7.0.100
+ version: 7.0.101
- task: CmdLine@2
displayName: 'Install Workloads'
@@ -138,14 +138,14 @@ jobs:
SolutionDir: '$(Build.SourcesDirectory)'
steps:
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 6.0.401'
+ displayName: 'Use .NET Core SDK 6.0.404'
inputs:
- version: 6.0.401
+ version: 6.0.404
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0.100'
+ displayName: 'Use .NET Core SDK 7.0.101'
inputs:
- version: 7.0.100
+ version: 7.0.101
- task: CmdLine@2
displayName: 'Install Workloads'
diff --git a/build/Base.props b/build/Base.props
index 588da8433a..26f19e3abc 100644
--- a/build/Base.props
+++ b/build/Base.props
@@ -1,5 +1,5 @@
-
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index e9c3d65b41..eca3ba37b0 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -8,7 +8,6 @@
https://github.com/AvaloniaUI/Avalonia/
true
$(NoWarn);CS1591
- preview
MIT
Icon.png
Avalonia is a cross-platform UI framework for .NET providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, macOS and with experimental support for Android, iOS and WebAssembly.
diff --git a/build/System.Memory.props b/build/System.Memory.props
index b36998a780..a413e18927 100644
--- a/build/System.Memory.props
+++ b/build/System.Memory.props
@@ -1,5 +1,5 @@
-
+
diff --git a/global.json b/global.json
index a9318b212f..e4a0cc20c2 100644
--- a/global.json
+++ b/global.json
@@ -1,11 +1,9 @@
{
"sdk": {
- "version": "7.0.100",
+ "version": "7.0.101",
"rollForward": "latestFeature"
},
"msbuild-sdks": {
- "Microsoft.Build.Traversal": "1.0.43",
- "MSBuild.Sdk.Extras": "3.0.22",
- "AggregatePackage.NuGet.Sdk" : "0.1.12"
+ "Microsoft.Build.Traversal": "1.0.43"
}
}
diff --git a/samples/ControlCatalog.Android/MainActivity.cs b/samples/ControlCatalog.Android/MainActivity.cs
index 62c582610c..f6fa07dbde 100644
--- a/samples/ControlCatalog.Android/MainActivity.cs
+++ b/samples/ControlCatalog.Android/MainActivity.cs
@@ -5,7 +5,7 @@ using Avalonia.Android;
namespace ControlCatalog.Android
{
- [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
+ [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.Main", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
public class MainActivity : AvaloniaMainActivity
{
}
diff --git a/samples/ControlCatalog.Android/Resources/values/styles.xml b/samples/ControlCatalog.Android/Resources/values/styles.xml
index 2759d2904a..49e079a719 100644
--- a/samples/ControlCatalog.Android/Resources/values/styles.xml
+++ b/samples/ControlCatalog.Android/Resources/values/styles.xml
@@ -14,4 +14,8 @@
- @null
+
+
diff --git a/samples/ControlCatalog.Android/SplashActivity.cs b/samples/ControlCatalog.Android/SplashActivity.cs
index 908b5f082a..a0b68b129b 100644
--- a/samples/ControlCatalog.Android/SplashActivity.cs
+++ b/samples/ControlCatalog.Android/SplashActivity.cs
@@ -28,6 +28,8 @@ namespace ControlCatalog.Android
base.OnResume();
StartActivity(new Intent(Application.Context, typeof(MainActivity)));
+
+ Finish();
}
}
}
diff --git a/samples/ControlCatalog.Browser/Properties/launchSettings.json b/samples/ControlCatalog.Browser/Properties/launchSettings.json
new file mode 100644
index 0000000000..76c1834e3c
--- /dev/null
+++ b/samples/ControlCatalog.Browser/Properties/launchSettings.json
@@ -0,0 +1,13 @@
+{
+ "profiles": {
+ "ControlCatalog.Browser": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/debug?browser={browserInspectUri}"
+ }
+ }
+}
diff --git a/samples/ControlCatalog.Desktop/Program.cs b/samples/ControlCatalog.Desktop/Program.cs
index 7b8b27fff7..4d28f15e2c 100644
--- a/samples/ControlCatalog.Desktop/Program.cs
+++ b/samples/ControlCatalog.Desktop/Program.cs
@@ -23,7 +23,7 @@ namespace ControlCatalog
private static void ConfigureAssetAssembly(AppBuilder builder)
{
AvaloniaLocator.CurrentMutable
- .GetService()
+ .GetRequiredService()
.SetDefaultAssembly(typeof(App).Assembly);
}
}
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index 9e0fb3f852..166b98436e 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -209,8 +209,7 @@
+ HorizontalAlignment="Stretch">
None
Transparent
diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs
index 15e666ae7b..f3c1a68e72 100644
--- a/samples/ControlCatalog/MainView.xaml.cs
+++ b/samples/ControlCatalog/MainView.xaml.cs
@@ -6,6 +6,7 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Immutable;
+using Avalonia.VisualTree;
using ControlCatalog.Models;
using ControlCatalog.Pages;
@@ -59,17 +60,25 @@ namespace ControlCatalog
};
var transparencyLevels = this.Get("TransparencyLevels");
- IDisposable? backgroundSetter = null, paneBackgroundSetter = null;
+ IDisposable? topLevelBackgroundSideSetter = null, sideBarBackgroundSetter = null, paneBackgroundSetter = null;
transparencyLevels.SelectionChanged += (sender, e) =>
{
- backgroundSetter?.Dispose();
+ topLevelBackgroundSideSetter?.Dispose();
+ sideBarBackgroundSetter?.Dispose();
paneBackgroundSetter?.Dispose();
- if (transparencyLevels.SelectedItem is WindowTransparencyLevel selected
- && selected != WindowTransparencyLevel.None)
+ if (transparencyLevels.SelectedItem is WindowTransparencyLevel selected)
{
- var semiTransparentBrush = new ImmutableSolidColorBrush(Colors.Gray, 0.5);
- backgroundSetter = sideBar.SetValue(BackgroundProperty, semiTransparentBrush, Avalonia.Data.BindingPriority.Style);
- paneBackgroundSetter = sideBar.SetValue(SplitView.PaneBackgroundProperty, semiTransparentBrush, Avalonia.Data.BindingPriority.Style);
+ var topLevel = (TopLevel)this.GetVisualRoot()!;
+ topLevel.TransparencyLevelHint = selected;
+
+ if (selected != WindowTransparencyLevel.None)
+ {
+ var transparentBrush = new ImmutableSolidColorBrush(Colors.White, 0);
+ var semiTransparentBrush = new ImmutableSolidColorBrush(Colors.Gray, 0.2);
+ topLevelBackgroundSideSetter = topLevel.SetValue(BackgroundProperty, transparentBrush, Avalonia.Data.BindingPriority.Style);
+ sideBarBackgroundSetter = sideBar.SetValue(BackgroundProperty, semiTransparentBrush, Avalonia.Data.BindingPriority.Style);
+ paneBackgroundSetter = sideBar.SetValue(SplitView.PaneBackgroundProperty, semiTransparentBrush, Avalonia.Data.BindingPriority.Style);
+ }
}
};
}
diff --git a/samples/ControlCatalog/MainWindow.xaml b/samples/ControlCatalog/MainWindow.xaml
index cebb3e0916..442c1d37b0 100644
--- a/samples/ControlCatalog/MainWindow.xaml
+++ b/samples/ControlCatalog/MainWindow.xaml
@@ -10,7 +10,6 @@
ExtendClientAreaToDecorationsHint="{Binding ExtendClientAreaEnabled}"
ExtendClientAreaChromeHints="{Binding ChromeHints}"
ExtendClientAreaTitleBarHeightHint="{Binding TitleBarHeight}"
- TransparencyLevelHint="{Binding TransparencyLevel}"
x:Name="MainWindow"
Background="Transparent"
x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}"
diff --git a/samples/ControlCatalog/Pages/DateTimePickerPage.xaml.cs b/samples/ControlCatalog/Pages/DateTimePickerPage.xaml.cs
index 11f504f4db..7520dabf37 100644
--- a/samples/ControlCatalog/Pages/DateTimePickerPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/DateTimePickerPage.xaml.cs
@@ -17,7 +17,7 @@ namespace ControlCatalog.Pages
this.Get("TimePickerDesc").Text = "Use a TimePicker to let users set a time in your app, for example " +
"to set a reminder. The TimePicker displays three controls for hour, minute, and AM / PM(if necessary).These controls " +
"are easy to use with touch or mouse, and they can be styled and configured in several different ways. " +
- "12 - hour or 24 - hour clock and visiblility of AM / PM is dynamically set based on user time settings, or can be overridden.";
+ "12 - hour or 24 - hour clock and visibility of AM / PM is dynamically set based on user time settings, or can be overridden.";
}
diff --git a/samples/ControlCatalog/Pages/PointerCanvas.cs b/samples/ControlCatalog/Pages/PointerCanvas.cs
index 7d26da8603..da1ff5442d 100644
--- a/samples/ControlCatalog/Pages/PointerCanvas.cs
+++ b/samples/ControlCatalog/Pages/PointerCanvas.cs
@@ -24,7 +24,7 @@ public class PointerCanvas : Control
{
struct CanvasPoint
{
- public IBrush Brush;
+ public IBrush? Brush;
public Point Point;
public double Radius;
public double? Pressure;
diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs
index 6af4cf353e..b5b80fb147 100644
--- a/samples/ControlCatalog/Pages/ScreenPage.cs
+++ b/samples/ControlCatalog/Pages/ScreenPage.cs
@@ -36,44 +36,44 @@ namespace ControlCatalog.Pages
var drawBrush = Brushes.Black;
Pen p = new Pen(drawBrush);
- if (screens != null)
- foreach (Screen screen in screens)
+
+ foreach (Screen screen in screens)
+ {
+ if (screen.Bounds.X / 10f < _leftMost)
{
- if (screen.Bounds.X / 10f < _leftMost)
- {
- _leftMost = screen.Bounds.X / 10f;
- Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
- return;
- }
+ _leftMost = screen.Bounds.X / 10f;
+ Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
+ return;
+ }
- Rect boundsRect = new Rect(screen.Bounds.X / 10f + Math.Abs(_leftMost), screen.Bounds.Y / 10f, screen.Bounds.Width / 10f,
- screen.Bounds.Height / 10f);
- Rect workingAreaRect = new Rect(screen.WorkingArea.X / 10f + Math.Abs(_leftMost), screen.WorkingArea.Y / 10f, screen.WorkingArea.Width / 10f,
- screen.WorkingArea.Height / 10f);
-
- context.DrawRectangle(p, boundsRect);
- context.DrawRectangle(p, workingAreaRect);
+ Rect boundsRect = new Rect(screen.Bounds.X / 10f + Math.Abs(_leftMost), screen.Bounds.Y / 10f, screen.Bounds.Width / 10f,
+ screen.Bounds.Height / 10f);
+ Rect workingAreaRect = new Rect(screen.WorkingArea.X / 10f + Math.Abs(_leftMost), screen.WorkingArea.Y / 10f, screen.WorkingArea.Width / 10f,
+ screen.WorkingArea.Height / 10f);
+ context.DrawRectangle(p, boundsRect);
+ context.DrawRectangle(p, workingAreaRect);
- var formattedText = CreateFormattedText($"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}");
- context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height));
- formattedText =
- CreateFormattedText($"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}");
- context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 20));
+ var formattedText = CreateFormattedText($"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height));
- formattedText = CreateFormattedText($"Scaling: {screen.Scaling * 100}%");
- context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40));
+ formattedText =
+ CreateFormattedText($"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 20));
- formattedText = CreateFormattedText($"IsPrimary: {screen.IsPrimary}");
+ formattedText = CreateFormattedText($"Scaling: {screen.Scaling * 100}%");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40));
- context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 60));
+ formattedText = CreateFormattedText($"IsPrimary: {screen.IsPrimary}");
- formattedText =
- CreateFormattedText(
- $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}");
- context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 80));
- }
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 60));
+
+ formattedText =
+ CreateFormattedText(
+ $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 80));
+ }
context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10f, w.Bounds.Width / 10, w.Bounds.Height / 10));
}
diff --git a/samples/ControlCatalog/Pages/TabControlPage.xaml.cs b/samples/ControlCatalog/Pages/TabControlPage.xaml.cs
index 413b6e1c75..f3f4bf6e93 100644
--- a/samples/ControlCatalog/Pages/TabControlPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/TabControlPage.xaml.cs
@@ -51,7 +51,7 @@ namespace ControlCatalog.Pages
private static IBitmap LoadBitmap(string uri)
{
- var assets = AvaloniaLocator.Current!.GetService()!;
+ var assets = AvaloniaLocator.Current.GetRequiredService();
return new Bitmap(assets.Open(new Uri(uri)));
}
}
diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml
index 6a4d9b7d0e..7408399873 100644
--- a/samples/ControlCatalog/Pages/TextBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml
@@ -38,7 +38,7 @@
UseFloatingWatermark="True"
PasswordChar="*"
Text="Password" />
-
+
-
- None
- Transparent
- Blur
- AcrylicBlur
- Mica
-
diff --git a/samples/ControlCatalog/ViewModels/ContextPageViewModel.cs b/samples/ControlCatalog/ViewModels/ContextPageViewModel.cs
index 4cfb00625e..4a5462a58b 100644
--- a/samples/ControlCatalog/ViewModels/ContextPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/ContextPageViewModel.cs
@@ -56,12 +56,9 @@ namespace ControlCatalog.ViewModels
var result = await window.StorageProvider.OpenFilePickerAsync(new Avalonia.Platform.Storage.FilePickerOpenOptions() { AllowMultiple = true });
- if (result != null)
+ foreach (var file in result)
{
- foreach (var file in result)
- {
- System.Diagnostics.Debug.WriteLine($"Opened: {file.Name}");
- }
+ System.Diagnostics.Debug.WriteLine($"Opened: {file.Name}");
}
}
diff --git a/samples/ControlCatalog/ViewModels/CursorPageViewModel.cs b/samples/ControlCatalog/ViewModels/CursorPageViewModel.cs
index 8a3f0ba947..f44d927801 100644
--- a/samples/ControlCatalog/ViewModels/CursorPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/CursorPageViewModel.cs
@@ -18,7 +18,7 @@ namespace ControlCatalog.ViewModels
.Select(x => new StandardCursorModel(x))
.ToList();
- var loader = AvaloniaLocator.Current!.GetService()!;
+ var loader = AvaloniaLocator.Current.GetRequiredService();
var s = loader.Open(new Uri("avares://ControlCatalog/Assets/avalonia-32.png"));
var bitmap = new Bitmap(s);
CustomCursor = new Cursor(bitmap, new PixelPoint(16, 16));
diff --git a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
index b79eff780c..47c6f70714 100644
--- a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
@@ -12,12 +12,9 @@ namespace ControlCatalog.ViewModels
{
class MainWindowViewModel : ViewModelBase
{
- private IManagedNotificationManager _notificationManager;
-
private bool _isMenuItemChecked = true;
private WindowState _windowState;
private WindowState[] _windowStates = Array.Empty();
- private int _transparencyLevel;
private ExtendClientAreaChromeHints _chromeHints = ExtendClientAreaChromeHints.PreferSystemChrome;
private bool _extendClientAreaEnabled;
private bool _systemTitleBarEnabled;
@@ -77,12 +74,6 @@ namespace ControlCatalog.ViewModels
TitleBarHeight = -1;
}
- public int TransparencyLevel
- {
- get { return _transparencyLevel; }
- set { this.RaiseAndSetIfChanged(ref _transparencyLevel, value); }
- }
-
public ExtendClientAreaChromeHints ChromeHints
{
get { return _chromeHints; }
diff --git a/samples/ControlCatalog/ViewModels/TransitioningContentControlPageViewModel.cs b/samples/ControlCatalog/ViewModels/TransitioningContentControlPageViewModel.cs
index 93857fd899..4505c11e95 100644
--- a/samples/ControlCatalog/ViewModels/TransitioningContentControlPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/TransitioningContentControlPageViewModel.cs
@@ -19,7 +19,7 @@ namespace ControlCatalog.ViewModels
{
public TransitioningContentControlPageViewModel()
{
- var assetLoader = AvaloniaLocator.Current?.GetService()!;
+ var assetLoader = AvaloniaLocator.Current.GetRequiredService();
var images = new string[]
{
diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props
index 471c42ec07..3b14f0ce12 100644
--- a/samples/Directory.Build.props
+++ b/samples/Directory.Build.props
@@ -2,9 +2,8 @@
false
$(MSBuildThisFileDirectory)..\src\tools\Avalonia.Designer.HostApp\bin\Debug\netcoreapp2.0\Avalonia.Designer.HostApp.dll
+ false
+ 11
-
- false
-
diff --git a/src/Android/Avalonia.Android/AvaloniaSplashActivity.cs b/src/Android/Avalonia.Android/AvaloniaSplashActivity.cs
index ec26ee5599..38038ef26c 100644
--- a/src/Android/Avalonia.Android/AvaloniaSplashActivity.cs
+++ b/src/Android/Avalonia.Android/AvaloniaSplashActivity.cs
@@ -1,6 +1,5 @@
using Android.OS;
using AndroidX.AppCompat.App;
-using Avalonia.Controls;
namespace Avalonia.Android
{
@@ -8,15 +7,22 @@ namespace Avalonia.Android
{
protected abstract AppBuilder CreateAppBuilder();
+ private static AppBuilder s_appBuilder;
+
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
- var builder = CreateAppBuilder();
+ if (s_appBuilder == null)
+ {
+ var builder = CreateAppBuilder();
+
+ var lifetime = new SingleViewLifetime();
- var lifetime = new SingleViewLifetime();
+ builder.SetupWithLifetime(lifetime);
- builder.SetupWithLifetime(lifetime);
+ s_appBuilder = builder;
+ }
}
}
diff --git a/src/Android/Avalonia.Android/AvaloniaView.cs b/src/Android/Avalonia.Android/AvaloniaView.cs
index 5267843bfc..f7e32f99db 100644
--- a/src/Android/Avalonia.Android/AvaloniaView.cs
+++ b/src/Android/Avalonia.Android/AvaloniaView.cs
@@ -24,6 +24,8 @@ namespace Avalonia.Android
_root = new EmbeddableControlRoot(_view);
_root.Prepare();
+
+ this.SetBackgroundColor(global::Android.Graphics.Color.Transparent);
}
internal TopLevelImpl TopLevelImpl => _view;
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
index 33501ece06..f205458f0e 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
@@ -22,6 +22,7 @@ namespace Avalonia.Android
public InvalidationAwareSurfaceView(Context context) : base(context)
{
Holder.AddCallback(this);
+ Holder.SetFormat(global::Android.Graphics.Format.Transparent);
_handler = new Handler(context.MainLooper);
}
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
index 56dbadca03..1aac567dda 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
@@ -26,6 +26,7 @@ using Avalonia.Rendering.Composition;
using Java.Lang;
using Math = System.Math;
using AndroidRect = Android.Graphics.Rect;
+using Android.Graphics.Drawables;
namespace Avalonia.Android.Platform.SkiaPlatform
{
@@ -283,7 +284,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public Action LostFocus { get; set; }
public Action TransparencyLevelChanged { get; set; }
- public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None;
+ public WindowTransparencyLevel TransparencyLevel { get; private set; }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => new AcrylicPlatformCompensationLevels(1, 1, 1);
@@ -301,7 +302,87 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel)
{
- throw new NotImplementedException();
+ if (TransparencyLevel != transparencyLevel)
+ {
+ bool isBelowR = Build.VERSION.SdkInt < BuildVersionCodes.R;
+ bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R;
+ if (_view.Context is AvaloniaMainActivity activity)
+ {
+ switch (transparencyLevel)
+ {
+ case WindowTransparencyLevel.AcrylicBlur:
+ case WindowTransparencyLevel.ForceAcrylicBlur:
+ case WindowTransparencyLevel.Mica:
+ case WindowTransparencyLevel.None:
+ if (!isBelowR)
+ {
+ activity.SetTranslucent(false);
+ }
+ if (isAboveR)
+ {
+ activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
+
+ var attr = activity.Window?.Attributes;
+ if (attr != null)
+ {
+ attr.BlurBehindRadius = 0;
+
+ activity.Window.Attributes = attr;
+ }
+ }
+ activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White));
+
+ if(transparencyLevel != WindowTransparencyLevel.None)
+ {
+ return;
+ }
+ break;
+ case WindowTransparencyLevel.Transparent:
+ if (!isBelowR)
+ {
+ activity.SetTranslucent(true);
+ }
+ if (isAboveR)
+ {
+ activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
+
+ var attr = activity.Window?.Attributes;
+ if (attr != null)
+ {
+ attr.BlurBehindRadius = 0;
+
+ activity.Window.Attributes = attr;
+ }
+ }
+ activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
+ break;
+ case WindowTransparencyLevel.Blur:
+ if (isAboveR)
+ {
+ activity.SetTranslucent(true);
+ activity.Window?.AddFlags(WindowManagerFlags.BlurBehind);
+
+ var attr = activity.Window?.Attributes;
+ if (attr != null)
+ {
+ attr.BlurBehindRadius = 120;
+
+ activity.Window.Attributes = attr;
+ }
+ activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
+ }
+ else
+ {
+ activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
+ activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White));
+
+ return;
+ }
+ break;
+ }
+ TransparencyLevel = transparencyLevel;
+ }
+ }
}
}
diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs
index 6d0e6be0ad..3d0f3b2652 100644
--- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs
+++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs
@@ -38,7 +38,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers
return null;
}
- var eventTime = (ulong)DateTime.Now.Millisecond;
+ var eventTime = (ulong)e.EventTime;
var inputRoot = _view.InputRoot;
var actionMasked = e.ActionMasked;
var modifiers = GetModifiers(e.MetaState, e.ButtonState);
diff --git a/src/Avalonia.Base/Controls/NameScopeExtensions.cs b/src/Avalonia.Base/Controls/NameScopeExtensions.cs
index 3895b6ceb9..0abd5e56f7 100644
--- a/src/Avalonia.Base/Controls/NameScopeExtensions.cs
+++ b/src/Avalonia.Base/Controls/NameScopeExtensions.cs
@@ -25,13 +25,18 @@ namespace Avalonia.Controls
var result = nameScope.Find(name);
- if (result != null && !(result is T))
+ if (result == null)
{
- throw new InvalidOperationException(
- $"Expected control '{name}' to be '{typeof(T)} but it was '{result.GetType()}'.");
+ return null;
}
- return (T?)result;
+ if (result is T typed)
+ {
+ return typed;
+ }
+
+ throw new InvalidOperationException(
+ $"Expected control '{name}' to be '{typeof(T)} but it was '{result.GetType()}'.");
}
///
@@ -74,13 +79,13 @@ namespace Avalonia.Controls
throw new KeyNotFoundException($"Could not find control '{name}'.");
}
- if (!(result is T))
+ if (result is T typed)
{
- throw new InvalidOperationException(
- $"Expected control '{name}' to be '{typeof(T)} but it was '{result.GetType()}'.");
+ return typed;
}
- return (T)result;
+ throw new InvalidOperationException(
+ $"Expected control '{name}' to be '{typeof(T)} but it was '{result.GetType()}'.");
}
///
diff --git a/src/Avalonia.Base/Data/Converters/FuncMultiValueConverter.cs b/src/Avalonia.Base/Data/Converters/FuncMultiValueConverter.cs
index 2577cac743..5084d8e822 100644
--- a/src/Avalonia.Base/Data/Converters/FuncMultiValueConverter.cs
+++ b/src/Avalonia.Base/Data/Converters/FuncMultiValueConverter.cs
@@ -38,7 +38,7 @@ namespace Avalonia.Data.Converters
}
else if (Equals(obj, default(TIn)))
{
- yield return default(TIn);
+ yield return default;
}
}
}
diff --git a/src/Avalonia.Base/Input/Cursor.cs b/src/Avalonia.Base/Input/Cursor.cs
index 8e79206f93..c555087879 100644
--- a/src/Avalonia.Base/Input/Cursor.cs
+++ b/src/Avalonia.Base/Input/Cursor.cs
@@ -71,8 +71,7 @@ namespace Avalonia.Input
private static ICursorFactory GetCursorFactory()
{
- return AvaloniaLocator.Current.GetService() ??
- throw new Exception("Could not create Cursor: ICursorFactory not registered.");
+ return AvaloniaLocator.Current.GetRequiredService();
}
}
}
diff --git a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs
index 64fe275547..cec98ec66b 100644
--- a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs
+++ b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs
@@ -17,7 +17,9 @@ namespace Avalonia.Input.GestureRecognizers
private bool _canVerticallyScroll;
private int _gestureId;
private int _scrollStartDistance = 30;
-
+ private Point _pointerPressedPoint;
+ private VelocityTracker? _velocityTracker;
+
// Movement per second
private Vector _inertia;
private ulong? _lastMoveTimestamp;
@@ -91,7 +93,7 @@ namespace Avalonia.Input.GestureRecognizers
EndGesture();
_tracking = e.Pointer;
_gestureId = ScrollGestureEventArgs.GetNextFreeId();
- _trackedRootPoint = e.GetPosition((Visual?)_target);
+ _trackedRootPoint = _pointerPressedPoint = e.GetPosition((Visual?)_target);
}
}
@@ -111,6 +113,13 @@ namespace Avalonia.Input.GestureRecognizers
_scrolling = true;
if (_scrolling)
{
+ _velocityTracker = new VelocityTracker();
+
+ // Correct _trackedRootPoint with ScrollStartDistance, so scrolling does not start with a skip of ScrollStartDistance
+ _trackedRootPoint = new Point(
+ _trackedRootPoint.X - (_trackedRootPoint.X >= rootPoint.X ? _scrollStartDistance : -_scrollStartDistance),
+ _trackedRootPoint.Y - (_trackedRootPoint.Y >= rootPoint.Y ? _scrollStartDistance : -_scrollStartDistance));
+
_actions!.Capture(e.Pointer, this);
}
}
@@ -118,14 +127,11 @@ namespace Avalonia.Input.GestureRecognizers
if (_scrolling)
{
var vector = _trackedRootPoint - rootPoint;
- var elapsed = _lastMoveTimestamp.HasValue && _lastMoveTimestamp < e.Timestamp ?
- TimeSpan.FromMilliseconds(e.Timestamp - _lastMoveTimestamp.Value) :
- TimeSpan.Zero;
-
+
+ _velocityTracker?.AddPosition(TimeSpan.FromMilliseconds(e.Timestamp), _pointerPressedPoint - rootPoint);
+
_lastMoveTimestamp = e.Timestamp;
_trackedRootPoint = rootPoint;
- if (elapsed.TotalSeconds > 0)
- _inertia = vector / elapsed.TotalSeconds;
_target!.RaiseEvent(new ScrollGestureEventArgs(_gestureId, vector));
e.Handled = true;
}
@@ -150,12 +156,14 @@ namespace Avalonia.Input.GestureRecognizers
}
}
-
-
+
+
public void PointerReleased(PointerReleasedEventArgs e)
{
if (e.Pointer == _tracking && _scrolling)
{
+ _inertia = _velocityTracker?.GetFlingVelocity().PixelsPerSecond ?? Vector.Zero;
+
e.Handled = true;
if (_inertia == default
|| e.Timestamp == 0
@@ -183,9 +191,18 @@ namespace Avalonia.Input.GestureRecognizers
var distance = speed * elapsedSinceLastTick.TotalSeconds;
_target!.RaiseEvent(new ScrollGestureEventArgs(_gestureId, distance));
-
-
- if (Math.Abs(speed.X) < InertialScrollSpeedEnd || Math.Abs(speed.Y) <= InertialScrollSpeedEnd)
+ // EndGesture using InertialScrollSpeedEnd only in the direction of scrolling
+ if (CanVerticallyScroll && CanHorizontallyScroll && Math.Abs(speed.X) < InertialScrollSpeedEnd && Math.Abs(speed.Y) <= InertialScrollSpeedEnd)
+ {
+ EndGesture();
+ return false;
+ }
+ else if (CanVerticallyScroll && Math.Abs(speed.Y) <= InertialScrollSpeedEnd)
+ {
+ EndGesture();
+ return false;
+ }
+ else if (CanHorizontallyScroll && Math.Abs(speed.X) < InertialScrollSpeedEnd)
{
EndGesture();
return false;
diff --git a/src/Avalonia.Base/Input/GestureRecognizers/VelocityTracker.cs b/src/Avalonia.Base/Input/GestureRecognizers/VelocityTracker.cs
new file mode 100644
index 0000000000..ce41aa6308
--- /dev/null
+++ b/src/Avalonia.Base/Input/GestureRecognizers/VelocityTracker.cs
@@ -0,0 +1,375 @@
+// Code in this file is derived from
+// https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/gestures/velocity_tracker.dart
+
+using System;
+using System.Diagnostics;
+using Avalonia.Utilities;
+
+namespace Avalonia.Input.GestureRecognizers
+{
+ // Possible enhancement: add Flutter's 'IOSScrollViewFlingVelocityTracker' and 'MacOSScrollViewFlingVelocityTracker'?
+
+ internal readonly record struct Velocity(Vector PixelsPerSecond)
+ {
+ public Velocity ClampMagnitude(double minValue, double maxValue)
+ {
+ Debug.Assert(minValue >= 0.0);
+ Debug.Assert(maxValue >= 0.0 && maxValue >= minValue);
+ double valueSquared = PixelsPerSecond.SquaredLength;
+ if (valueSquared > maxValue * maxValue)
+ {
+ double length = PixelsPerSecond.Length;
+ return new Velocity(length != 0.0 ? (PixelsPerSecond / length) * maxValue : Vector.Zero);
+ // preventing double.NaN in Vector PixelsPerSecond is important -- if a NaN eventually gets into a
+ // ScrollGestureEventArgs it results in runtime errors.
+ }
+ if (valueSquared < minValue * minValue)
+ {
+ double length = PixelsPerSecond.Length;
+ return new Velocity(length != 0.0 ? (PixelsPerSecond / length) * minValue : Vector.Zero);
+ }
+ return this;
+ }
+ }
+
+ /// A two dimensional velocity estimate.
+ ///
+ /// VelocityEstimates are computed by [VelocityTracker.getVelocityEstimate]. An
+ /// estimate's [confidence] measures how well the velocity tracker's position
+ /// data fit a straight line, [duration] is the time that elapsed between the
+ /// first and last position sample used to compute the velocity, and [offset]
+ /// is similarly the difference between the first and last positions.
+ ///
+ /// See also:
+ ///
+ /// * [VelocityTracker], which computes [VelocityEstimate]s.
+ /// * [Velocity], which encapsulates (just) a velocity vector and provides some
+ /// useful velocity operations.
+ internal record VelocityEstimate(Vector PixelsPerSecond, double Confidence, TimeSpan Duration, Vector Offset);
+
+ internal record struct PointAtTime(bool Valid, Vector Point, TimeSpan Time);
+
+ /// Computes a pointer's velocity based on data from [PointerMoveEvent]s.
+ ///
+ /// The input data is provided by calling [addPosition]. Adding data is cheap.
+ ///
+ /// To obtain a velocity, call [getVelocity] or [getVelocityEstimate]. This will
+ /// compute the velocity based on the data added so far. Only call these when
+ /// you need to use the velocity, as they are comparatively expensive.
+ ///
+ /// The quality of the velocity estimation will be better if more data points
+ /// have been received.
+ internal class VelocityTracker
+ {
+ private const int AssumePointerMoveStoppedMilliseconds = 40;
+ private const int HistorySize = 20;
+ private const int HorizonMilliseconds = 100;
+ private const int MinSampleSize = 3;
+ private const double MinFlingVelocity = 50.0; // Logical pixels / second
+ private const double MaxFlingVelocity = 8000.0;
+
+ private readonly PointAtTime[] _samples = new PointAtTime[HistorySize];
+ private int _index = 0;
+
+ ///
+ /// Adds a position as the given time to the tracker.
+ ///
+ ///
+ ///
+ public void AddPosition(TimeSpan time, Vector position)
+ {
+ _index++;
+ if (_index == HistorySize)
+ {
+ _index = 0;
+ }
+ _samples[_index] = new PointAtTime(true, position, time);
+ }
+
+ /// Returns an estimate of the velocity of the object being tracked by the
+ /// tracker given the current information available to the tracker.
+ ///
+ /// Information is added using [addPosition].
+ ///
+ /// Returns null if there is no data on which to base an estimate.
+ protected virtual VelocityEstimate? GetVelocityEstimate()
+ {
+ Span x = stackalloc double[HistorySize];
+ Span y = stackalloc double[HistorySize];
+ Span w = stackalloc double[HistorySize];
+ Span time = stackalloc double[HistorySize];
+ int sampleCount = 0;
+ int index = _index;
+
+ var newestSample = _samples[index];
+ if (!newestSample.Valid)
+ {
+ return null;
+ }
+
+ var previousSample = newestSample;
+ var oldestSample = newestSample;
+
+ // Starting with the most recent PointAtTime sample, iterate backwards while
+ // the samples represent continuous motion.
+ do
+ {
+ var sample = _samples[index];
+ if (!sample.Valid)
+ {
+ break;
+ }
+
+ double age = (newestSample.Time - sample.Time).TotalMilliseconds;
+ double delta = Math.Abs((sample.Time - previousSample.Time).TotalMilliseconds);
+ previousSample = sample;
+ if (age > HorizonMilliseconds || delta > AssumePointerMoveStoppedMilliseconds)
+ {
+ break;
+ }
+
+ oldestSample = sample;
+ var position = sample.Point;
+ x[sampleCount] = position.X;
+ y[sampleCount] = position.Y;
+ w[sampleCount] = 1.0;
+ time[sampleCount] = -age;
+ index = (index == 0 ? HistorySize : index) - 1;
+
+ sampleCount++;
+ } while (sampleCount < HistorySize);
+
+ if (sampleCount >= MinSampleSize)
+ {
+ var xFit = LeastSquaresSolver.Solve(2, time.Slice(0, sampleCount), x.Slice(0, sampleCount), w.Slice(0, sampleCount));
+ if (xFit != null)
+ {
+ var yFit = LeastSquaresSolver.Solve(2, time.Slice(0, sampleCount), y.Slice(0, sampleCount), w.Slice(0, sampleCount));
+ if (yFit != null)
+ {
+ return new VelocityEstimate( // convert from pixels/ms to pixels/s
+ PixelsPerSecond: new Vector(xFit.Coefficients[1] * 1000, yFit.Coefficients[1] * 1000),
+ Confidence: xFit.Confidence * yFit.Confidence,
+ Duration: newestSample.Time - oldestSample.Time,
+ Offset: newestSample.Point - oldestSample.Point
+ );
+ }
+ }
+ }
+
+ // We're unable to make a velocity estimate but we did have at least one
+ // valid pointer position.
+ return new VelocityEstimate(
+ PixelsPerSecond: Vector.Zero,
+ Confidence: 1.0,
+ Duration: newestSample.Time - oldestSample.Time,
+ Offset: newestSample.Point - oldestSample.Point
+ );
+ }
+
+ ///
+ /// Computes the velocity of the pointer at the time of the last
+ /// provided data point.
+ ///
+ /// This can be expensive. Only call this when you need the velocity.
+ ///
+ /// Returns [Velocity.zero] if there is no data from which to compute an
+ /// estimate or if the estimated velocity is zero.///
+ ///
+ ///
+ internal Velocity GetVelocity()
+ {
+ var estimate = GetVelocityEstimate();
+ if (estimate == null || estimate.PixelsPerSecond.IsDefault)
+ {
+ return new Velocity(Vector.Zero);
+ }
+ return new Velocity(estimate.PixelsPerSecond);
+ }
+
+ internal virtual Velocity GetFlingVelocity()
+ {
+ return GetVelocity().ClampMagnitude(MinFlingVelocity, MaxFlingVelocity);
+ }
+ }
+
+ /// An nth degree polynomial fit to a dataset.
+ internal class PolynomialFit
+ {
+ /// Creates a polynomial fit of the given degree.
+ ///
+ /// There are n + 1 coefficients in a fit of degree n.
+ internal PolynomialFit(int degree)
+ {
+ Coefficients = new double[degree + 1];
+ }
+
+ /// The polynomial coefficients of the fit.
+ public double[] Coefficients { get; }
+
+ /// An indicator of the quality of the fit.
+ ///
+ /// Larger values indicate greater quality.
+ public double Confidence { get; set; }
+ }
+
+ internal class LeastSquaresSolver
+ {
+ private const double PrecisionErrorTolerance = 1e-10;
+
+ ///
+ /// Fits a polynomial of the given degree to the data points.
+ /// When there is not enough data to fit a curve null is returned.
+ ///
+ public static PolynomialFit? Solve(int degree, ReadOnlySpan x, ReadOnlySpan y, ReadOnlySpan w)
+ {
+ if (degree > x.Length)
+ {
+ // Not enough data to fit a curve.
+ return null;
+ }
+
+ PolynomialFit result = new PolynomialFit(degree);
+
+ // Shorthands for the purpose of notation equivalence to original C++ code.
+ int m = x.Length;
+ int n = degree + 1;
+
+ // Expand the X vector to a matrix A, pre-multiplied by the weights.
+ _Matrix a = new _Matrix(m, stackalloc double[n * m]);
+ for (int h = 0; h < m; h += 1)
+ {
+ a[0, h] = w[h];
+ for (int i = 1; i < n; i += 1)
+ {
+ a[i, h] = a[i - 1, h] * x[h];
+ }
+ }
+
+ // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
+
+ // Orthonormal basis, column-major order Vector.
+ _Matrix q = new _Matrix(m, stackalloc double[n * m]);
+ // Upper triangular matrix, row-major order.
+ _Matrix r = new _Matrix(n, stackalloc double[n * n]);
+ for (int j = 0; j < n; j += 1)
+ {
+ for (int h = 0; h < m; h += 1)
+ {
+ q[j, h] = a[j, h];
+ }
+ for (int i = 0; i < j; i += 1)
+ {
+ double dot = Multiply(q.GetRow(j), q.GetRow(i));
+ for (int h = 0; h < m; h += 1)
+ {
+ q[j, h] = q[j, h] - dot * q[i, h];
+ }
+ }
+
+ double norm = Norm(q.GetRow(j));
+ if (norm < PrecisionErrorTolerance)
+ {
+ // Vectors are linearly dependent or zero so no solution.
+ return null;
+ }
+
+ double inverseNorm = 1.0 / norm;
+ for (int h = 0; h < m; h += 1)
+ {
+ q[j, h] = q[j, h] * inverseNorm;
+ }
+ for (int i = 0; i < n; i += 1)
+ {
+ r[j, i] = i < j ? 0.0 : Multiply(q.GetRow(j), a.GetRow(i));
+ }
+ }
+
+ // Solve R B = Qt W Y to find B. This is easy because R is upper triangular.
+ // We just work from bottom-right to top-left calculating B's coefficients.
+ // "m" isn't expected to be bigger than HistorySize=20, so allocation on stack is safe.
+ Span wy = stackalloc double[m];
+ for (int h = 0; h < m; h += 1)
+ {
+ wy[h] = y[h] * w[h];
+ }
+ for (int i = n - 1; i >= 0; i -= 1)
+ {
+ result.Coefficients[i] = Multiply(q.GetRow(i), wy);
+ for (int j = n - 1; j > i; j -= 1)
+ {
+ result.Coefficients[i] -= r[i, j] * result.Coefficients[j];
+ }
+ result.Coefficients[i] /= r[i, i];
+ }
+
+ // Calculate the coefficient of determination (confidence) as:
+ // 1 - (sumSquaredError / sumSquaredTotal)
+ // ...where sumSquaredError is the residual sum of squares (variance of the
+ // error), and sumSquaredTotal is the total sum of squares (variance of the
+ // data) where each has been weighted.
+ double yMean = 0.0;
+ for (int h = 0; h < m; h += 1)
+ {
+ yMean += y[h];
+ }
+ yMean /= m;
+
+ double sumSquaredError = 0.0;
+ double sumSquaredTotal = 0.0;
+ for (int h = 0; h < m; h += 1)
+ {
+ double term = 1.0;
+ double err = y[h] - result.Coefficients[0];
+ for (int i = 1; i < n; i += 1)
+ {
+ term *= x[h];
+ err -= term * result.Coefficients[i];
+ }
+ sumSquaredError += w[h] * w[h] * err * err;
+ double v = y[h] - yMean;
+ sumSquaredTotal += w[h] * w[h] * v * v;
+ }
+
+ result.Confidence = sumSquaredTotal <= PrecisionErrorTolerance ? 1.0 :
+ 1.0 - (sumSquaredError / sumSquaredTotal);
+
+ return result;
+ }
+
+ private static double Multiply(Span v1, Span v2)
+ {
+ double result = 0.0;
+ for (int i = 0; i < v1.Length; i += 1)
+ {
+ result += v1[i] * v2[i];
+ }
+ return result;
+ }
+
+ private static double Norm(Span v)
+ {
+ return Math.Sqrt(Multiply(v, v));
+ }
+
+ private readonly ref struct _Matrix
+ {
+ private readonly int _columns;
+ private readonly Span _elements;
+
+ internal _Matrix(int cols, Span elements)
+ {
+ _columns = cols;
+ _elements = elements;
+ }
+
+ public double this[int row, int col]
+ {
+ get => _elements[row * _columns + col];
+ set => _elements[row * _columns + col] = value;
+ }
+
+ public Span GetRow(int row) => _elements.Slice(row * _columns, _columns);
+ }
+ }
+}
diff --git a/src/Avalonia.Base/Input/Gestures.cs b/src/Avalonia.Base/Input/Gestures.cs
index 38e2be941a..a9e42c2374 100644
--- a/src/Avalonia.Base/Input/Gestures.cs
+++ b/src/Avalonia.Base/Input/Gestures.cs
@@ -1,6 +1,8 @@
using System;
+using System.Threading;
using Avalonia.Interactivity;
using Avalonia.Platform;
+using Avalonia.Threading;
using Avalonia.Reactive;
using Avalonia.VisualTree;
@@ -9,6 +11,21 @@ namespace Avalonia.Input
public static class Gestures
{
private static bool s_isDoubleTapped = false;
+ private static bool s_isHolding;
+ private static CancellationTokenSource? s_holdCancellationToken;
+
+ ///
+ /// Defines the IsHoldingEnabled attached property.
+ ///
+ public static readonly AttachedProperty IsHoldingEnabledProperty =
+ AvaloniaProperty.RegisterAttached("IsHoldingEnabled", typeof(Gestures), true);
+
+ ///
+ /// Defines the IsHoldWithMouseEnabled attached property.
+ ///
+ public static readonly AttachedProperty IsHoldWithMouseEnabledProperty =
+ AvaloniaProperty.RegisterAttached("IsHoldWithMouseEnabled", typeof(Gestures), false);
+
public static readonly RoutedEvent TappedEvent = RoutedEvent.Register(
"Tapped",
RoutingStrategies.Bubble,
@@ -46,6 +63,7 @@ namespace Avalonia.Input
private static readonly WeakReference
public static readonly RoutedEvent TappedEvent = Gestures.TappedEvent;
+ ///
+ /// Defines the event.
+ ///
+ public static readonly RoutedEvent HoldingEvent = Gestures.HoldingEvent;
+
///
/// Defines the event.
///
public static readonly RoutedEvent DoubleTappedEvent = Gestures.DoubleTappedEvent;
-
+
private bool _isEffectivelyEnabled = true;
private bool _isFocused;
private bool _isKeyboardFocusWithin;
@@ -353,6 +358,15 @@ namespace Avalonia.Input
add { AddHandler(TappedEvent, value); }
remove { RemoveHandler(TappedEvent, value); }
}
+
+ ///
+ /// Occurs when a hold gesture occurs on the control.
+ ///
+ public event EventHandler? Holding
+ {
+ add { AddHandler(HoldingEvent, value); }
+ remove { RemoveHandler(HoldingEvent, value); }
+ }
///
/// Occurs when a double-tap gesture occurs on the control.
diff --git a/src/Avalonia.Base/Layout/WrapLayout/UvMeasure.cs b/src/Avalonia.Base/Layout/WrapLayout/UvMeasure.cs
index 91fa459acb..fa298b53a3 100644
--- a/src/Avalonia.Base/Layout/WrapLayout/UvMeasure.cs
+++ b/src/Avalonia.Base/Layout/WrapLayout/UvMeasure.cs
@@ -7,7 +7,7 @@ namespace Avalonia.Layout
{
internal struct UvMeasure
{
- internal static readonly UvMeasure Zero = default(UvMeasure);
+ internal static readonly UvMeasure Zero = default;
internal double U { get; set; }
diff --git a/src/Avalonia.Base/Media/DrawingContext.cs b/src/Avalonia.Base/Media/DrawingContext.cs
index eabd7c8274..077816c645 100644
--- a/src/Avalonia.Base/Media/DrawingContext.cs
+++ b/src/Avalonia.Base/Media/DrawingContext.cs
@@ -279,7 +279,7 @@ namespace Avalonia.Media
OpacityMask,
}
- public PushedState(DrawingContext context, PushedStateType type, Matrix matrix = default(Matrix))
+ public PushedState(DrawingContext context, PushedStateType type, Matrix matrix = default)
{
if (context._states is null)
throw new ObjectDisposedException(nameof(DrawingContext));
diff --git a/src/Avalonia.Base/Media/DrawingGroup.cs b/src/Avalonia.Base/Media/DrawingGroup.cs
index 4a46d89153..7d3b4c056e 100644
--- a/src/Avalonia.Base/Media/DrawingGroup.cs
+++ b/src/Avalonia.Base/Media/DrawingGroup.cs
@@ -76,8 +76,8 @@ namespace Avalonia.Media
{
using (context.PushPreTransform(Transform?.Value ?? Matrix.Identity))
using (context.PushOpacity(Opacity))
- using (ClipGeometry != null ? context.PushGeometryClip(ClipGeometry) : default(DrawingContext.PushedState))
- using (OpacityMask != null ? context.PushOpacityMask(OpacityMask, GetBounds()) : default(DrawingContext.PushedState))
+ using (ClipGeometry != null ? context.PushGeometryClip(ClipGeometry) : default)
+ using (OpacityMask != null ? context.PushOpacityMask(OpacityMask, GetBounds()) : default)
{
foreach (var drawing in Children)
{
diff --git a/src/Avalonia.Base/Media/FontManager.cs b/src/Avalonia.Base/Media/FontManager.cs
index d92d003c2a..e82d5b7ba5 100644
--- a/src/Avalonia.Base/Media/FontManager.cs
+++ b/src/Avalonia.Base/Media/FontManager.cs
@@ -47,10 +47,7 @@ namespace Avalonia.Media
return current;
}
- var fontManagerImpl = AvaloniaLocator.Current.GetService();
-
- if (fontManagerImpl == null)
- throw new InvalidOperationException("No font manager implementation was registered.");
+ var fontManagerImpl = AvaloniaLocator.Current.GetRequiredService();
current = new FontManager(fontManagerImpl);
diff --git a/src/Avalonia.Base/Media/ImmediateDrawingContext.cs b/src/Avalonia.Base/Media/ImmediateDrawingContext.cs
index 1e1a73437d..eb6f105680 100644
--- a/src/Avalonia.Base/Media/ImmediateDrawingContext.cs
+++ b/src/Avalonia.Base/Media/ImmediateDrawingContext.cs
@@ -218,7 +218,7 @@ namespace Avalonia.Media
OpacityMask,
}
- internal PushedState(ImmediateDrawingContext context, PushedStateType type, Matrix matrix = default(Matrix))
+ internal PushedState(ImmediateDrawingContext context, PushedStateType type, Matrix matrix = default)
{
if (context._states is null)
throw new ObjectDisposedException(nameof(ImmediateDrawingContext));
diff --git a/src/Avalonia.Base/Media/TextFormatting/CharacterBufferRange.cs b/src/Avalonia.Base/Media/TextFormatting/CharacterBufferRange.cs
index d76f212f26..f5d39e4371 100644
--- a/src/Avalonia.Base/Media/TextFormatting/CharacterBufferRange.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/CharacterBufferRange.cs
@@ -140,7 +140,7 @@ namespace Avalonia.Media.TextFormatting
throw new ArgumentOutOfRangeException(nameof(index));
}
#endif
- return Span[index];
+ return CharacterBufferReference.CharacterBuffer.Span[CharacterBufferReference.OffsetToFirstChar + index];
}
}
@@ -163,27 +163,18 @@ namespace Avalonia.Media.TextFormatting
///
/// Gets the character memory buffer
///
- internal ReadOnlyMemory CharacterBuffer
- {
- get { return CharacterBufferReference.CharacterBuffer; }
- }
+ internal ReadOnlyMemory CharacterBuffer => CharacterBufferReference.CharacterBuffer;
///
/// Gets the character offset relative to the beginning of buffer to
/// the first character of the run
///
- internal int OffsetToFirstChar
- {
- get { return CharacterBufferReference.OffsetToFirstChar; }
- }
+ internal int OffsetToFirstChar => CharacterBufferReference.OffsetToFirstChar;
///
/// Indicate whether the character buffer range is empty
///
- internal bool IsEmpty
- {
- get { return CharacterBufferReference.CharacterBuffer.Length == 0 || Length <= 0; }
- }
+ internal bool IsEmpty => CharacterBufferReference.CharacterBuffer.Length == 0 || Length <= 0;
internal CharacterBufferRange Take(int length)
{
@@ -280,14 +271,8 @@ namespace Avalonia.Media.TextFormatting
int IReadOnlyCollection.Count => Length;
- public IEnumerator GetEnumerator()
- {
- return new ImmutableReadOnlyListStructEnumerator(this);
- }
+ public IEnumerator GetEnumerator() => new ImmutableReadOnlyListStructEnumerator(this);
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/FormattedTextSource.cs b/src/Avalonia.Base/Media/TextFormatting/FormattedTextSource.cs
index 4472ba87eb..49d94b511d 100644
--- a/src/Avalonia.Base/Media/TextFormatting/FormattedTextSource.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/FormattedTextSource.cs
@@ -132,7 +132,7 @@ namespace Avalonia.Media.TextFormatting
{
var grapheme = graphemeEnumerator.Current;
- finalLength += grapheme.Text.Length;
+ finalLength += grapheme.Length;
if (finalLength >= length)
{
diff --git a/src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs b/src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs
index 3c3a46c209..21e8ce089a 100644
--- a/src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs
@@ -91,7 +91,7 @@ namespace Avalonia.Media.TextFormatting
continue;
}
- if (textRun is ShapedTextCharacters shapedText)
+ if (textRun is ShapedTextRun shapedText)
{
var glyphRun = shapedText.GlyphRun;
var shapedBuffer = shapedText.ShapedBuffer;
diff --git a/src/Avalonia.Base/Media/TextFormatting/ShapedTextCharacters.cs b/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
similarity index 92%
rename from src/Avalonia.Base/Media/TextFormatting/ShapedTextCharacters.cs
rename to src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
index 3035eb7b18..3149bc2cda 100644
--- a/src/Avalonia.Base/Media/TextFormatting/ShapedTextCharacters.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
@@ -6,11 +6,11 @@ namespace Avalonia.Media.TextFormatting
///
/// A text run that holds shaped characters.
///
- public sealed class ShapedTextCharacters : DrawableTextRun
+ public sealed class ShapedTextRun : DrawableTextRun
{
private GlyphRun? _glyphRun;
- public ShapedTextCharacters(ShapedBuffer shapedBuffer, TextRunProperties properties)
+ public ShapedTextRun(ShapedBuffer shapedBuffer, TextRunProperties properties)
{
ShapedBuffer = shapedBuffer;
CharacterBufferReference = shapedBuffer.CharacterBufferRange.CharacterBufferReference;
@@ -155,7 +155,7 @@ namespace Avalonia.Media.TextFormatting
return length > 0;
}
- internal SplitResult Split(int length)
+ internal SplitResult Split(int length)
{
if (IsReversed)
{
@@ -171,7 +171,7 @@ namespace Avalonia.Media.TextFormatting
var splitBuffer = ShapedBuffer.Split(length);
- var first = new ShapedTextCharacters(splitBuffer.First, Properties);
+ var first = new ShapedTextRun(splitBuffer.First, Properties);
#if DEBUG
@@ -182,9 +182,9 @@ namespace Avalonia.Media.TextFormatting
#endif
- var second = new ShapedTextCharacters(splitBuffer.Second!, Properties);
+ var second = new ShapedTextRun(splitBuffer.Second!, Properties);
- return new SplitResult(first, second);
+ return new SplitResult(first, second);
}
internal GlyphRun CreateGlyphRun()
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs b/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs
index 0be753bd04..1a48151834 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs
@@ -91,12 +91,12 @@ namespace Avalonia.Media.TextFormatting
public override TextRunProperties Properties { get; }
///
- /// Gets a list of .
+ /// Gets a list of .
///
/// The shapeable text characters.
- internal IReadOnlyList GetShapeableCharacters(CharacterBufferRange characterBufferRange, sbyte biDiLevel, ref TextRunProperties? previousProperties)
+ internal IReadOnlyList GetShapeableCharacters(CharacterBufferRange characterBufferRange, sbyte biDiLevel, ref TextRunProperties? previousProperties)
{
- var shapeableCharacters = new List(2);
+ var shapeableCharacters = new List(2);
while (characterBufferRange.Length > 0)
{
@@ -120,7 +120,7 @@ namespace Avalonia.Media.TextFormatting
/// The bidi level of the run.
///
/// A list of shapeable text runs.
- private static ShapeableTextCharacters CreateShapeableRun(CharacterBufferRange characterBufferRange,
+ private static UnshapedTextRun CreateShapeableRun(CharacterBufferRange characterBufferRange,
TextRunProperties defaultProperties, sbyte biDiLevel, ref TextRunProperties? previousProperties)
{
var defaultTypeface = defaultProperties.Typeface;
@@ -133,12 +133,12 @@ namespace Avalonia.Media.TextFormatting
{
if (TryGetShapeableLength(characterBufferRange, previousTypeface.Value, null, out var fallbackCount, out _))
{
- return new ShapeableTextCharacters(characterBufferRange.CharacterBufferReference, fallbackCount,
+ return new UnshapedTextRun(characterBufferRange.CharacterBufferReference, fallbackCount,
defaultProperties.WithTypeface(previousTypeface.Value), biDiLevel);
}
}
- return new ShapeableTextCharacters(characterBufferRange.CharacterBufferReference, count, defaultProperties.WithTypeface(currentTypeface),
+ return new UnshapedTextRun(characterBufferRange.CharacterBufferReference, count, defaultProperties.WithTypeface(currentTypeface),
biDiLevel);
}
@@ -146,7 +146,7 @@ namespace Avalonia.Media.TextFormatting
{
if (TryGetShapeableLength(characterBufferRange, previousTypeface.Value, defaultTypeface, out count, out _))
{
- return new ShapeableTextCharacters(characterBufferRange.CharacterBufferReference, count,
+ return new UnshapedTextRun(characterBufferRange.CharacterBufferReference, count,
defaultProperties.WithTypeface(previousTypeface.Value), biDiLevel);
}
}
@@ -176,7 +176,7 @@ namespace Avalonia.Media.TextFormatting
if (matchFound && TryGetShapeableLength(characterBufferRange, currentTypeface, defaultTypeface, out count, out _))
{
//Fallback found
- return new ShapeableTextCharacters(characterBufferRange.CharacterBufferReference, count, defaultProperties.WithTypeface(currentTypeface),
+ return new UnshapedTextRun(characterBufferRange.CharacterBufferReference, count, defaultProperties.WithTypeface(currentTypeface),
biDiLevel);
}
@@ -196,10 +196,10 @@ namespace Avalonia.Media.TextFormatting
break;
}
- count += grapheme.Text.Length;
+ count += grapheme.Length;
}
- return new ShapeableTextCharacters(characterBufferRange.CharacterBufferReference, count, defaultProperties, biDiLevel);
+ return new UnshapedTextRun(characterBufferRange.CharacterBufferReference, count, defaultProperties, biDiLevel);
}
///
@@ -264,7 +264,7 @@ namespace Avalonia.Media.TextFormatting
}
}
- length += currentGrapheme.Text.Length;
+ length += currentGrapheme.Length;
}
return length > 0;
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextEllipsisHelper.cs b/src/Avalonia.Base/Media/TextFormatting/TextEllipsisHelper.cs
index a1b8985b43..086ea85d97 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextEllipsisHelper.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextEllipsisHelper.cs
@@ -31,7 +31,7 @@ namespace Avalonia.Media.TextFormatting
switch (currentRun)
{
- case ShapedTextCharacters shapedRun:
+ case ShapedTextRun shapedRun:
{
currentWidth += shapedRun.Size.Width;
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs
index 93eb4811b9..ef2abdfea0 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs
@@ -124,7 +124,7 @@ namespace Avalonia.Media.TextFormatting
var second = new List(secondCount);
- if (currentRun is ShapedTextCharacters shapedTextCharacters)
+ if (currentRun is ShapedTextRun shapedTextCharacters)
{
var split = shapedTextCharacters.Split(length - currentLength);
@@ -206,16 +206,16 @@ namespace Avalonia.Media.TextFormatting
break;
}
- case ShapeableTextCharacters shapeableRun:
+ case UnshapedTextRun shapeableRun:
{
- var groupedRuns = new List(2) { shapeableRun };
+ var groupedRuns = new List(2) { shapeableRun };
var characterBufferReference = currentRun.CharacterBufferReference;
var length = currentRun.Length;
var offsetToFirstCharacter = characterBufferReference.OffsetToFirstChar;
while (index + 1 < processedRuns.Count)
{
- if (processedRuns[index + 1] is not ShapeableTextCharacters nextRun)
+ if (processedRuns[index + 1] is not UnshapedTextRun nextRun)
{
break;
}
@@ -258,10 +258,10 @@ namespace Avalonia.Media.TextFormatting
return drawableTextRuns;
}
- private static IReadOnlyList ShapeTogether(
- IReadOnlyList textRuns, CharacterBufferReference text, int length, TextShaperOptions options)
+ private static IReadOnlyList ShapeTogether(
+ IReadOnlyList textRuns, CharacterBufferReference text, int length, TextShaperOptions options)
{
- var shapedRuns = new List(textRuns.Count);
+ var shapedRuns = new List(textRuns.Count);
var shapedBuffer = TextShaper.Current.ShapeText(text, length, options);
@@ -271,7 +271,7 @@ namespace Avalonia.Media.TextFormatting
var splitResult = shapedBuffer.Split(currentRun.Length);
- shapedRuns.Add(new ShapedTextCharacters(splitResult.First, currentRun.Properties));
+ shapedRuns.Add(new ShapedTextRun(splitResult.First, currentRun.Properties));
shapedBuffer = splitResult.Second!;
}
@@ -280,9 +280,9 @@ namespace Avalonia.Media.TextFormatting
}
///
- /// Coalesces ranges of the same bidi level to form
+ /// Coalesces ranges of the same bidi level to form
///
- /// The text characters to form from.
+ /// The text characters to form from.
/// The bidi levels.
///
private static IEnumerable> CoalesceLevels(IReadOnlyList textCharacters, ArraySlice levels)
@@ -474,7 +474,7 @@ namespace Avalonia.Media.TextFormatting
{
switch (currentRun)
{
- case ShapedTextCharacters shapedTextCharacters:
+ case ShapedTextRun shapedTextCharacters:
{
if(shapedTextCharacters.ShapedBuffer.Length > 0)
{
@@ -538,7 +538,7 @@ namespace Avalonia.Media.TextFormatting
var shapedBuffer = new ShapedBuffer(characterBufferRange, glyphInfos, glyphTypeface, properties.FontRenderingEmSize,
(sbyte)flowDirection);
- var textRuns = new List { new ShapedTextCharacters(shapedBuffer, properties) };
+ var textRuns = new List { new ShapedTextRun(shapedBuffer, properties) };
return new TextLineImpl(textRuns, firstTextSourceIndex, 0, paragraphWidth, paragraphProperties, flowDirection).FinalizeLine();
}
@@ -744,7 +744,7 @@ namespace Avalonia.Media.TextFormatting
///
/// The shaped symbol.
///
- internal static ShapedTextCharacters CreateSymbol(TextRun textRun, FlowDirection flowDirection)
+ internal static ShapedTextRun CreateSymbol(TextRun textRun, FlowDirection flowDirection)
{
var textShaper = TextShaper.Current;
@@ -760,7 +760,7 @@ namespace Avalonia.Media.TextFormatting
var shapedBuffer = textShaper.ShapeText(characterBuffer, textRun.Length, shaperOptions);
- return new ShapedTextCharacters(shapedBuffer, textRun.Properties);
+ return new ShapedTextRun(shapedBuffer, textRun.Properties);
}
}
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLeadingPrefixCharacterEllipsis.cs b/src/Avalonia.Base/Media/TextFormatting/TextLeadingPrefixCharacterEllipsis.cs
index 2752af8f0c..7b80d5ce40 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextLeadingPrefixCharacterEllipsis.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextLeadingPrefixCharacterEllipsis.cs
@@ -65,7 +65,7 @@ namespace Avalonia.Media.TextFormatting
switch (currentRun)
{
- case ShapedTextCharacters shapedRun:
+ case ShapedTextRun shapedRun:
{
currentWidth += currentRun.Size.Width;
@@ -118,7 +118,7 @@ namespace Avalonia.Media.TextFormatting
switch (run)
{
- case ShapedTextCharacters endShapedRun:
+ case ShapedTextRun endShapedRun:
{
if (endShapedRun.TryMeasureCharactersBackwards(availableSuffixWidth,
out var suffixCount, out var suffixWidth))
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
index d893468052..5fb1171221 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
@@ -192,14 +192,14 @@ namespace Avalonia.Media.TextFormatting
{
var currentRun = _textRuns[i];
- if (currentRun is ShapedTextCharacters shapedRun && !shapedRun.ShapedBuffer.IsLeftToRight)
+ if (currentRun is ShapedTextRun shapedRun && !shapedRun.ShapedBuffer.IsLeftToRight)
{
var rightToLeftIndex = i;
currentPosition += currentRun.Length;
while (rightToLeftIndex + 1 <= _textRuns.Count - 1)
{
- var nextShaped = _textRuns[++rightToLeftIndex] as ShapedTextCharacters;
+ var nextShaped = _textRuns[++rightToLeftIndex] as ShapedTextRun;
if (nextShaped == null || nextShaped.ShapedBuffer.IsLeftToRight)
{
@@ -255,7 +255,7 @@ namespace Avalonia.Media.TextFormatting
switch (run)
{
- case ShapedTextCharacters shapedRun:
+ case ShapedTextRun shapedRun:
{
characterHit = shapedRun.GlyphRun.GetCharacterHitFromDistance(distance, out _);
@@ -303,7 +303,7 @@ namespace Avalonia.Media.TextFormatting
{
var currentRun = _textRuns[index];
- if (currentRun is ShapedTextCharacters shapedRun && !shapedRun.ShapedBuffer.IsLeftToRight)
+ if (currentRun is ShapedTextRun shapedRun && !shapedRun.ShapedBuffer.IsLeftToRight)
{
var i = index;
@@ -313,7 +313,7 @@ namespace Avalonia.Media.TextFormatting
{
var nextRun = _textRuns[i + 1];
- if (nextRun is ShapedTextCharacters nextShapedRun && !nextShapedRun.ShapedBuffer.IsLeftToRight)
+ if (nextRun is ShapedTextRun nextShapedRun && !nextShapedRun.ShapedBuffer.IsLeftToRight)
{
i++;
@@ -407,7 +407,7 @@ namespace Avalonia.Media.TextFormatting
switch (currentRun)
{
- case ShapedTextCharacters shapedTextCharacters:
+ case ShapedTextRun shapedTextCharacters:
{
currentGlyphRun = shapedTextCharacters.GlyphRun;
@@ -476,7 +476,7 @@ namespace Avalonia.Media.TextFormatting
switch (currentRun)
{
- case ShapedTextCharacters shapedRun:
+ case ShapedTextRun shapedRun:
{
nextCharacterHit = shapedRun.GlyphRun.GetNextCaretCharacterHit(characterHit);
break;
@@ -550,7 +550,7 @@ namespace Avalonia.Media.TextFormatting
double combinedWidth;
- if (currentRun is ShapedTextCharacters currentShapedRun)
+ if (currentRun is ShapedTextRun currentShapedRun)
{
var firstCluster = currentShapedRun.GlyphRun.Metrics.FirstCluster;
@@ -592,7 +592,7 @@ namespace Avalonia.Media.TextFormatting
var rightToLeftIndex = index;
var rightToLeftWidth = currentShapedRun.Size.Width;
- while (rightToLeftIndex + 1 <= _textRuns.Count - 1 && _textRuns[rightToLeftIndex + 1] is ShapedTextCharacters nextShapedRun)
+ while (rightToLeftIndex + 1 <= _textRuns.Count - 1 && _textRuns[rightToLeftIndex + 1] is ShapedTextRun nextShapedRun)
{
if (nextShapedRun == null || nextShapedRun.ShapedBuffer.IsLeftToRight)
{
@@ -624,12 +624,12 @@ namespace Avalonia.Media.TextFormatting
for (int i = rightToLeftIndex - 1; i >= index; i--)
{
- if (TextRuns[i] is not ShapedTextCharacters)
+ if (TextRuns[i] is not ShapedTextRun)
{
continue;
}
- currentShapedRun = (ShapedTextCharacters)TextRuns[i];
+ currentShapedRun = (ShapedTextRun)TextRuns[i];
currentRunBounds = GetRightToLeftTextRunBounds(currentShapedRun, startX, firstTextSourceIndex, characterIndex, currentPosition, remainingLength);
@@ -769,7 +769,7 @@ namespace Avalonia.Media.TextFormatting
var characterLength = 0;
var endX = startX;
- if (currentRun is ShapedTextCharacters currentShapedRun)
+ if (currentRun is ShapedTextRun currentShapedRun)
{
var offset = Math.Max(0, firstTextSourceIndex - currentPosition);
@@ -883,7 +883,7 @@ namespace Avalonia.Media.TextFormatting
return result;
}
- private TextRunBounds GetRightToLeftTextRunBounds(ShapedTextCharacters currentRun, double endX, int firstTextSourceIndex, int characterIndex, int currentPosition, int remainingLength)
+ private TextRunBounds GetRightToLeftTextRunBounds(ShapedTextRun currentRun, double endX, int firstTextSourceIndex, int characterIndex, int currentPosition, int remainingLength)
{
var startX = endX;
@@ -945,7 +945,7 @@ namespace Avalonia.Media.TextFormatting
private static sbyte GetRunBidiLevel(DrawableTextRun run, FlowDirection flowDirection)
{
- if (run is ShapedTextCharacters shapedTextCharacters)
+ if (run is ShapedTextRun shapedTextCharacters)
{
return shapedTextCharacters.BidiLevel;
}
@@ -1027,7 +1027,7 @@ namespace Avalonia.Media.TextFormatting
{
if (current.Level >= minLevelToReverse && current.Level % 2 != 0)
{
- if (current.Run is ShapedTextCharacters { IsReversed: false } shapedTextCharacters)
+ if (current.Run is ShapedTextRun { IsReversed: false } shapedTextCharacters)
{
shapedTextCharacters.Reverse();
}
@@ -1145,7 +1145,7 @@ namespace Avalonia.Media.TextFormatting
switch (currentRun)
{
- case ShapedTextCharacters shapedRun:
+ case ShapedTextRun shapedRun:
{
var foundCharacterHit = shapedRun.GlyphRun.FindNearestCharacterHit(characterHit.FirstCharacterIndex + characterHit.TrailingLength, out _);
@@ -1230,7 +1230,7 @@ namespace Avalonia.Media.TextFormatting
switch (currentRun)
{
- case ShapedTextCharacters shapedRun:
+ case ShapedTextRun shapedRun:
{
var foundCharacterHit = shapedRun.GlyphRun.FindNearestCharacterHit(characterHit.FirstCharacterIndex - 1, out _);
@@ -1294,7 +1294,7 @@ namespace Avalonia.Media.TextFormatting
switch (currentRun)
{
- case ShapedTextCharacters shapedRun:
+ case ShapedTextRun shapedRun:
{
var firstCluster = shapedRun.GlyphRun.Metrics.FirstCluster;
@@ -1303,7 +1303,7 @@ namespace Avalonia.Media.TextFormatting
break;
}
- if (previousRun is ShapedTextCharacters previousShaped && !previousShaped.ShapedBuffer.IsLeftToRight)
+ if (previousRun is ShapedTextRun previousShaped && !previousShaped.ShapedBuffer.IsLeftToRight)
{
if (shapedRun.ShapedBuffer.IsLeftToRight)
{
@@ -1394,7 +1394,7 @@ namespace Avalonia.Media.TextFormatting
{
switch (_textRuns[index])
{
- case ShapedTextCharacters textRun:
+ case ShapedTextRun textRun:
{
var textMetrics =
new TextMetrics(textRun.Properties.Typeface.GlyphTypeface, textRun.Properties.FontRenderingEmSize);
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextParagraphProperties.cs b/src/Avalonia.Base/Media/TextFormatting/TextParagraphProperties.cs
index 5691dd8ad0..27515738a4 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextParagraphProperties.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextParagraphProperties.cs
@@ -63,14 +63,11 @@
{
get { return 0; }
}
-
+
///
/// Gets the default incremental tab width.
///
- public virtual double DefaultIncrementalTab
- {
- get { return 4 * DefaultTextRunProperties.FontRenderingEmSize; }
- }
+ public virtual double DefaultIncrementalTab => 0;
///
/// Gets the letter spacing.
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextRun.cs b/src/Avalonia.Base/Media/TextFormatting/TextRun.cs
index 0306054767..e79c2ed8b3 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextRun.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextRun.cs
@@ -44,7 +44,7 @@ namespace Avalonia.Media.TextFormatting
fixed (char* charsPtr = characterBuffer.Span)
{
- return new string(charsPtr, 0, characterBuffer.Span.Length);
+ return new string(charsPtr, _textRun.CharacterBufferReference.OffsetToFirstChar, _textRun.Length);
}
}
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextShaper.cs b/src/Avalonia.Base/Media/TextFormatting/TextShaper.cs
index 4aacec7c48..c161b08d20 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextShaper.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextShaper.cs
@@ -29,10 +29,7 @@ namespace Avalonia.Media.TextFormatting
return current;
}
- var textShaperImpl = AvaloniaLocator.Current.GetService();
-
- if (textShaperImpl == null)
- throw new InvalidOperationException("No text shaper implementation was registered.");
+ var textShaperImpl = AvaloniaLocator.Current.GetRequiredService();
current = new TextShaper(textShaperImpl);
diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs
index e6408bcfa6..8b9d1c1d02 100644
--- a/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Avalonia.Media.TextFormatting.Unicode
@@ -222,6 +223,71 @@ namespace Avalonia.Media.TextFormatting.Unicode
return new Codepoint(code);
}
+
+ ///
+ /// Reads the at specified position.
+ ///
+ /// The buffer to read from.
+ /// The index to read at.
+ /// The count of character that were read.
+ ///
+ public static Codepoint ReadAt(CharacterBufferRange text, int index, out int count)
+ {
+ count = 1;
+
+ if (index >= text.Length)
+ {
+ return ReplacementCodepoint;
+ }
+
+ var code = text[index];
+
+ ushort hi, low;
+
+ //# High surrogate
+ if (0xD800 <= code && code <= 0xDBFF)
+ {
+ hi = code;
+
+ if (index + 1 == text.Length)
+ {
+ return ReplacementCodepoint;
+ }
+
+ low = text[index + 1];
+
+ if (0xDC00 <= low && low <= 0xDFFF)
+ {
+ count = 2;
+ return new Codepoint((uint)((hi - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000));
+ }
+
+ return ReplacementCodepoint;
+ }
+
+ //# Low surrogate
+ if (0xDC00 <= code && code <= 0xDFFF)
+ {
+ if (index == 0)
+ {
+ return ReplacementCodepoint;
+ }
+
+ hi = text[index - 1];
+
+ low = code;
+
+ if (0xD800 <= hi && hi <= 0xDBFF)
+ {
+ count = 2;
+ return new Codepoint((uint)((hi - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000));
+ }
+
+ return ReplacementCodepoint;
+ }
+
+ return new Codepoint(code);
+ }
///
/// Returns if is between
diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/Grapheme.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/Grapheme.cs
index 69015fb17d..f75168083c 100644
--- a/src/Avalonia.Base/Media/TextFormatting/Unicode/Grapheme.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/Grapheme.cs
@@ -7,10 +7,11 @@ namespace Avalonia.Media.TextFormatting.Unicode
///
public readonly ref struct Grapheme
{
- public Grapheme(Codepoint firstCodepoint, ReadOnlySpan text)
+ public Grapheme(Codepoint firstCodepoint, int offset, int length)
{
FirstCodepoint = firstCodepoint;
- Text = text;
+ Offset = offset;
+ Length = length;
}
///
@@ -19,8 +20,13 @@ namespace Avalonia.Media.TextFormatting.Unicode
public Codepoint FirstCodepoint { get; }
///
- /// The text that is representing the .
+ /// The Offset to the FirstCodepoint
///
- public ReadOnlySpan Text { get; }
+ public int Offset { get; }
+
+ ///
+ /// The length of the grapheme cluster
+ ///
+ public int Length { get; }
}
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeEnumerator.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeEnumerator.cs
index 5ca120c856..dc21e06813 100644
--- a/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeEnumerator.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeEnumerator.cs
@@ -185,9 +185,7 @@ namespace Avalonia.Media.TextFormatting.Unicode
Return:
- var text = _text.Take(processor.CurrentCodeUnitOffset);
-
- Current = new Grapheme(firstCodepoint, text.Span);
+ Current = new Grapheme(firstCodepoint, _text.OffsetToFirstChar, processor.CurrentCodeUnitOffset);
_text = _text.Skip(processor.CurrentCodeUnitOffset);
diff --git a/src/Avalonia.Base/Media/TextFormatting/ShapeableTextCharacters.cs b/src/Avalonia.Base/Media/TextFormatting/UnshapedTextRun.cs
similarity index 61%
rename from src/Avalonia.Base/Media/TextFormatting/ShapeableTextCharacters.cs
rename to src/Avalonia.Base/Media/TextFormatting/UnshapedTextRun.cs
index 0e8d6e3e4a..817086db88 100644
--- a/src/Avalonia.Base/Media/TextFormatting/ShapeableTextCharacters.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/UnshapedTextRun.cs
@@ -5,9 +5,9 @@ namespace Avalonia.Media.TextFormatting
///
/// A group of characters that can be shaped.
///
- public sealed class ShapeableTextCharacters : TextRun
+ public sealed class UnshapedTextRun : TextRun
{
- public ShapeableTextCharacters(CharacterBufferReference characterBufferReference, int length,
+ public UnshapedTextRun(CharacterBufferReference characterBufferReference, int length,
TextRunProperties properties, sbyte biDiLevel)
{
CharacterBufferReference = characterBufferReference;
@@ -24,30 +24,30 @@ namespace Avalonia.Media.TextFormatting
public sbyte BidiLevel { get; }
- public bool CanShapeTogether(ShapeableTextCharacters shapeableTextCharacters)
+ public bool CanShapeTogether(UnshapedTextRun unshapedTextRun)
{
- if (!CharacterBufferReference.Equals(shapeableTextCharacters.CharacterBufferReference))
+ if (!CharacterBufferReference.Equals(unshapedTextRun.CharacterBufferReference))
{
return false;
}
- if (BidiLevel != shapeableTextCharacters.BidiLevel)
+ if (BidiLevel != unshapedTextRun.BidiLevel)
{
return false;
}
if (!MathUtilities.AreClose(Properties.FontRenderingEmSize,
- shapeableTextCharacters.Properties.FontRenderingEmSize))
+ unshapedTextRun.Properties.FontRenderingEmSize))
{
return false;
}
- if (Properties.Typeface != shapeableTextCharacters.Properties.Typeface)
+ if (Properties.Typeface != unshapedTextRun.Properties.Typeface)
{
return false;
}
- if (Properties.BaselineAlignment != shapeableTextCharacters.Properties.BaselineAlignment)
+ if (Properties.BaselineAlignment != unshapedTextRun.Properties.BaselineAlignment)
{
return false;
}
diff --git a/src/Avalonia.Base/Platform/DefaultPlatformSettings.cs b/src/Avalonia.Base/Platform/DefaultPlatformSettings.cs
index dd3e1a4cb1..d0b27b057f 100644
--- a/src/Avalonia.Base/Platform/DefaultPlatformSettings.cs
+++ b/src/Avalonia.Base/Platform/DefaultPlatformSettings.cs
@@ -26,5 +26,7 @@ namespace Avalonia.Platform
};
}
public TimeSpan GetDoubleTapTime(PointerType type) => TimeSpan.FromMilliseconds(500);
+
+ public TimeSpan HoldWaitDuration { get; set; } = TimeSpan.FromMilliseconds(300);
}
}
diff --git a/src/Avalonia.Base/Platform/IPlatformSettings.cs b/src/Avalonia.Base/Platform/IPlatformSettings.cs
index e7921883fd..7c4c1420eb 100644
--- a/src/Avalonia.Base/Platform/IPlatformSettings.cs
+++ b/src/Avalonia.Base/Platform/IPlatformSettings.cs
@@ -27,5 +27,7 @@ namespace Avalonia.Platform
/// tap gesture.
///
TimeSpan GetDoubleTapTime(PointerType type);
+
+ TimeSpan HoldWaitDuration { get; set; }
}
}
diff --git a/src/Avalonia.Base/Rendering/Composition/Compositor.cs b/src/Avalonia.Base/Rendering/Composition/Compositor.cs
index b4817bfe9a..7fc5487171 100644
--- a/src/Avalonia.Base/Rendering/Composition/Compositor.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Compositor.cs
@@ -111,7 +111,7 @@ namespace Avalonia.Rendering.Composition
}
}
- batch.CommitedAt = Server.Clock.Elapsed;
+ batch.CommittedAt = Server.Clock.Elapsed;
_server.EnqueueBatch(batch);
lock (_pendingBatchLock)
diff --git a/src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionVariant.cs b/src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionVariant.cs
index 6e53a138cd..21f14283b5 100644
--- a/src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionVariant.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionVariant.cs
@@ -654,7 +654,7 @@ namespace Avalonia.Rendering.Composition.Expressions
}
}
- res = default(T);
+ res = default;
return false;
}
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionDrawListVisual.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionDrawListVisual.cs
index 8dc088fed1..aebe3a5cdd 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionDrawListVisual.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionDrawListVisual.cs
@@ -48,7 +48,7 @@ internal class ServerCompositionDrawListVisual : ServerCompositionContainerVisua
}
}
- protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan commitedAt)
+ protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan committedAt)
{
if (reader.Read() == 1)
{
@@ -56,7 +56,7 @@ internal class ServerCompositionDrawListVisual : ServerCompositionContainerVisua
_renderCommands = reader.ReadObject();
_contentBounds = null;
}
- base.DeserializeChangesCore(reader, commitedAt);
+ base.DeserializeChangesCore(reader, committedAt);
}
protected override void RenderCore(CompositorDrawingContextProxy canvas, Rect currentTransformedClip)
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
index 0e15cbd54b..e33dc999dc 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
@@ -42,11 +42,18 @@ namespace Avalonia.Rendering.Composition.Server
Root!.RenderedVisuals++;
+ if (Opacity != 1)
+ canvas.PushOpacity(Opacity);
+ if (AdornedVisual != null)
+ {
+ canvas.PostTransform = Matrix.Identity;
+ canvas.Transform = Matrix.Identity;
+ canvas.PushClip(AdornedVisual._combinedTransformedClipBounds);
+ }
var transform = GlobalTransformMatrix;
canvas.PostTransform = MatrixUtils.ToMatrix(transform);
canvas.Transform = Matrix.Identity;
- if (Opacity != 1)
- canvas.PushOpacity(Opacity);
+
var boundsRect = new Rect(new Size(Size.X, Size.Y));
if (ClipToBounds && !HandlesClipToBounds)
canvas.PushClip(Root!.SnapToDevicePixels(boundsRect));
@@ -67,6 +74,8 @@ namespace Avalonia.Rendering.Composition.Server
canvas.PopGeometryClip();
if (ClipToBounds && !HandlesClipToBounds)
canvas.PopClip();
+ if (AdornedVisual != null)
+ canvas.PopClip();
if(Opacity != 1)
canvas.PopOpacity();
}
@@ -155,15 +164,25 @@ namespace Avalonia.Rendering.Composition.Server
_clipSizeDirty = false;
}
+
+ _combinedTransformedClipBounds =
+ AdornedVisual?._combinedTransformedClipBounds
+ ?? Parent?._combinedTransformedClipBounds
+ ?? new Rect(Root!.Size);
- _combinedTransformedClipBounds = Parent?._combinedTransformedClipBounds ?? new Rect(Root!.Size);
if (_transformedClipBounds != null)
_combinedTransformedClipBounds = _combinedTransformedClipBounds.Intersect(_transformedClipBounds.Value);
EffectiveOpacity = Opacity * (Parent?.EffectiveOpacity ?? 1);
- IsVisibleInFrame = _parent?.IsVisibleInFrame != false && Visible && EffectiveOpacity > 0.04 && !_isBackface &&
- !_combinedTransformedClipBounds.IsDefault;
+ IsHitTestVisibleInFrame = _parent?.IsHitTestVisibleInFrame != false
+ && Visible
+ && !_isBackface
+ && !_combinedTransformedClipBounds.IsDefault;
+
+ IsVisibleInFrame = IsHitTestVisibleInFrame
+ && _parent?.IsVisibleInFrame != false
+ && EffectiveOpacity > 0.04;
if (wasVisible != IsVisibleInFrame || positionChanged)
{
@@ -187,7 +206,7 @@ namespace Avalonia.Rendering.Composition.Server
readback.Revision = root.Revision;
readback.Matrix = GlobalTransformMatrix;
readback.TargetId = Root.Id;
- readback.Visible = IsVisibleInFrame;
+ readback.Visible = IsHitTestVisibleInFrame;
}
void AddDirtyRect(Rect rc)
@@ -248,6 +267,7 @@ namespace Avalonia.Rendering.Composition.Server
}
public bool IsVisibleInFrame { get; set; }
+ public bool IsHitTestVisibleInFrame { get; set; }
public double EffectiveOpacity { get; set; }
public Rect TransformedOwnContentBounds { get; set; }
public virtual Rect OwnContentBounds => new Rect(0, 0, Size.X, Size.Y);
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCustomCompositionVisual.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCustomCompositionVisual.cs
index 227df87a87..74889c9bfe 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCustomCompositionVisual.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCustomCompositionVisual.cs
@@ -16,9 +16,9 @@ internal class ServerCompositionCustomVisual : ServerCompositionContainerVisual,
_handler.Attach(this);
}
- protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan commitedAt)
+ protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan committedAt)
{
- base.DeserializeChangesCore(reader, commitedAt);
+ base.DeserializeChangesCore(reader, committedAt);
var count = reader.Read();
for (var c = 0; c < count; c++)
{
@@ -79,4 +79,4 @@ internal class ServerCompositionCustomVisual : ServerCompositionContainerVisual,
?.Log(_handler, $"Exception in {_handler.GetType().Name}.{nameof(CompositionCustomVisualHandler.OnRender)} {{0}}", e);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerList.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerList.cs
index 08a3fdce22..2500358866 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerList.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerList.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Rendering.Composition.Server
{
public List List { get; } = new List();
- protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan commitedAt)
+ protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan committedAt)
{
if (reader.Read() == 1)
{
@@ -23,7 +23,7 @@ namespace Avalonia.Rendering.Composition.Server
for (var c = 0; c < count; c++)
List.Add(reader.ReadObject());
}
- base.DeserializeChangesCore(reader, commitedAt);
+ base.DeserializeChangesCore(reader, committedAt);
}
public override long LastChangedBy
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs
index 257d3b29a2..31cb16ec20 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs
@@ -104,13 +104,13 @@ namespace Avalonia.Rendering.Composition.Server
}
protected void SetAnimatedValue(CompositionProperty prop, ref T field,
- TimeSpan commitedAt, IAnimationInstance animation) where T : struct
+ TimeSpan committedAt, IAnimationInstance animation) where T : struct
{
if (IsActive && _animations.TryGetValue(prop, out var oldAnimation))
oldAnimation.Deactivate();
_animations[prop] = animation;
- animation.Initialize(commitedAt, ExpressionVariant.Create(field), prop);
+ animation.Initialize(committedAt, ExpressionVariant.Create(field), prop);
if(IsActive)
animation.Activate();
@@ -165,7 +165,7 @@ namespace Avalonia.Rendering.Composition.Server
public virtual CompositionProperty? GetCompositionProperty(string fieldName) => null;
- protected virtual void DeserializeChangesCore(BatchStreamReader reader, TimeSpan commitedAt)
+ protected virtual void DeserializeChangesCore(BatchStreamReader reader, TimeSpan committedAt)
{
if (this is IDisposable disp
&& reader.Read() == 1)
@@ -174,7 +174,7 @@ namespace Avalonia.Rendering.Composition.Server
public void DeserializeChanges(BatchStreamReader reader, Batch batch)
{
- DeserializeChangesCore(reader, batch.CommitedAt);
+ DeserializeChangesCore(reader, batch.CommittedAt);
ValuesInvalidated();
ItselfLastChangedBy = batch.SequenceId;
}
diff --git a/src/Avalonia.Base/Rendering/Composition/Transport/Batch.cs b/src/Avalonia.Base/Rendering/Composition/Transport/Batch.cs
index d3e3664f84..803ea809c0 100644
--- a/src/Avalonia.Base/Rendering/Composition/Transport/Batch.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Transport/Batch.cs
@@ -29,7 +29,7 @@ namespace Avalonia.Rendering.Composition.Transport
public BatchStreamData Changes { get; private set; }
- public TimeSpan CommitedAt { get; set; }
+ public TimeSpan CommittedAt { get; set; }
public void Complete()
{
diff --git a/src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs b/src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs
index a3cad3cebd..5a88f0e91d 100644
--- a/src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using Avalonia.Rendering.Composition.Animations;
using Avalonia.Rendering.Composition.Server;
@@ -27,6 +28,37 @@ public record struct BatchStreamSegment
public int ElementCount { get; set; }
}
+
+// Unsafe.ReadUnaligned/Unsafe.WriteUnaligned are broken on arm,
+// see https://github.com/dotnet/runtime/issues/80068
+static unsafe class UnalignedMemoryHelper
+{
+ public static T ReadUnaligned(byte* src) where T : unmanaged
+ {
+#if NET6_0_OR_GREATER
+ Unsafe.SkipInit(out var rv);
+#else
+ T rv;
+#endif
+ UnalignedMemcpy((byte*)&rv, src, Unsafe.SizeOf());
+ return rv;
+ }
+
+ public static void WriteUnaligned(byte* dst, T value) where T : unmanaged
+ {
+ UnalignedMemcpy(dst, (byte*)&value, Unsafe.SizeOf());
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static unsafe void UnalignedMemcpy(byte* dst, byte* src, int count)
+ {
+ for (var c = 0; c < count; c++)
+ {
+ dst[c] = src[c];
+ }
+ }
+}
+
internal class BatchStreamWriter : IDisposable
{
private readonly BatchStreamData _output;
@@ -74,7 +106,15 @@ internal class BatchStreamWriter : IDisposable
var size = Unsafe.SizeOf();
if (_currentDataSegment.Data == IntPtr.Zero || _currentDataSegment.ElementCount + size > _memoryPool.BufferSize)
NextDataSegment();
- Unsafe.WriteUnaligned((byte*)_currentDataSegment.Data + _currentDataSegment.ElementCount, item);
+ var ptr = (byte*)_currentDataSegment.Data + _currentDataSegment.ElementCount;
+
+ // Unsafe.ReadUnaligned/Unsafe.WriteUnaligned are broken on arm32,
+ // see https://github.com/dotnet/runtime/issues/80068
+ if (RuntimeInformation.ProcessArchitecture == Architecture.Arm)
+ UnalignedMemoryHelper.WriteUnaligned(ptr, item);
+ else
+ Unsafe.WriteUnaligned(ptr, item);
+
_currentDataSegment.ElementCount += size;
}
@@ -125,7 +165,16 @@ internal class BatchStreamReader : IDisposable
if (_memoryOffset + size > _currentDataSegment.ElementCount)
throw new InvalidOperationException("Attempted to read more memory then left in the current segment");
- var rv = Unsafe.ReadUnaligned((byte*)_currentDataSegment.Data + _memoryOffset);
+ var ptr = (byte*)_currentDataSegment.Data + _memoryOffset;
+ T rv;
+
+ // Unsafe.ReadUnaligned/Unsafe.WriteUnaligned are broken on arm32,
+ // see https://github.com/dotnet/runtime/issues/80068
+ if (RuntimeInformation.ProcessArchitecture == Architecture.Arm)
+ rv = UnalignedMemoryHelper.ReadUnaligned(ptr);
+ else
+ rv = Unsafe.ReadUnaligned(ptr);
+
_memoryOffset += size;
if (_memoryOffset == _currentDataSegment.ElementCount)
{
diff --git a/src/Avalonia.Base/Rendering/ImmediateRenderer.cs b/src/Avalonia.Base/Rendering/ImmediateRenderer.cs
index 4909c78ed1..60b144e806 100644
--- a/src/Avalonia.Base/Rendering/ImmediateRenderer.cs
+++ b/src/Avalonia.Base/Rendering/ImmediateRenderer.cs
@@ -330,11 +330,11 @@ namespace Avalonia.Rendering
? visual is IVisualWithRoundRectClip roundClipVisual
? context.PushClip(new RoundedRect(bounds, roundClipVisual.ClipToBoundsRadius))
: context.PushClip(bounds)
- : default(DrawingContext.PushedState))
+ : default)
#pragma warning restore CS0618 // Type or member is obsolete
- using (visual.Clip != null ? context.PushGeometryClip(visual.Clip) : default(DrawingContext.PushedState))
- using (visual.OpacityMask != null ? context.PushOpacityMask(visual.OpacityMask, bounds) : default(DrawingContext.PushedState))
+ using (visual.Clip != null ? context.PushGeometryClip(visual.Clip) : default)
+ using (visual.OpacityMask != null ? context.PushOpacityMask(visual.OpacityMask, bounds) : default)
using (context.PushTransformContainer())
{
visual.Render(context);
diff --git a/src/Avalonia.Base/Rendering/RenderLoop.cs b/src/Avalonia.Base/Rendering/RenderLoop.cs
index 5a08bfc6a1..1f58ca3827 100644
--- a/src/Avalonia.Base/Rendering/RenderLoop.cs
+++ b/src/Avalonia.Base/Rendering/RenderLoop.cs
@@ -50,8 +50,7 @@ namespace Avalonia.Rendering
{
get
{
- return _timer ??= AvaloniaLocator.Current.GetService() ??
- throw new InvalidOperationException("Cannot locate IRenderTimer.");
+ return _timer ??= AvaloniaLocator.Current.GetRequiredService();
}
}
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/VisualNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/VisualNode.cs
index 6e05bf8631..b9491e6cbd 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/VisualNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/VisualNode.cs
@@ -303,7 +303,7 @@ namespace Avalonia.Rendering.SceneGraph
if (ClipToBounds)
{
context.Transform = Matrix.Identity;
- if (ClipToBoundsRadius.IsEmpty)
+ if (ClipToBoundsRadius.IsDefault)
context.PushClip(ClipBounds);
else
context.PushClip(new RoundedRect(ClipBounds, ClipToBoundsRadius));
diff --git a/src/Avalonia.Base/Rendering/Utilities/TileBrushCalculator.cs b/src/Avalonia.Base/Rendering/Utilities/TileBrushCalculator.cs
index af2c7f71dc..6b34b44337 100644
--- a/src/Avalonia.Base/Rendering/Utilities/TileBrushCalculator.cs
+++ b/src/Avalonia.Base/Rendering/Utilities/TileBrushCalculator.cs
@@ -109,7 +109,7 @@ namespace Avalonia.Rendering.Utilities
{
if (IntermediateTransform != Matrix.Identity)
return true;
- if (SourceRect.Position != default(Point))
+ if (SourceRect.Position != default)
return true;
if (SourceRect.Size.AspectRatio == _imageSize.AspectRatio)
return false;
diff --git a/src/Avalonia.Base/Threading/DispatcherTimer.cs b/src/Avalonia.Base/Threading/DispatcherTimer.cs
index f83e4e860e..f81229eb48 100644
--- a/src/Avalonia.Base/Threading/DispatcherTimer.cs
+++ b/src/Avalonia.Base/Threading/DispatcherTimer.cs
@@ -176,13 +176,7 @@ namespace Avalonia.Threading
{
if (!IsEnabled)
{
- var threading = AvaloniaLocator.Current.GetService();
-
- if (threading == null)
- {
- throw new Exception("Could not start timer: IPlatformThreadingInterface is not registered.");
- }
-
+ var threading = AvaloniaLocator.Current.GetRequiredService();
_timer = threading.StartTimer(_priority, Interval, InternalTick);
}
}
diff --git a/src/Avalonia.Base/Utilities/SingleOrDictionary.cs b/src/Avalonia.Base/Utilities/SingleOrDictionary.cs
index 00cc5864f5..0eb7ae2e31 100644
--- a/src/Avalonia.Base/Utilities/SingleOrDictionary.cs
+++ b/src/Avalonia.Base/Utilities/SingleOrDictionary.cs
@@ -42,7 +42,7 @@ namespace Avalonia.Utilities
{
if (!_singleValue.HasValue || !EqualityComparer.Default.Equals(_singleValue.Value.Key, key))
{
- value = default(TValue);
+ value = default;
return false;
}
else
diff --git a/src/Avalonia.Base/Utilities/StringTokenizer.cs b/src/Avalonia.Base/Utilities/StringTokenizer.cs
index 726c9735ef..aad742e02b 100644
--- a/src/Avalonia.Base/Utilities/StringTokenizer.cs
+++ b/src/Avalonia.Base/Utilities/StringTokenizer.cs
@@ -63,7 +63,7 @@ namespace Avalonia.Utilities
}
else
{
- result = default(Int32);
+ result = default;
return false;
}
}
@@ -87,7 +87,7 @@ namespace Avalonia.Utilities
}
else
{
- result = default(double);
+ result = default;
return false;
}
}
diff --git a/src/Avalonia.Base/Visual.cs b/src/Avalonia.Base/Visual.cs
index 7f2e8f6bcf..7fcb53bcea 100644
--- a/src/Avalonia.Base/Visual.cs
+++ b/src/Avalonia.Base/Visual.cs
@@ -484,6 +484,7 @@ namespace Avalonia
{
AttachToCompositor(compositingRenderer.Compositor);
}
+ InvalidateMirrorTransform();
OnAttachedToVisualTree(e);
AttachedToVisualTree?.Invoke(this, e);
InvalidateVisual();
diff --git a/src/Avalonia.Build.Tasks/ComInteropHelper.cs b/src/Avalonia.Build.Tasks/ComInteropHelper.cs
index 007231417d..c990741e1e 100644
--- a/src/Avalonia.Build.Tasks/ComInteropHelper.cs
+++ b/src/Avalonia.Build.Tasks/ComInteropHelper.cs
@@ -65,10 +65,8 @@ namespace Avalonia.Build.Tasks
{
Instruction instruction = instructions[i];
- if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodReference)
+ if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodReference methodDescription)
{
- var methodDescription = (MethodReference)instruction.Operand;
-
if (methodDescription.Name.StartsWith("Calli") && methodDescription.DeclaringType.Name == "LocalInterop")
{
var callSite = new CallSite(methodDescription.ReturnType) { CallingConvention = MethodCallingConvention.StdCall };
diff --git a/src/Avalonia.Controls.ColorPicker/ColorPalettes/FlatColorPalette.cs b/src/Avalonia.Controls.ColorPicker/ColorPalettes/FlatColorPalette.cs
index 2cc5b99b2e..aaf272c6d2 100644
--- a/src/Avalonia.Controls.ColorPicker/ColorPalettes/FlatColorPalette.cs
+++ b/src/Avalonia.Controls.ColorPicker/ColorPalettes/FlatColorPalette.cs
@@ -289,8 +289,8 @@ namespace Avalonia.Controls
};
// See: https://htmlcolorcodes.com/assets/downloads/flat-design-colors/flat-design-color-chart.png
- protected static Color[,]? _colorChart = null;
- protected static object _colorChartMutex = new object();
+ private static Color[,]? _colorChart = null;
+ private static readonly object _colorChartMutex = new();
///
/// Initializes all color chart colors.
diff --git a/src/Avalonia.Controls.ColorPicker/ColorPalettes/FlatHalfColorPalette.cs b/src/Avalonia.Controls.ColorPicker/ColorPalettes/FlatHalfColorPalette.cs
index 2758124fae..4a30fb6cb4 100644
--- a/src/Avalonia.Controls.ColorPicker/ColorPalettes/FlatHalfColorPalette.cs
+++ b/src/Avalonia.Controls.ColorPicker/ColorPalettes/FlatHalfColorPalette.cs
@@ -10,8 +10,8 @@ namespace Avalonia.Controls
///
public class FlatHalfColorPalette : IColorPalette
{
- protected static Color[,]? _colorChart = null;
- protected static object _colorChartMutex = new object();
+ private static Color[,]? _colorChart = null;
+ private static readonly object _colorChartMutex = new();
///
/// Initializes all color chart colors.
diff --git a/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs b/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs
index d009926bc5..d4b904163c 100644
--- a/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs
+++ b/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs
@@ -344,8 +344,8 @@ namespace Avalonia.Controls
// See: https://material.io/design/color/the-color-system.html#tools-for-picking-colors
// This is a reduced palette for uniformity
- protected static Color[,]? _colorChart = null;
- protected static object _colorChartMutex = new object();
+ private static Color[,]? _colorChart = null;
+ private static readonly object _colorChartMutex = new();
///
/// Initializes all color chart colors.
diff --git a/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialHalfColorPalette.cs b/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialHalfColorPalette.cs
index 01d44aa65d..4432642675 100644
--- a/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialHalfColorPalette.cs
+++ b/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialHalfColorPalette.cs
@@ -10,8 +10,8 @@ namespace Avalonia.Controls
///
public class MaterialHalfColorPalette : IColorPalette
{
- protected static Color[,]? _colorChart = null;
- protected static object _colorChartMutex = new object();
+ private static Color[,]? _colorChart = null;
+ private static readonly object _colorChartMutex = new();
///
/// Initializes all color chart colors.
diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs
index b7546a4625..f35124ee0a 100644
--- a/src/Avalonia.Controls.DataGrid/DataGrid.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs
@@ -52,15 +52,10 @@ namespace Avalonia.Controls
private const string DATAGRID_elementTopLeftCornerHeaderName = "PART_TopLeftCornerHeader";
private const string DATAGRID_elementTopRightCornerHeaderName = "PART_TopRightCornerHeader";
private const string DATAGRID_elementBottomRightCornerHeaderName = "PART_BottomRightCorner";
- private const string DATAGRID_elementValidationSummary = "PART_ValidationSummary";
private const string DATAGRID_elementVerticalScrollbarName = "PART_VerticalScrollbar";
-
- private const bool DATAGRID_defaultAutoGenerateColumns = true;
internal const bool DATAGRID_defaultCanUserReorderColumns = true;
internal const bool DATAGRID_defaultCanUserResizeColumns = true;
internal const bool DATAGRID_defaultCanUserSortColumns = true;
- private const DataGridRowDetailsVisibilityMode DATAGRID_defaultRowDetailsVisibility = DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
- private const DataGridSelectionMode DATAGRID_defaultSelectionMode = DataGridSelectionMode.Extended;
///
/// The default order to use for columns when there is no
@@ -1124,7 +1119,7 @@ namespace Avalonia.Controls
EnsureColumnHeadersVisibility();
if (!newValueCols)
{
- _columnHeadersPresenter.Measure(default(Size));
+ _columnHeadersPresenter.Measure(default);
}
else
{
@@ -1165,7 +1160,7 @@ namespace Avalonia.Controls
_topLeftCornerHeader.IsVisible = newValueRows && newValueCols;
if (_topLeftCornerHeader.IsVisible)
{
- _topLeftCornerHeader.Measure(default(Size));
+ _topLeftCornerHeader.Measure(default);
}
}
@@ -3300,7 +3295,7 @@ namespace Avalonia.Controls
newCell.IsVisible = column.IsVisible;
if (row.OwningGrid.CellTheme is {} cellTheme)
{
- newCell.SetValue(ThemeProperty, cellTheme, BindingPriority.TemplatedParent);
+ newCell.SetValue(ThemeProperty, cellTheme, BindingPriority.Template);
}
}
row.Cells.Insert(column.Index, newCell);
@@ -4158,6 +4153,7 @@ namespace Avalonia.Controls
if (exitEditingMode)
{
+ CurrentColumn.EndCellEditInternal();
_editingColumnIndex = -1;
editingCell.UpdatePseudoClasses();
diff --git a/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs
index c308312398..39c1e4c118 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs
@@ -31,7 +31,7 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static StyledProperty IsThreeStateProperty =
+ public static readonly StyledProperty IsThreeStateProperty =
CheckBox.IsThreeStateProperty.AddOwner();
///
diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
index 75101dc487..d1e1efdd85 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs
@@ -185,7 +185,7 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static StyledProperty IsVisibleProperty =
+ public static readonly StyledProperty IsVisibleProperty =
Control.IsVisibleProperty.AddOwner();
///
@@ -800,11 +800,22 @@ namespace Avalonia.Controls
protected internal virtual void RefreshCellContent(Control element, string propertyName)
{ }
+ ///
+ /// When overridden in a derived class, called when a cell in the column exits editing mode.
+ ///
+ protected virtual void EndCellEdit()
+ { }
+
internal void CancelCellEditInternal(Control editingElement, object uneditedValue)
{
CancelCellEdit(editingElement, uneditedValue);
}
+ internal void EndCellEditInternal()
+ {
+ EndCellEdit();
+ }
+
///
/// Coerces a DataGridLength to a valid value. If any value components are double.NaN, this method
/// coerces them to a proper initial value. For star columns, the desired width is calculated based
@@ -897,7 +908,7 @@ namespace Avalonia.Controls
result[!ContentControl.ContentTemplateProperty] = this[!HeaderTemplateProperty];
if (OwningGrid.ColumnHeaderTheme is {} columnTheme)
{
- result.SetValue(StyledElement.ThemeProperty, columnTheme, BindingPriority.TemplatedParent);
+ result.SetValue(StyledElement.ThemeProperty, columnTheme, BindingPriority.Template);
}
return result;
diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
index 252868847a..b3e106a7bf 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
@@ -673,7 +673,7 @@ namespace Avalonia.Controls
};
if (OwningGrid.ColumnHeaderTheme is {} columnHeaderTheme)
{
- dragIndicator.SetValue(ThemeProperty, columnHeaderTheme, BindingPriority.TemplatedParent);
+ dragIndicator.SetValue(ThemeProperty, columnHeaderTheme, BindingPriority.Template);
}
dragIndicator.PseudoClasses.Add(":dragIndicator");
diff --git a/src/Avalonia.Controls.DataGrid/DataGridRow.cs b/src/Avalonia.Controls.DataGrid/DataGridRow.cs
index c4010487af..ea9b2fe972 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridRow.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridRow.cs
@@ -254,7 +254,7 @@ namespace Avalonia.Controls
};
if (OwningGrid.CellTheme is {} cellTheme)
{
- _fillerCell.SetValue(ThemeProperty, cellTheme, BindingPriority.TemplatedParent);
+ _fillerCell.SetValue(ThemeProperty, cellTheme, BindingPriority.Template);
}
if (_cellsElement != null)
{
diff --git a/src/Avalonia.Controls.DataGrid/DataGridRows.cs b/src/Avalonia.Controls.DataGrid/DataGridRows.cs
index 4d3bccee70..00e035270c 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridRows.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridRows.cs
@@ -1029,7 +1029,7 @@ namespace Avalonia.Controls
dataGridRow.DataContext = dataContext;
if (RowTheme is {} rowTheme)
{
- dataGridRow.SetValue(ThemeProperty, rowTheme, BindingPriority.TemplatedParent);
+ dataGridRow.SetValue(ThemeProperty, rowTheme, BindingPriority.Template);
}
CompleteCellsCollection(dataGridRow);
@@ -2743,7 +2743,7 @@ namespace Avalonia.Controls
groupHeader.Level = rowGroupInfo.Level;
if (RowGroupTheme is {} rowGroupTheme)
{
- groupHeader.SetValue(ThemeProperty, rowGroupTheme, BindingPriority.TemplatedParent);
+ groupHeader.SetValue(ThemeProperty, rowGroupTheme, BindingPriority.Template);
}
// Set the RowGroupHeader's PropertyName. Unfortunately, CollectionViewGroup doesn't have this
diff --git a/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs
index 24ae358dcc..516e9cf6c2 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs
@@ -55,17 +55,25 @@ namespace Avalonia.Controls
get => _cellEditingCellTemplate;
set => SetAndRaise(CellEditingTemplateProperty, ref _cellEditingCellTemplate, value);
}
-
- private static void OnCellTemplateChanged(AvaloniaPropertyChangedEventArgs e)
+
+ private bool _forceGenerateCellFromTemplate;
+
+ protected override void EndCellEdit()
{
- var oldValue = (IDataTemplate)e.OldValue;
- var value = (IDataTemplate)e.NewValue;
+ //the next call to generate element should not resuse the current content as we need to exit edit mode
+ _forceGenerateCellFromTemplate = true;
+ base.EndCellEdit();
}
protected override Control GenerateElement(DataGridCell cell, object dataItem)
{
if (CellTemplate != null)
{
+ if (_forceGenerateCellFromTemplate)
+ {
+ _forceGenerateCellFromTemplate = false;
+ return CellTemplate.Build(dataItem);
+ }
return (CellTemplate is IRecyclingDataTemplate recyclingDataTemplate)
? recyclingDataTemplate.Build(dataItem, cell.Content as Control)
: CellTemplate.Build(dataItem);
diff --git a/src/Avalonia.Controls.DataGrid/IndexToValueTable.cs b/src/Avalonia.Controls.DataGrid/IndexToValueTable.cs
index 65c3af344c..68a2fc562f 100644
--- a/src/Avalonia.Controls.DataGrid/IndexToValueTable.cs
+++ b/src/Avalonia.Controls.DataGrid/IndexToValueTable.cs
@@ -422,7 +422,7 @@ namespace Avalonia.Controls
else
{
found = false;
- return default(T);
+ return default;
}
}
diff --git a/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs
index 4b88f6b537..22b5f8236d 100644
--- a/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs
+++ b/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel;
using Avalonia.Metadata;
namespace Avalonia.Controls.ApplicationLifetimes
@@ -19,7 +18,7 @@ namespace Avalonia.Controls.ApplicationLifetimes
///
/// Gets the arguments passed to the
- ///
+ ///
/// method.
///
string[]? Args { get; }
diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs
index c84e96ed6d..98885e11ca 100644
--- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs
+++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs
@@ -474,6 +474,7 @@ namespace Avalonia.Controls
FilterModeProperty.Changed.AddClassHandler((x,e) => x.OnFilterModePropertyChanged(e));
ItemFilterProperty.Changed.AddClassHandler((x,e) => x.OnItemFilterPropertyChanged(e));
ItemsProperty.Changed.AddClassHandler((x,e) => x.OnItemsPropertyChanged(e));
+ ItemTemplateProperty.Changed.AddClassHandler((x,e) => x.OnItemTemplatePropertyChanged(e));
IsEnabledProperty.Changed.AddClassHandler((x,e) => x.OnControlIsEnabledChanged(e));
}
diff --git a/src/Avalonia.Controls/BorderVisual.cs b/src/Avalonia.Controls/BorderVisual.cs
index 7afbf9edcf..b0e5c30e2f 100644
--- a/src/Avalonia.Controls/BorderVisual.cs
+++ b/src/Avalonia.Controls/BorderVisual.cs
@@ -50,7 +50,7 @@ class CompositionBorderVisual : CompositionDrawListVisual
if (ClipToBounds)
{
var clipRect = Root!.SnapToDevicePixels(new Rect(new Size(Size.X, Size.Y)));
- if (_cornerRadius.IsEmpty)
+ if (_cornerRadius.IsDefault)
canvas.PushClip(clipRect);
else
canvas.PushClip(new RoundedRect(clipRect, _cornerRadius));
@@ -63,9 +63,9 @@ class CompositionBorderVisual : CompositionDrawListVisual
}
- protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan commitedAt)
+ protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan committedAt)
{
- base.DeserializeChangesCore(reader, commitedAt);
+ base.DeserializeChangesCore(reader, committedAt);
if (reader.Read())
_cornerRadius = reader.Read();
}
@@ -73,4 +73,4 @@ class CompositionBorderVisual : CompositionDrawListVisual
protected override bool HandlesClipToBounds => true;
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Controls/ContentControl.cs b/src/Avalonia.Controls/ContentControl.cs
index b8a45e102f..d47a7a7809 100644
--- a/src/Avalonia.Controls/ContentControl.cs
+++ b/src/Avalonia.Controls/ContentControl.cs
@@ -116,14 +116,19 @@ namespace Avalonia.Controls
return false;
}
- private void ContentChanged(AvaloniaPropertyChangedEventArgs e)
+ protected virtual void ContentChanged(AvaloniaPropertyChangedEventArgs e)
{
- if (e.OldValue is ILogical oldChild)
+ UpdateLogicalTree(e.OldValue, e.NewValue);
+ }
+
+ protected void UpdateLogicalTree(object? toRemove, object? toAdd)
+ {
+ if (toRemove is ILogical oldChild)
{
LogicalChildren.Remove(oldChild);
}
- if (e.NewValue is ILogical newChild)
+ if (toAdd is ILogical newChild)
{
LogicalChildren.Add(newChild);
}
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index 88c9823952..ed24c3c7c2 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -366,25 +366,30 @@ namespace Avalonia.Controls
{
base.OnAttachedToVisualTreeCore(e);
+ AddHandler(Gestures.HoldingEvent, OnHoldEvent);
+
InitializeIfNeeded();
ScheduleOnLoadedCore();
}
- ///
- protected sealed override void OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e)
+ private void OnHoldEvent(object? sender, HoldingRoutedEventArgs e)
{
- base.OnDetachedFromVisualTreeCore(e);
-
- OnUnloadedCore();
+ if(e.HoldingState == HoldingState.Started)
+ {
+ // Trigger ContentRequest when hold has started
+ RaiseEvent(new ContextRequestedEventArgs());
+ }
}
///
- protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ protected sealed override void OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e)
{
- base.OnAttachedToVisualTree(e);
+ base.OnDetachedFromVisualTreeCore(e);
+
+ RemoveHandler(Gestures.HoldingEvent, OnHoldEvent);
- InvalidateMirrorTransform();
+ OnUnloadedCore();
}
///
diff --git a/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs b/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs
index 9fddb91231..343b628fb9 100644
--- a/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs
+++ b/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs
@@ -8,6 +8,6 @@
///
/// Provides access to the internal for use in DevTools.
///
- public static AvaloniaProperty ToolTipProperty = ToolTip.ToolTipProperty;
+ public static readonly AvaloniaProperty ToolTipProperty = ToolTip.ToolTipProperty;
}
}
diff --git a/src/Avalonia.Controls/Platform/InProcessDragSource.cs b/src/Avalonia.Controls/Platform/InProcessDragSource.cs
index 1a262aa493..bfd8bd73cb 100644
--- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs
+++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs
@@ -39,7 +39,7 @@ namespace Avalonia.Platform
{
_draggedData = data;
_lastRoot = null;
- _lastPosition = default(Point);
+ _lastPosition = default;
_allowedEffects = allowedEffects;
var inputObserver = new AnonymousObserver(arg =>
diff --git a/src/Avalonia.Controls/Platform/PlatformManager.cs b/src/Avalonia.Controls/Platform/PlatformManager.cs
index d678911e1f..6f043463d4 100644
--- a/src/Avalonia.Controls/Platform/PlatformManager.cs
+++ b/src/Avalonia.Controls/Platform/PlatformManager.cs
@@ -26,21 +26,14 @@ namespace Avalonia.Controls.Platform
public static IWindowImpl CreateWindow()
{
- var platform = AvaloniaLocator.Current.GetService();
-
- if (platform == null)
- {
- throw new Exception("Could not CreateWindow(): IWindowingPlatform is not registered.");
- }
+ var platform = AvaloniaLocator.Current.GetRequiredService();
return s_designerMode ? platform.CreateEmbeddableWindow() : platform.CreateWindow();
}
public static IWindowImpl CreateEmbeddableWindow()
{
- var platform = AvaloniaLocator.Current.GetService();
- if (platform == null)
- throw new Exception("Could not CreateEmbeddableWindow(): IWindowingPlatform is not registered.");
+ var platform = AvaloniaLocator.Current.GetRequiredService();
return platform.CreateEmbeddableWindow();
}
}
diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
index 254515755d..5a691ce665 100644
--- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
@@ -92,6 +92,7 @@ namespace Avalonia.Controls.Presenters
{
AddHandler(RequestBringIntoViewEvent, BringIntoViewRequested);
AddHandler(Gestures.ScrollGestureEvent, OnScrollGesture);
+ AddHandler(Gestures.ScrollGestureEndedEvent, OnScrollGestureEnded);
this.GetObservable(ChildProperty).Subscribe(UpdateScrollableSubscription);
}
@@ -498,7 +499,7 @@ namespace Avalonia.Controls.Presenters
if (e.OldValue != null)
{
- Offset = default(Vector);
+ Offset = default;
}
}
@@ -540,7 +541,7 @@ namespace Avalonia.Controls.Presenters
if (logicalScroll != scrollable.IsLogicalScrollEnabled)
{
UpdateScrollableSubscription(Child);
- Offset = default(Vector);
+ Offset = default;
InvalidateMeasure();
}
else if (scrollable.IsLogicalScrollEnabled)
diff --git a/src/Avalonia.Controls/PullToRefresh/ScrollViewerIRefreshInfoProviderAdapter.cs b/src/Avalonia.Controls/PullToRefresh/ScrollViewerIRefreshInfoProviderAdapter.cs
index c3aebc82c5..844973bd28 100644
--- a/src/Avalonia.Controls/PullToRefresh/ScrollViewerIRefreshInfoProviderAdapter.cs
+++ b/src/Avalonia.Controls/PullToRefresh/ScrollViewerIRefreshInfoProviderAdapter.cs
@@ -197,12 +197,12 @@ namespace Avalonia.Controls.PullToRefresh
throw new ArgumentException(nameof(_scrollViewer), "Adaptee's content property must be a Visual");
}
- if (content.Parent is not InputElement)
+ if (content.Parent is not InputElement parent)
{
throw new ArgumentException(nameof(_scrollViewer), "Adaptee's content parent must be an InputElement");
}
- MakeInteractionSource(content.Parent as InputElement);
+ MakeInteractionSource(parent);
if (_scrollViewer != null)
{
diff --git a/src/Avalonia.Controls/Repeater/ViewportManager.cs b/src/Avalonia.Controls/Repeater/ViewportManager.cs
index d7f24ec537..56e0cda8fe 100644
--- a/src/Avalonia.Controls/Repeater/ViewportManager.cs
+++ b/src/Avalonia.Controls/Repeater/ViewportManager.cs
@@ -116,22 +116,6 @@ namespace Avalonia.Controls
}
}
}
-
- private Rect GetLayoutVisibleWindowDiscardAnchor()
- {
- var visibleWindow = _visibleWindow;
-
- if (HasScroller)
- {
- visibleWindow = new Rect(
- visibleWindow.X + _layoutExtent.X + _expectedViewportShift.X + _unshiftableShift.X,
- visibleWindow.Y + _layoutExtent.Y + _expectedViewportShift.Y + _unshiftableShift.Y,
- visibleWindow.Width,
- visibleWindow.Height);
- }
-
- return visibleWindow;
- }
public Rect GetLayoutVisibleWindow()
{
diff --git a/src/Avalonia.Controls/SelectableTextBlock.cs b/src/Avalonia.Controls/SelectableTextBlock.cs
index b343439f98..f4c4d54951 100644
--- a/src/Avalonia.Controls/SelectableTextBlock.cs
+++ b/src/Avalonia.Controls/SelectableTextBlock.cs
@@ -300,7 +300,11 @@ namespace Avalonia.Controls
_wordSelectionStart = SelectionStart;
- SelectionEnd = StringUtils.NextWord(text, index);
+ if (!StringUtils.IsEndOfWord(text, index))
+ {
+ SelectionEnd = StringUtils.NextWord(text, index);
+ }
+
break;
case 3:
_wordSelectionStart = -1;
diff --git a/src/Avalonia.Controls/Templates/FuncTreeDataTemplate`1.cs b/src/Avalonia.Controls/Templates/FuncTreeDataTemplate`1.cs
index d4ecdd6cf0..a093d976f7 100644
--- a/src/Avalonia.Controls/Templates/FuncTreeDataTemplate`1.cs
+++ b/src/Avalonia.Controls/Templates/FuncTreeDataTemplate`1.cs
@@ -59,7 +59,7 @@ namespace Avalonia.Controls.Templates
/// The untyped function.
private static Func CastMatch(Func f)
{
- return o => (o is T) && f((T)o);
+ return o => o is T arg && f(arg);
}
///
@@ -72,7 +72,7 @@ namespace Avalonia.Controls.Templates
{
return (o, s) => f((T)o!, s);
}
-
+
///
/// Casts a function with a typed parameter to an untyped function.
///
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index 6938027510..f388dc871e 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -981,7 +981,7 @@ namespace Avalonia.Controls
}
}
- length += grapheme.Text.Length;
+ length += grapheme.Length;
}
if (length < input.Length)
@@ -1475,7 +1475,11 @@ namespace Avalonia.Controls
_wordSelectionStart = SelectionStart;
- SelectionEnd = StringUtils.NextWord(text, index);
+ if (!StringUtils.IsEndOfWord(text, index))
+ {
+ SelectionEnd = StringUtils.NextWord(text, index);
+ }
+
break;
case 3:
_wordSelectionStart = -1;
diff --git a/src/Avalonia.Controls/TransitioningContentControl.cs b/src/Avalonia.Controls/TransitioningContentControl.cs
index 70b21b7248..2e0a36ad19 100644
--- a/src/Avalonia.Controls/TransitioningContentControl.cs
+++ b/src/Avalonia.Controls/TransitioningContentControl.cs
@@ -69,6 +69,15 @@ public class TransitioningContentControl : ContentControl
{
Dispatcher.UIThread.Post(() => UpdateContentWithTransition(Content));
}
+ else if (change.Property == CurrentContentProperty)
+ {
+ UpdateLogicalTree(change.OldValue, change.NewValue);
+ }
+ }
+
+ protected override void ContentChanged(AvaloniaPropertyChangedEventArgs e)
+ {
+ // We do nothing becuse we should not remove old Content until the animation is over
}
///
diff --git a/src/Avalonia.Controls/Utils/StringUtils.cs b/src/Avalonia.Controls/Utils/StringUtils.cs
index b2e56434b2..6c459d7985 100644
--- a/src/Avalonia.Controls/Utils/StringUtils.cs
+++ b/src/Avalonia.Controls/Utils/StringUtils.cs
@@ -67,6 +67,55 @@ namespace Avalonia.Controls.Utils
}
}
+ public static bool IsEndOfWord(string text, int index)
+ {
+ if (index >= text.Length)
+ {
+ return true;
+ }
+
+ var codepoint = new Codepoint(text[index]);
+
+ if (!codepoint.IsWhiteSpace)
+ {
+ return false;
+ }
+ // A 'word' starts with an AlphaNumeric or some punctuation symbols immediately
+ // preceeded by lwsp.
+ if (index > 0)
+ {
+ var nextCodePoint = new Codepoint(text[index + 1]);
+
+ if (nextCodePoint.IsBreakChar)
+ {
+ return true;
+ }
+ }
+
+ switch (codepoint.GeneralCategory)
+ {
+ case GeneralCategory.LowercaseLetter:
+ case GeneralCategory.TitlecaseLetter:
+ case GeneralCategory.UppercaseLetter:
+ case GeneralCategory.DecimalNumber:
+ case GeneralCategory.LetterNumber:
+ case GeneralCategory.OtherNumber:
+ case GeneralCategory.DashPunctuation:
+ case GeneralCategory.InitialPunctuation:
+ case GeneralCategory.OpenPunctuation:
+ case GeneralCategory.CurrencySymbol:
+ case GeneralCategory.MathSymbol:
+ return false;
+
+ // TODO: How do you do this in .NET?
+ // case UnicodeCategory.OtherPunctuation:
+ // // words cannot start with '.', but they can start with '&' or '*' (for example)
+ // return g_unichar_break_type(buffer->text[index]) == G_UNICODE_BREAK_ALPHABETIC;
+ default:
+ return true;
+ }
+ }
+
public static int PreviousWord(string text, int cursor)
{
if (string.IsNullOrEmpty(text))
diff --git a/src/Avalonia.Controls/Utils/UndoRedoHelper.cs b/src/Avalonia.Controls/Utils/UndoRedoHelper.cs
index 6ff72751a6..7b663dd017 100644
--- a/src/Avalonia.Controls/Utils/UndoRedoHelper.cs
+++ b/src/Avalonia.Controls/Utils/UndoRedoHelper.cs
@@ -49,7 +49,7 @@ namespace Avalonia.Controls.Utils
public bool TryGetLastState(out TState? _state)
{
- _state = default(TState);
+ _state = default;
if (!IsLastState)
return false;
diff --git a/src/Avalonia.DesignerSupport/DesignWindowLoader.cs b/src/Avalonia.DesignerSupport/DesignWindowLoader.cs
index b4cfffcdca..eff190c39e 100644
--- a/src/Avalonia.DesignerSupport/DesignWindowLoader.cs
+++ b/src/Avalonia.DesignerSupport/DesignWindowLoader.cs
@@ -18,12 +18,9 @@ namespace Avalonia.DesignerSupport
Control control;
using (PlatformManager.DesignerMode())
{
- var loader = AvaloniaLocator.Current.GetService();
+ var loader = AvaloniaLocator.Current.GetRequiredService();
var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml));
- if (loader == null)
- throw new XamlLoadException("Runtime XAML loader is not registered");
-
Uri baseUri = null;
if (assemblyPath != null)
{
diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs
index 5cf9e17ecf..8bff9ccde0 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs
@@ -33,12 +33,12 @@ namespace Avalonia.Diagnostics.ViewModels
{
_avaloniaObject = avaloniaObject;
- TreePage = treePage;
- Layout = avaloniaObject is Visual
- ? new ControlLayoutViewModel((Visual)avaloniaObject)
+ TreePage = treePage;
+ Layout = avaloniaObject is Visual visual
+ ? new ControlLayoutViewModel(visual)
: default;
- NavigateToProperty(_avaloniaObject, (_avaloniaObject as Control)?.Name ?? _avaloniaObject.ToString());
+ NavigateToProperty(_avaloniaObject, (_avaloniaObject as Control)?.Name ?? _avaloniaObject.ToString());
AppliedStyles = new ObservableCollection();
PseudoClasses = new ObservableCollection();
diff --git a/src/Avalonia.Dialogs/Internal/ManagedFileChooserViewModel.cs b/src/Avalonia.Dialogs/Internal/ManagedFileChooserViewModel.cs
index a2f8af0575..df67c06b73 100644
--- a/src/Avalonia.Dialogs/Internal/ManagedFileChooserViewModel.cs
+++ b/src/Avalonia.Dialogs/Internal/ManagedFileChooserViewModel.cs
@@ -116,7 +116,7 @@ namespace Avalonia.Dialogs.Internal
?? new ManagedFileChooserSources();
var sub1 = AvaloniaLocator.Current
- .GetService()
+ .GetRequiredService()
.Listen(ManagedFileChooserSources.MountedVolumes);
var sub2 = ManagedFileChooserSources.MountedVolumes.GetWeakCollectionChangedObservable()
diff --git a/src/Avalonia.FreeDesktop/DBusMenu.cs b/src/Avalonia.FreeDesktop/DBusMenu.cs
index 3a1c65e7c9..7e22988270 100644
--- a/src/Avalonia.FreeDesktop/DBusMenu.cs
+++ b/src/Avalonia.FreeDesktop/DBusMenu.cs
@@ -36,10 +36,10 @@ namespace Avalonia.FreeDesktop.DBusMenu
[Dictionary]
class DBusMenuProperties
{
- public uint Version { get; set; } = default (uint);
- public string? TextDirection { get; set; } = default (string);
- public string? Status { get; set; } = default (string);
- public string[]? IconThemePath { get; set; } = default (string[]);
+ public uint Version { get; set; } = default;
+ public string? TextDirection { get; set; } = default;
+ public string? Status { get; set; } = default;
+ public string[]? IconThemePath { get; set; } = default;
}
diff --git a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
index a9136c2c99..9b38c150fa 100644
--- a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
+++ b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
@@ -13,4 +13,9 @@
+
+
+
+
+
diff --git a/src/Avalonia.OpenGL/Egl/EglInterface.cs b/src/Avalonia.OpenGL/Egl/EglInterface.cs
index a913c05996..06aafb4f57 100644
--- a/src/Avalonia.OpenGL/Egl/EglInterface.cs
+++ b/src/Avalonia.OpenGL/Egl/EglInterface.cs
@@ -35,7 +35,7 @@ namespace Avalonia.OpenGL.Egl
static Func Load(string library)
{
- var dyn = AvaloniaLocator.Current.GetService();
+ var dyn = AvaloniaLocator.Current.GetRequiredService();
var lib = dyn.LoadLibrary(library);
return (s) => dyn.GetProcAddress(lib, s, true);
}
diff --git a/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml b/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml
index 9abcf5d32b..28f8649e2d 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CheckBox.xaml
@@ -50,7 +50,8 @@
Opacity="0"
Fill="{DynamicResource CheckBoxCheckGlyphForegroundUnchecked}"
Stretch="Uniform"
- VerticalAlignment="Center" />
+ VerticalAlignment="Center"
+ FlowDirection="LeftToRight" />
@@ -146,7 +147,6 @@
-
diff --git a/src/Avalonia.X11/Avalonia.X11.csproj b/src/Avalonia.X11/Avalonia.X11.csproj
index c762349c1c..061c516ef6 100644
--- a/src/Avalonia.X11/Avalonia.X11.csproj
+++ b/src/Avalonia.X11/Avalonia.X11.csproj
@@ -10,7 +10,12 @@
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.X11/X11Framebuffer.cs b/src/Avalonia.X11/X11Framebuffer.cs
index 94f930e9ec..a9fedff8b5 100644
--- a/src/Avalonia.X11/X11Framebuffer.cs
+++ b/src/Avalonia.X11/X11Framebuffer.cs
@@ -25,7 +25,7 @@ namespace Avalonia.X11
RowBytes = width * 4;
Dpi = new Vector(96, 96) * factor;
Format = PixelFormat.Bgra8888;
- _blob = AvaloniaLocator.Current.GetService().AllocBlob(RowBytes * height);
+ _blob = AvaloniaLocator.Current.GetRequiredService().AllocBlob(RowBytes * height);
Address = _blob.Address;
}
diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs
index 9692e0a384..0f9ef72a3f 100644
--- a/src/Avalonia.X11/X11Platform.cs
+++ b/src/Avalonia.X11/X11Platform.cs
@@ -105,7 +105,7 @@ namespace Avalonia.X11
var gl = AvaloniaLocator.Current.GetService();
if (options.UseCompositor)
- Compositor = new Compositor(AvaloniaLocator.Current.GetService()!, gl);
+ Compositor = new Compositor(AvaloniaLocator.Current.GetRequiredService(), gl);
else
RenderInterface = new(gl);
diff --git a/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj b/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
index a2f1b55b6f..a9cad0538f 100644
--- a/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
+++ b/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
@@ -7,6 +7,7 @@
+
diff --git a/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs b/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs
index 2cc74273c0..68efea31d6 100644
--- a/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs
+++ b/src/Browser/Avalonia.Browser.Blazor/AvaloniaView.cs
@@ -8,9 +8,10 @@ using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using BrowserView = Avalonia.Browser.AvaloniaView;
+[assembly: SupportedOSPlatform("browser")]
+
namespace Avalonia.Browser.Blazor;
-[SupportedOSPlatform("browser")]
public class AvaloniaView : ComponentBase
{
private Browser.AvaloniaView? _browserView;
diff --git a/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs b/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
index 5e101f7f17..a7bb5a62df 100644
--- a/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
+++ b/src/Browser/Avalonia.Browser.Blazor/BlazorSingleViewLifetime.cs
@@ -5,7 +5,6 @@ using Avalonia.Controls.ApplicationLifetimes;
namespace Avalonia.Browser.Blazor;
-[SupportedOSPlatform("browser")]
public static class WebAppBuilder
{
public static AppBuilder SetupWithSingleViewLifetime(
diff --git a/src/Browser/Avalonia.Browser/Avalonia.Browser.csproj b/src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
index 014d387cb2..2fc3cc885a 100644
--- a/src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
+++ b/src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
@@ -1,7 +1,6 @@
net7.0
- preview
enable
true
diff --git a/src/Browser/Avalonia.Browser/AvaloniaView.cs b/src/Browser/Avalonia.Browser/AvaloniaView.cs
index abda618b0d..294216ee03 100644
--- a/src/Browser/Avalonia.Browser/AvaloniaView.cs
+++ b/src/Browser/Avalonia.Browser/AvaloniaView.cs
@@ -18,7 +18,6 @@ using SkiaSharp;
namespace Avalonia.Browser
{
- [System.Runtime.Versioning.SupportedOSPlatform("browser")] // gets rid of callsite warnings
public partial class AvaloniaView : ITextInputMethodImpl
{
private static readonly PooledList s_intermediatePointsPooledList = new(ClearMode.Never);
@@ -107,7 +106,7 @@ namespace Avalonia.Browser
_dpi = DomHelper.ObserveDpi(OnDpiChanged);
- _useGL = AvaloniaLocator.Current.GetRequiredService() != null;
+ _useGL = AvaloniaLocator.Current.GetService() != null;
if (_useGL)
{
diff --git a/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs b/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
index 3adcb8e539..add69760ee 100644
--- a/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
+++ b/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
@@ -5,7 +5,6 @@ using System.Runtime.Versioning;
namespace Avalonia.Browser;
-[SupportedOSPlatform("browser")]
public class BrowserSingleViewLifetime : ISingleViewApplicationLifetime
{
public AvaloniaView? View;
@@ -22,7 +21,6 @@ public class BrowserPlatformOptions
public Func FrameworkAssetPathResolver { get; set; } = new(fileName => $"./{fileName}");
}
-[SupportedOSPlatform("browser")]
public static class WebAppBuilder
{
public static AppBuilder SetupBrowserApp(
diff --git a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs
index 85725e4cf3..4e6be3268b 100644
--- a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs
+++ b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Runtime.Versioning;
using Avalonia.Browser.Skia;
using Avalonia.Browser.Storage;
using Avalonia.Controls;
@@ -14,9 +15,10 @@ using Avalonia.Platform.Storage;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
+[assembly: SupportedOSPlatform("browser")]
+
namespace Avalonia.Browser
{
- [System.Runtime.Versioning.SupportedOSPlatform("browser")] // gets rid of callsite warnings
internal class BrowserTopLevelImpl : ITopLevelImplWithTextInputMethod, ITopLevelImplWithNativeControlHost, ITopLevelImplWithStorageProvider
{
private Size _clientSize;
@@ -201,7 +203,11 @@ namespace Avalonia.Browser
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel)
{
-
+ if (transparencyLevel == WindowTransparencyLevel.None
+ || transparencyLevel == WindowTransparencyLevel.Transparent)
+ {
+ TransparencyLevel = transparencyLevel;
+ }
}
public Size ClientSize => _clientSize;
@@ -221,7 +227,7 @@ namespace Avalonia.Browser
public IMouseDevice MouseDevice { get; } = new MouseDevice();
public IKeyboardDevice KeyboardDevice { get; } = BrowserWindowingPlatform.Keyboard;
- public WindowTransparencyLevel TransparencyLevel { get; }
+ public WindowTransparencyLevel TransparencyLevel { get; private set; }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; }
public ITextInputMethodImpl TextInputMethod => _avaloniaView;
diff --git a/src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs b/src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs
index 8321b00658..27a2b1dcb7 100644
--- a/src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs
+++ b/src/Browser/Avalonia.Browser/Interop/CanvasHelper.cs
@@ -6,7 +6,6 @@ namespace Avalonia.Browser.Interop;
internal record GLInfo(int ContextId, uint FboId, int Stencils, int Samples, int Depth);
-[System.Runtime.Versioning.SupportedOSPlatform("browser")] // gets rid of callsite warnings
internal static partial class CanvasHelper
{
diff --git a/src/Browser/Avalonia.Browser/Interop/StorageHelper.cs b/src/Browser/Avalonia.Browser/Interop/StorageHelper.cs
index c44af810d1..e50f8790ef 100644
--- a/src/Browser/Avalonia.Browser/Interop/StorageHelper.cs
+++ b/src/Browser/Avalonia.Browser/Interop/StorageHelper.cs
@@ -45,7 +45,7 @@ internal static partial class StorageHelper
[JSImport("StorageItem.getItems", AvaloniaModule.StorageModuleName)]
[return: JSMarshalAs>]
- public static partial Task GetItems(JSObject item);
+ public static partial Task GetItems(JSObject item);
[JSImport("StorageItems.itemsArray", AvaloniaModule.StorageModuleName)]
public static partial JSObject[] ItemsArray(JSObject item);
diff --git a/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs
index f69dd3c344..9424122ce8 100644
--- a/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs
+++ b/src/Browser/Avalonia.Browser/Skia/BrowserSkiaGpuRenderTarget.cs
@@ -14,14 +14,12 @@ namespace Avalonia.Browser.Skia
_size = browserSkiaSurface.Size;
var glFbInfo = new GRGlFramebufferInfo(browserSkiaSurface.GlInfo.FboId, browserSkiaSurface.ColorType.ToGlSizedFormat());
- {
- _browserSkiaSurface = browserSkiaSurface;
- _renderTarget = new GRBackendRenderTarget(
- (int)(browserSkiaSurface.Size.Width * browserSkiaSurface.Scaling),
- (int)(browserSkiaSurface.Size.Height * browserSkiaSurface.Scaling),
- browserSkiaSurface.GlInfo.Samples,
- browserSkiaSurface.GlInfo.Stencils, glFbInfo);
- }
+ _browserSkiaSurface = browserSkiaSurface;
+ _renderTarget = new GRBackendRenderTarget(
+ (int)(browserSkiaSurface.Size.Width * browserSkiaSurface.Scaling),
+ (int)(browserSkiaSurface.Size.Height * browserSkiaSurface.Scaling),
+ browserSkiaSurface.GlInfo.Samples,
+ browserSkiaSurface.GlInfo.Stencils, glFbInfo);
}
public void Dispose()
diff --git a/src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs b/src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs
index 4fce190346..3404452bca 100644
--- a/src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs
+++ b/src/Browser/Avalonia.Browser/Storage/BlobReadableStream.cs
@@ -7,7 +7,6 @@ using Avalonia.Browser.Interop;
namespace Avalonia.Browser.Storage;
-[System.Runtime.Versioning.SupportedOSPlatform("browser")]
internal class BlobReadableStream : Stream
{
private JSObject? _jSReference;
diff --git a/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs b/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
index 28de55092b..dc580f0fcb 100644
--- a/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
+++ b/src/Browser/Avalonia.Browser/Storage/BrowserStorageProvider.cs
@@ -13,7 +13,6 @@ namespace Avalonia.Browser.Storage;
internal record FilePickerAcceptType(string Description, IReadOnlyDictionary> Accept);
-[SupportedOSPlatform("browser")]
internal class BrowserStorageProvider : IStorageProvider
{
internal const string PickerCancelMessage = "The user aborted a request";
diff --git a/src/Browser/Avalonia.Browser/Storage/WriteableStream.cs b/src/Browser/Avalonia.Browser/Storage/WriteableStream.cs
index f29f7420ac..b2f14b6a7a 100644
--- a/src/Browser/Avalonia.Browser/Storage/WriteableStream.cs
+++ b/src/Browser/Avalonia.Browser/Storage/WriteableStream.cs
@@ -7,7 +7,6 @@ using Avalonia.Browser.Interop;
namespace Avalonia.Browser.Storage;
-[System.Runtime.Versioning.SupportedOSPlatform("browser")]
// Loose wrapper implementaion of a stream on top of FileAPI FileSystemWritableFileStream
internal sealed class WriteableStream : Stream
{
diff --git a/src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts
index 385cdd4c41..e8e37faf58 100644
--- a/src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts
+++ b/src/Browser/Avalonia.Browser/webapp/modules/avalonia/dom.ts
@@ -17,7 +17,6 @@ export class AvaloniaDOM {
const canvas = document.createElement("canvas");
canvas.id = `canvas${randomIdPart}`;
canvas.classList.add("avalonia-canvas");
- canvas.style.backgroundColor = "#ccc";
canvas.style.width = "100%";
canvas.style.position = "absolute";
diff --git a/src/Browser/Avalonia.Browser/webapp/package-lock.json b/src/Browser/Avalonia.Browser/webapp/package-lock.json
index 06e94629d7..2d875e84db 100644
--- a/src/Browser/Avalonia.Browser/webapp/package-lock.json
+++ b/src/Browser/Avalonia.Browser/webapp/package-lock.json
@@ -2162,9 +2162,9 @@
"dev": true
},
"node_modules/json5": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
- "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dev": true,
"dependencies": {
"minimist": "^1.2.0"
@@ -4699,9 +4699,9 @@
"dev": true
},
"json5": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
- "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dev": true,
"requires": {
"minimist": "^1.2.0"
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
index ac54365f51..6032f3a92c 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
@@ -25,7 +25,7 @@ namespace Avalonia.LinuxFramebuffer
Surfaces = new object[] { _outputBackend };
- Invalidate(default(Rect));
+ Invalidate(default);
_inputBackend.Initialize(this, e => Input?.Invoke(e));
}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
index 2bb91e8a32..e3d154ffdd 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
@@ -179,7 +179,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
}
finally
{
- if( _sreCanSave)
+ if(!success && _sreCanSave)
DumpRuntimeCompilationResults();
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/BitmapTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/BitmapTypeConverter.cs
index dcd60f7a79..fc6a8557f3 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Converters/BitmapTypeConverter.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/Converters/BitmapTypeConverter.cs
@@ -24,7 +24,7 @@ namespace Avalonia.Markup.Xaml.Converters
if(uri.IsAbsoluteUri && uri.IsFile)
return new Bitmap(uri.LocalPath);
- var assets = AvaloniaLocator.Current.GetService();
+ var assets = AvaloniaLocator.Current.GetRequiredService();
return new Bitmap(assets.Open(uri, context.GetContextBaseUri()));
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/IconTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/IconTypeConverter.cs
index 24b690b6f1..698f5a9327 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Converters/IconTypeConverter.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/Converters/IconTypeConverter.cs
@@ -40,7 +40,7 @@ namespace Avalonia.Markup.Xaml.Converters
if(uri.IsAbsoluteUri && uri.IsFile)
return new WindowIcon(uri.LocalPath);
- var assets = AvaloniaLocator.Current.GetService();
+ var assets = AvaloniaLocator.Current.GetRequiredService();
return new WindowIcon(assets.Open(uri, context.GetContextBaseUri()));
}
}
diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs
index 4d6d16a3ce..dbf37f0900 100644
--- a/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs
+++ b/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs
@@ -552,7 +552,8 @@ namespace Avalonia.Markup.Parsers
public override bool Equals(object? obj)
{
- return obj is ClassSyntax && ((ClassSyntax)obj).Class == Class;
+ return obj is ClassSyntax syntax &&
+ syntax.Class == Class;
}
}
@@ -562,7 +563,8 @@ namespace Avalonia.Markup.Parsers
public override bool Equals(object? obj)
{
- return obj is NameSyntax && ((NameSyntax)obj).Name == Name;
+ return obj is NameSyntax syntax &&
+ syntax.Name == Name;
}
}
@@ -574,9 +576,9 @@ namespace Avalonia.Markup.Parsers
public override bool Equals(object? obj)
{
- return obj is PropertySyntax &&
- ((PropertySyntax)obj).Property == Property &&
- ((PropertySyntax)obj).Value == Value;
+ return obj is PropertySyntax syntax &&
+ syntax.Property == Property &&
+ syntax.Value == Value;
}
}
diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
index 48e8c761eb..8b71f4e17e 100644
--- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
+++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
@@ -224,9 +224,9 @@ namespace Avalonia.Skia
var impl = (GeometryImpl) geometry;
var size = geometry.Bounds.Size;
- using (var fill = brush != null ? CreatePaint(_fillPaint, brush, size) : default(PaintWrapper))
+ using (var fill = brush != null ? CreatePaint(_fillPaint, brush, size) : default)
using (var stroke = pen?.Brush != null ? CreatePaint(_strokePaint, pen,
- size.Inflate(new Thickness(pen?.Thickness / 2 ?? 0))) : default(PaintWrapper))
+ size.Inflate(new Thickness(pen?.Thickness / 2 ?? 0))) : default)
{
if (fill.Paint != null)
{
diff --git a/src/Skia/Avalonia.Skia/GeometryImpl.cs b/src/Skia/Avalonia.Skia/GeometryImpl.cs
index 1141763097..15a3ebff40 100644
--- a/src/Skia/Avalonia.Skia/GeometryImpl.cs
+++ b/src/Skia/Avalonia.Skia/GeometryImpl.cs
@@ -245,7 +245,7 @@ namespace Avalonia.Skia
{
CachedStrokePath?.Dispose();
CachedGeometryRenderBounds = default;
- _cachedStrokeWidth = default(float);
+ _cachedStrokeWidth = default;
}
}
}
diff --git a/src/Skia/Avalonia.Skia/SKTypefaceCollectionCache.cs b/src/Skia/Avalonia.Skia/SKTypefaceCollectionCache.cs
index 5ca7f40d17..f7a86c11ff 100644
--- a/src/Skia/Avalonia.Skia/SKTypefaceCollectionCache.cs
+++ b/src/Skia/Avalonia.Skia/SKTypefaceCollectionCache.cs
@@ -37,7 +37,7 @@ namespace Avalonia.Skia
var typeFaceCollection = new SKTypefaceCollection();
- var assetLoader = AvaloniaLocator.Current.GetService();
+ var assetLoader = AvaloniaLocator.Current.GetRequiredService();
foreach (var asset in fontAssets)
{
diff --git a/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs b/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs
index dcb267b2a3..9864a14a9c 100644
--- a/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs
+++ b/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs
@@ -96,9 +96,9 @@ namespace Avalonia.Skia
SKColorType colorType = format.ToSkColorType();
SKAlphaType alphaType = alphaFormat.ToSkAlphaType();
-
- var runtimePlatform = AvaloniaLocator.Current?.GetService();
-
+
+ var runtimePlatform = AvaloniaLocator.Current.GetService();
+
if (runtimePlatform != null)
{
_bitmap = new SKBitmap();
diff --git a/src/Windows/Avalonia.Direct2D1/Media/DWriteResourceFontLoader.cs b/src/Windows/Avalonia.Direct2D1/Media/DWriteResourceFontLoader.cs
index e5f87e71a2..4663a6561f 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/DWriteResourceFontLoader.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/DWriteResourceFontLoader.cs
@@ -22,7 +22,7 @@ namespace Avalonia.Direct2D1.Media
{
var factory1 = factory;
- var assetLoader = AvaloniaLocator.Current.GetService();
+ var assetLoader = AvaloniaLocator.Current.GetRequiredService();
foreach (var asset in fontAssets)
{
diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
index 180ae491b3..3f2298eb22 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
@@ -409,7 +409,7 @@ namespace Avalonia.Direct2D1.Media
}
else
{
- var platform = AvaloniaLocator.Current.GetService();
+ var platform = AvaloniaLocator.Current.GetRequiredService();
var dpi = new Vector(_deviceContext.DotsPerInch.Width, _deviceContext.DotsPerInch.Height);
var pixelSize = PixelSize.FromSizeWithDpi(size, dpi);
return (IDrawingContextLayerImpl)platform.CreateRenderTargetBitmap(pixelSize, dpi);
diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs
index a5474803a1..f900204504 100644
--- a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs
+++ b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs
@@ -127,7 +127,7 @@ namespace Avalonia.Win32.Interop.Wpf
DeviceWindowHandle = GetDesktopWindow(),
PresentationInterval = PresentInterval.Default
};
- s_dxDevice = s_dxDevice ?? AvaloniaLocator.Current.GetService()
+ s_dxDevice = s_dxDevice ?? AvaloniaLocator.Current.GetRequiredService()
.QueryInterface();
s_d3DDevice = new DeviceEx(s_d3DContext, 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve, presentparams);
@@ -156,7 +156,7 @@ namespace Avalonia.Win32.Interop.Wpf
_impl.ImageSource = _image;
RemoveAndDispose(ref _backBuffer);
- if (size == default(IntSize))
+ if (size == default)
{
_image.Lock();
_image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero);
@@ -171,7 +171,7 @@ namespace Avalonia.Win32.Interop.Wpf
static void RemoveAndDispose(ref T d) where T : IDisposable
{
d?.Dispose();
- d = default(T);
+ d = default;
}
void Swap()
diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs
index b8648dfc50..3bfbf4bd92 100644
--- a/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs
+++ b/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs
@@ -28,7 +28,7 @@ namespace Avalonia.Win32.Interop.Wpf
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
- return obj is IntSize && Equals((IntSize) obj);
+ return obj is IntSize size && Equals(size);
}
public override int GetHashCode()
diff --git a/src/Windows/Avalonia.Win32/DataObject.cs b/src/Windows/Avalonia.Win32/DataObject.cs
index b7a567ea97..7d22e57a30 100644
--- a/src/Windows/Avalonia.Win32/DataObject.cs
+++ b/src/Windows/Avalonia.Win32/DataObject.cs
@@ -205,7 +205,7 @@ namespace Avalonia.Win32
if (string.IsNullOrEmpty(fmt) || !_wrapped.Contains(fmt))
return DV_E_FORMATETC;
- * medium = default(Interop.STGMEDIUM);
+ * medium = default;
medium->tymed = TYMED.TYMED_HGLOBAL;
return WriteDataToHGlobal(fmt, ref medium->unionmember);
}
diff --git a/src/Windows/Avalonia.Win32/OleDropTarget.cs b/src/Windows/Avalonia.Win32/OleDropTarget.cs
index b4eb6d8851..8bbdfe5fd9 100644
--- a/src/Windows/Avalonia.Win32/OleDropTarget.cs
+++ b/src/Windows/Avalonia.Win32/OleDropTarget.cs
@@ -121,7 +121,7 @@ namespace Avalonia.Win32
_dragDevice,
RawDragEventType.DragLeave,
_target,
- default(Point),
+ default,
null,
DragDropEffects.None,
RawInputModifiers.None
diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs
index 689a7cef93..e3d0cd9e5f 100644
--- a/src/Windows/Avalonia.Win32/Win32Platform.cs
+++ b/src/Windows/Avalonia.Win32/Win32Platform.cs
@@ -258,6 +258,8 @@ namespace Avalonia.Win32
public bool CurrentThreadIsLoopThread => _uiThread == Thread.CurrentThread;
+ public TimeSpan HoldWaitDuration { get; set; } = TimeSpan.FromMilliseconds(300);
+
public event Action Signaled;
public event EventHandler ShutdownRequested;
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs
index d393bd304a..fb27ab7856 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs
@@ -109,7 +109,7 @@ namespace Avalonia.Win32
if (_owner is Window window)
{
- var visual = window.Renderer.HitTestFirst(position, (Visual)_owner, x =>
+ var visual = window.Renderer.HitTestFirst(position, window, x =>
{
if (x is IInputElement ie && (!ie.IsHitTestVisible || !ie.IsEffectivelyVisible))
{
diff --git a/src/tools/DevAnalyzers/DevAnalyzers.csproj b/src/tools/DevAnalyzers/DevAnalyzers.csproj
index 53e3e74e76..e5c2fc6cf6 100644
--- a/src/tools/DevAnalyzers/DevAnalyzers.csproj
+++ b/src/tools/DevAnalyzers/DevAnalyzers.csproj
@@ -2,7 +2,6 @@
netstandard2.0
- 10
enable
diff --git a/src/tools/DevAnalyzers/GenericVirtualAnalyzer.cs b/src/tools/DevAnalyzers/GenericVirtualAnalyzer.cs
index 8ecd9119f6..ecd6154e0b 100644
--- a/src/tools/DevAnalyzers/GenericVirtualAnalyzer.cs
+++ b/src/tools/DevAnalyzers/GenericVirtualAnalyzer.cs
@@ -16,7 +16,7 @@ public class GenericVirtualAnalyzer : DiagnosticAnalyzer
"Performance",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
- description: "Generic virtual methods affect JIT startup time adversly and should be avoided.");
+ description: "Generic virtual methods affect JIT startup time adversely and should be avoided.");
public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule);
diff --git a/src/tools/DevGenerators/CompositionGenerator/Generator.cs b/src/tools/DevGenerators/CompositionGenerator/Generator.cs
index f8d5ad826e..3b5d3d8c3f 100644
--- a/src/tools/DevGenerators/CompositionGenerator/Generator.cs
+++ b/src/tools/DevGenerators/CompositionGenerator/Generator.cs
@@ -257,7 +257,7 @@ namespace Avalonia.SourceGenerator.CompositionGenerator
if (cl.Properties.Count > 0)
{
server = server.AddMembers(((MethodDeclarationSyntax)ParseMemberDeclaration(
- $"protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan commitedAt){{}}")
+ $"protected override void DeserializeChangesCore(BatchStreamReader reader, TimeSpan committedAt){{}}")
!)
.WithBody(ApplyDeserializeChangesEpilogue(deserializeMethodBody, cl)));
server = server.AddMembers(MethodDeclaration(ParseTypeName("void"), "OnFieldsDeserialized")
@@ -481,7 +481,7 @@ return;
private static BlockSyntax DeserializeChangesPrologue(GClass cl)
{
return Block(ParseStatement($@"
-base.DeserializeChangesCore(reader, commitedAt);
+base.DeserializeChangesCore(reader, committedAt);
DeserializeChangesExtra(reader);
var changed = reader.Read<{ChangedFieldsTypeName(cl)}>();
"));
@@ -500,7 +500,7 @@ var changed = reader.Read<{ChangedFieldsTypeName(cl)}>();
{
code = $@"
if((changed & {changedFieldsType}.{prop.Name}Animated) == {changedFieldsType}.{prop.Name}Animated)
- SetAnimatedValue({CompositionPropertyField(prop)}, ref {PropertyBackingFieldName(prop)}, commitedAt, reader.ReadObject());
+ SetAnimatedValue({CompositionPropertyField(prop)}, ref {PropertyBackingFieldName(prop)}, committedAt, reader.ReadObject());
else ";
}
diff --git a/src/tools/DevGenerators/DevGenerators.csproj b/src/tools/DevGenerators/DevGenerators.csproj
index 069ff159fc..30da940514 100644
--- a/src/tools/DevGenerators/DevGenerators.csproj
+++ b/src/tools/DevGenerators/DevGenerators.csproj
@@ -4,7 +4,6 @@
netstandard2.0
enable
false
- 10
diff --git a/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj b/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
index 0162f53f5e..4cdce8df26 100644
--- a/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
+++ b/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj
@@ -3,7 +3,6 @@
net6.0
Library
true
- latest
diff --git a/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs b/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs
index 59085a21ce..84ee35ba61 100644
--- a/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs
@@ -1,9 +1,13 @@
+using System;
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Input.GestureRecognizers;
using Avalonia.Media;
+using Avalonia.Platform;
+using Avalonia.Threading;
using Avalonia.UnitTests;
+using Moq;
using Xunit;
namespace Avalonia.Base.UnitTests.Input
@@ -169,6 +173,242 @@ namespace Avalonia.Base.UnitTests.Input
Assert.False(raised);
}
+ [Fact]
+ public void Hold_Should_Be_Raised_After_Hold_Duration()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ iSettingsMock.Setup(x => x.GetTapSize(It.IsAny())).Returns(new Size(16, 16));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ HoldingState holding = HoldingState.Cancelled;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => holding = e.HoldingState);
+
+ _mouse.Down(border);
+ Assert.False(holding != HoldingState.Cancelled);
+
+ // Verify timer duration, but execute it immediately.
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ Assert.True(holding == HoldingState.Started);
+
+ _mouse.Up(border);
+
+ Assert.True(holding == HoldingState.Completed);
+ }
+
+ [Fact]
+ public void Hold_Should_Not_Raised_When_Pointer_Released_Before_Timer()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var raised = false;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => raised = e.HoldingState == HoldingState.Started);
+
+ _mouse.Down(border);
+ Assert.False(raised);
+
+ _mouse.Up(border);
+ Assert.False(raised);
+
+ // Verify timer duration, but execute it immediately.
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ Assert.False(raised);
+ }
+
+ [Fact]
+ public void Hold_Should_Not_Raised_When_Pointer_Is_Moved_Before_Timer()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var raised = false;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => raised = e.HoldingState == HoldingState.Completed);
+
+ _mouse.Down(border);
+ Assert.False(raised);
+
+ _mouse.Move(border, position: new Point(20, 20));
+ Assert.False(raised);
+
+ // Verify timer duration, but execute it immediately.
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ Assert.False(raised);
+ }
+
+ [Fact]
+ public void Hold_Should_Be_Cancelled_When_Second_Contact_Is_Detected()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var cancelled = false;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => cancelled = e.HoldingState == HoldingState.Cancelled);
+
+ _mouse.Down(border);
+ Assert.False(cancelled);
+
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ var secondMouse = new MouseTestHelper();
+
+ secondMouse.Down(border);
+
+ Assert.True(cancelled);
+ }
+
+ [Fact]
+ public void Hold_Should_Be_Cancelled_When_Pointer_Moves_Too_Far()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ iSettingsMock.Setup(x => x.GetTapSize(It.IsAny())).Returns(new Size(16, 16));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var cancelled = false;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => cancelled = e.HoldingState == HoldingState.Cancelled);
+
+ _mouse.Down(border);
+
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ _mouse.Move(border, position: new Point(3, 3));
+
+ Assert.False(cancelled);
+
+ _mouse.Move(border, position: new Point(20, 20));
+
+ Assert.True(cancelled);
+ }
+
+ [Fact]
+ public void Hold_Should_Not_Be_Raised_For_Multiple_Contacts()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ var scheduledTimers = new List<(TimeSpan time, Action action)>();
+ using var app = UnitTestApplication.Start(new TestServices(
+ threadingInterface: CreatePlatformThreadingInterface(t => scheduledTimers.Add(t))));
+
+ Border border = new Border();
+ Gestures.SetIsHoldWithMouseEnabled(border, true);
+ var decorator = new Decorator
+ {
+ Child = border
+ };
+ var raised = false;
+
+ decorator.AddHandler(Gestures.HoldingEvent, (s, e) => raised = e.HoldingState == HoldingState.Completed);
+
+ var secondMouse = new MouseTestHelper();
+
+ _mouse.Down(border, MouseButton.Left);
+
+ // Verify timer duration, but execute it immediately.
+ var timer = Assert.Single(scheduledTimers);
+ Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.time);
+ timer.action();
+
+ secondMouse.Down(border, MouseButton.Left);
+
+ Assert.False(raised);
+ }
+
+ private static IPlatformThreadingInterface CreatePlatformThreadingInterface(Action<(TimeSpan, Action)> callback)
+ {
+ var threadingInterface = new Mock();
+ threadingInterface.SetupGet(p => p.CurrentThreadIsLoopThread).Returns(true);
+ threadingInterface.Setup(p => p
+ .StartTimer(It.IsAny(), It.IsAny(), It.IsAny()))
+ .Callback((_, t, a) => callback((t, a)));
+ return threadingInterface.Object;
+ }
+
private static void AddHandlers(
Decorator decorator,
Border border,
diff --git a/tests/Avalonia.Base.UnitTests/Input/TouchDeviceTests.cs b/tests/Avalonia.Base.UnitTests/Input/TouchDeviceTests.cs
index c0c0182622..36587ea222 100644
--- a/tests/Avalonia.Base.UnitTests/Input/TouchDeviceTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Input/TouchDeviceTests.cs
@@ -207,7 +207,7 @@ namespace Avalonia.Input.UnitTests
private IDisposable UnitTestApp(TimeSpan doubleClickTime = new TimeSpan())
{
var unitTestApp = UnitTestApplication.Start(
- new TestServices(inputManager: new InputManager()));
+ new TestServices(inputManager: new InputManager(), threadingInterface: Mock.Of(x => x.CurrentThreadIsLoopThread == true)));
var iSettingsMock = new Mock();
iSettingsMock.Setup(x => x.GetDoubleTapTime(It.IsAny())).Returns(doubleClickTime);
iSettingsMock.Setup(x => x.GetDoubleTapSize(It.IsAny())).Returns(new Size(16, 16));
diff --git a/tests/Avalonia.Base.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs b/tests/Avalonia.Base.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs
index aa042ffec8..afc25ab88e 100644
--- a/tests/Avalonia.Base.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Media/Fonts/FontFamilyLoaderTests.cs
@@ -97,7 +97,7 @@ namespace Avalonia.Base.UnitTests.Media.Fonts
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
- var assetLoader = AvaloniaLocator.Current.GetService();
+ var assetLoader = AvaloniaLocator.Current.GetRequiredService();
var fontFamily = new FontFamily("resm:Avalonia.Base.UnitTests.Assets?assembly=Avalonia.Base.UnitTests#Noto Mono");
diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGeneratorTests.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGeneratorTests.cs
index 4e0207a85d..c57bd6c002 100644
--- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGeneratorTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGeneratorTests.cs
@@ -42,7 +42,7 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting
enumerator.MoveNext();
- var actual = enumerator.Current.Text;
+ var actual = text.AsSpan(enumerator.Current.Offset, enumerator.Current.Length);
var pass = true;
@@ -93,7 +93,7 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting
while (enumerator.MoveNext())
{
- Assert.Equal(1, enumerator.Current.Text.Length);
+ Assert.Equal(1, enumerator.Current.Length);
count++;
}
diff --git a/tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs b/tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs
index 27faf1e13c..3d8369faeb 100644
--- a/tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs
@@ -82,6 +82,39 @@ public class CompositorHitTestingTests : CompositorTestsBase
}
}
+ [Theory,
+ InlineData(false, false),
+ InlineData(true, false),
+ InlineData(false, true),
+ InlineData(true, true),
+ ]
+ public void HitTest_Should_Find_Zero_Opacity_Controls_At_Point(bool parent, bool child)
+ {
+
+ using (var s = new CompositorServices(new Size(200, 200)))
+ {
+ Border visible, border;
+ s.TopLevel.Content = border = new Border
+ {
+ Width = 100,
+ Height = 100,
+ Background = Brushes.Red,
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ Opacity = parent ? 0 : 1,
+ Child = visible = new Border
+ {
+ Opacity = child ? 0 : 1,
+ Background = Brushes.Red,
+ HorizontalAlignment = HorizontalAlignment.Stretch,
+ VerticalAlignment = VerticalAlignment.Stretch,
+ }
+ };
+
+ s.AssertHitTest(new Point(100, 100), null, visible, border);
+ }
+ }
+
[Fact]
public void HitTest_Should_Not_Find_Control_Outside_Point()
{
diff --git a/tests/Avalonia.Benchmarks/Text/HugeTextLayout.cs b/tests/Avalonia.Benchmarks/Text/HugeTextLayout.cs
new file mode 100644
index 0000000000..e1b3c6a99c
--- /dev/null
+++ b/tests/Avalonia.Benchmarks/Text/HugeTextLayout.cs
@@ -0,0 +1,62 @@
+using System;
+using Avalonia.Media;
+using Avalonia.Media.TextFormatting;
+using Avalonia.UnitTests;
+using BenchmarkDotNet.Attributes;
+
+namespace Avalonia.Benchmarks.Text;
+
+[MemoryDiagnoser]
+public class HugeTextLayout : IDisposable
+{
+ private readonly IDisposable _app;
+
+ public HugeTextLayout()
+ {
+ _app = UnitTestApplication.Start(
+ TestServices.StyledWindow.With(
+ renderInterface: new NullRenderingPlatform(),
+ threadingInterface: new NullThreadingPlatform(),
+ standardCursorFactory: new NullCursorFactory()));
+ }
+
+ private const string Text = @"Though, the objectives of the development of the prominent landmarks can be neglected in most cases, it should be realized that after the completion of the strategic decision gives rise to The Expertise of Regular Program (Carlton Cartwright in The Book of the Key Factor)
+A number of key issues arise from the belief that the explicit examination of strategic management should correlate with the conceptual design.
+By all means, the unification of the reliably developed techniques indicates the importance of the ultimate advantage of episodic skill over alternate practices.
+Let's consider, that the portion of the continuing support can be regarded as relentlessly insignificant. The hardware maintenance focuses our attention on the structure absorption. The real reason of the permanent growth drastically the preliminary action plan the ultimate advantage of useful probability over alternate practices.
+Let it not be said that a section of the essential component discards the principle of the more interconnection of critical thinking with productivity boosting of the referential arguments.
+One should, however, not forget that concentration of violations of the strategic management requires urgent actions to be taken towards the comprehensive set of policy statements. Therefore, the concept of the design aspects can be treated as the only solution.
+In a loose sense concentration of the center of the critical thinking provides a deep insight into the emergency planning. The comparison is quite a powerful matter.
+Resulting from review or analysis of threats and opportunities, we can presume that either significant improvement or basics of planning and scheduling reveals the patterns of the final draft. Therefore, the concept of the crucial component can be treated as the only solution.
+One should, nevertheless, consider that the exceptional results of the diverse sources of information gives an overview of the production cycle. It should rather be regarded as an integral part of the direct access to key resources.
+Admitting that the possibility of achieving the results of the constructive criticism, as far as the strategic management is questionable, cannot rely only on the critical thinking. It may reveal how the systems approach partially the comprehensive project management. We must be ready for outline design stage and network development investigation of every contradiction between the effective time management and the efficient decision the network development. Everyone understands what it takes to the draft analysis and prior decisions and early design solutions. In any case, we can systematically change the mechanism of the sources and influences of the continuing financing doctrine. This could exceedingly be a result of a task analysis the hardware maintenance. The real reason of the strategic planning seemingly the influence on eventual productivity. Everyone understands what it takes to the well-known practice. Therefore, the concept of the productivity boost can be treated as the only solution the driving factor. It may reveal how the matters of peculiar interest slowly the goals and objectives or the diverse sources of information the positive influence of any major outcomes complete failure of the supposed theory.
+In respect that the structure of the sufficient amount poses problems and challenges for both the set of related commands and controls and the ability bias.";
+
+ [Benchmark]
+ public TextLayout BuildTextLayout() => new TextLayout(Text, Typeface.Default, 12d, Brushes.Black);
+
+ private const string Emojis = @"😀 😁 😂 🤣 😃 😄 😅 😆 😉 😊 😋 😎 😍 😘 🥰 😗 😙 😚 ☺️ 🙂 🤗 🤩 🤔 🤨 😐 😑 😶 🙄 😏 😣 😥 😮 🤐 😯 😪 😫 😴 😌 😛 😜 😝 🤤 😒 😓 😔 😕 🙃 🤑 😲 ☹️ 🙁 😖 😞 😟 😤 😢 😭 😦 😧 😨 😩 🤯 😬 😰 😱 🥵 🥶 😳 🤪 😵 😡 😠 🤬 😷 🤒 🤕 🤢 🤮 🤧 😇 🤠 🤡 🥳 🥴 🥺 🤥 🤫 🤭 🧐 🤓 😈 👿 👹 👺 💀 👻 👽 🤖 💩 😺 😸 😹 😻 😼 😽 🙀 😿 😾
+👶 👧 🧒 👦 👩 🧑 👨 👵 🧓 👴 👲 👳♀️ 👳♂️ 🧕 🧔 👱♂️ 👱♀️ 👨🦰 👩🦰 👨🦱 👩🦱 👨🦲 👩🦲 👨🦳 👩🦳 🦸♀️ 🦸♂️ 🦹♀️ 🦹♂️ 👮♀️ 👮♂️ 👷♀️ 👷♂️ 💂♀️ 💂♂️ 🕵️♀️ 🕵️♂️ 👩⚕️ 👨⚕️ 👩🌾 👨🌾 👩🍳 👨🍳 👩🎓 👨🎓 👩🎤 👨🎤 👩🏫 👨🏫 👩🏭 👨🏭 👩💻 👨💻 👩💼 👨💼 👩🔧 👨🔧 👩🔬 👨🔬 👩🎨 👨🎨 👩🚒 👨🚒 👩✈️ 👨✈️ 👩🚀 👨🚀 👩⚖️ 👨⚖️ 👰 🤵 👸 🤴 🤶 🎅 🧙♀️ 🧙♂️ 🧝♀️ 🧝♂️ 🧛♀️ 🧛♂️ 🧟♀️ 🧟♂️ 🧞♀️ 🧞♂️ 🧜♀️ 🧜♂️ 🧚♀️ 🧚♂️ 👼 🤰 🤱 🙇♀️ 🙇♂️ 💁♀️ 💁♂️ 🙅♀️ 🙅♂️ 🙆♀️ 🙆♂️ 🙋♀️ 🙋♂️ 🤦♀️ 🤦♂️ 🤷♀️ 🤷♂️ 🙎♀️ 🙎♂️ 🙍♀️ 🙍♂️ 💇♀️ 💇♂️ 💆♀️ 💆♂️ 🧖♀️ 🧖♂️ 💅 🤳 💃 🕺 👯♀️ 👯♂️ 🕴 🚶♀️ 🚶♂️ 🏃♀️ 🏃♂️ 👫 👭 👬 💑 👩❤️👩 👨❤️👨 💏 👩❤️💋👩 👨❤️💋👨 👪 👨👩👧 👨👩👧👦 👨👩👦👦 👨👩👧👧 👩👩👦 👩👩👧 👩👩👧👦 👩👩👦👦 👩👩👧👧 👨👨👦 👨👨👧 👨👨👧👦 👨👨👦👦 👨👨👧👧 👩👦 👩👧 👩👧👦 👩👦👦 👩👧👧 👨👦 👨👧 👨👧👦 👨👦👦 👨👧👧 🤲 👐 🙌 👏 🤝 👍 👎 👊 ✊ 🤛 🤜 🤞 ✌️ 🤟 🤘 👌 👈 👉 👆 👇 ☝️ ✋ 🤚 🖐 🖖 👋 🤙 💪 🦵 🦶 🖕 ✍️ 🙏 💍 💄 💋 👄 👅 👂 👃 👣 👁 👀 🧠 🦴 🦷 🗣 👤 👥
+🧥 👚 👕 👖 👔 👗 👙 👘 👠 👡 👢 👞 👟 🥾 🥿 🧦 🧤 🧣 🎩 🧢 👒 🎓 ⛑ 👑 👝 👛 👜 💼 🎒 👓 🕶 🥽 🥼 🌂 🧵 🧶
+👶🏻 👦🏻 👧🏻 👨🏻 👩🏻 👱🏻♀️ 👱🏻 👴🏻 👵🏻 👲🏻 👳🏻♀️ 👳🏻 👮🏻♀️ 👮🏻 👷🏻♀️ 👷🏻 💂🏻♀️ 💂🏻 🕵🏻♀️ 🕵🏻 👩🏻⚕️ 👨🏻⚕️ 👩🏻🌾 👨🏻🌾 👩🏻🍳 👨🏻🍳 👩🏻🎓 👨🏻🎓 👩🏻🎤 👨🏻🎤 👩🏻🏫 👨🏻🏫 👩🏻🏭 👨🏻🏭 👩🏻💻 👨🏻💻 👩🏻💼 👨🏻💼 👩🏻🔧 👨🏻🔧 👩🏻🔬 👨🏻🔬 👩🏻🎨 👨🏻🎨 👩🏻🚒 👨🏻🚒 👩🏻✈️ 👨🏻✈️ 👩🏻🚀 👨🏻🚀 👩🏻⚖️ 👨🏻⚖️ 🤶🏻 🎅🏻 👸🏻 🤴🏻 👰🏻 🤵🏻 👼🏻 🤰🏻 🙇🏻♀️ 🙇🏻 💁🏻 💁🏻♂️ 🙅🏻 🙅🏻♂️ 🙆🏻 🙆🏻♂️ 🙋🏻 🙋🏻♂️ 🤦🏻♀️ 🤦🏻♂️ 🤷🏻♀️ 🤷🏻♂️ 🙎🏻 🙎🏻♂️ 🙍🏻 🙍🏻♂️ 💇🏻 💇🏻♂️ 💆🏻 💆🏻♂️ 🕴🏻 💃🏻 🕺🏻 🚶🏻♀️ 🚶🏻 🏃🏻♀️ 🏃🏻 🤲🏻 👐🏻 🙌🏻 👏🏻 🙏🏻 👍🏻 👎🏻 👊🏻 ✊🏻 🤛🏻 🤜🏻 🤞🏻 ✌🏻 🤟🏻 🤘🏻 👌🏻 👈🏻 👉🏻 👆🏻 👇🏻 ☝🏻 ✋🏻 🤚🏻 🖐🏻 🖖🏻 👋🏻 🤙🏻 💪🏻 🖕🏻 ✍🏻 🤳🏻 💅🏻 👂🏻 👃🏻
+👶🏼 👦🏼 👧🏼 👨🏼 👩🏼 👱🏼♀️ 👱🏼 👴🏼 👵🏼 👲🏼 👳🏼♀️ 👳🏼 👮🏼♀️ 👮🏼 👷🏼♀️ 👷🏼 💂🏼♀️ 💂🏼 🕵🏼♀️ 🕵🏼 👩🏼⚕️ 👨🏼⚕️ 👩🏼🌾 👨🏼🌾 👩🏼🍳 👨🏼🍳 👩🏼🎓 👨🏼🎓 👩🏼🎤 👨🏼🎤 👩🏼🏫 👨🏼🏫 👩🏼🏭 👨🏼🏭 👩🏼💻 👨🏼💻 👩🏼💼 👨🏼💼 👩🏼🔧 👨🏼🔧 👩🏼🔬 👨🏼🔬 👩🏼🎨 👨🏼🎨 👩🏼🚒 👨🏼🚒 👩🏼✈️ 👨🏼✈️ 👩🏼🚀 👨🏼🚀 👩🏼⚖️ 👨🏼⚖️ 🤶🏼 🎅🏼 👸🏼 🤴🏼 👰🏼 🤵🏼 👼🏼 🤰🏼 🙇🏼♀️ 🙇🏼 💁🏼 💁🏼♂️ 🙅🏼 🙅🏼♂️ 🙆🏼 🙆🏼♂️ 🙋🏼 🙋🏼♂️ 🤦🏼♀️ 🤦🏼♂️ 🤷🏼♀️ 🤷🏼♂️ 🙎🏼 🙎🏼♂️ 🙍🏼 🙍🏼♂️ 💇🏼 💇🏼♂️ 💆🏼 💆🏼♂️ 🕴🏼 💃🏼 🕺🏼 🚶🏼♀️ 🚶🏼 🏃🏼♀️ 🏃🏼 🤲🏼 👐🏼 🙌🏼 👏🏼 🙏🏼 👍🏼 👎🏼 👊🏼 ✊🏼 🤛🏼 🤜🏼 🤞🏼 ✌🏼 🤟🏼 🤘🏼 👌🏼 👈🏼 👉🏼 👆🏼 👇🏼 ☝🏼 ✋🏼 🤚🏼 🖐🏼 🖖🏼 👋🏼 🤙🏼 💪🏼 🖕🏼 ✍🏼 🤳🏼 💅🏼 👂🏼 👃🏼
+👶🏽 👦🏽 👧🏽 👨🏽 👩🏽 👱🏽♀️ 👱🏽 👴🏽 👵🏽 👲🏽 👳🏽♀️ 👳🏽 👮🏽♀️ 👮🏽 👷🏽♀️ 👷🏽 💂🏽♀️ 💂🏽 🕵🏽♀️ 🕵🏽 👩🏽⚕️ 👨🏽⚕️ 👩🏽🌾 👨🏽🌾 👩🏽🍳 👨🏽🍳 👩🏽🎓 👨🏽🎓 👩🏽🎤 👨🏽🎤 👩🏽🏫 👨🏽🏫 👩🏽🏭 👨🏽🏭 👩🏽💻 👨🏽💻 👩🏽💼 👨🏽💼 👩🏽🔧 👨🏽🔧 👩🏽🔬 👨🏽🔬 👩🏽🎨 👨🏽🎨 👩🏽🚒 👨🏽🚒 👩🏽✈️ 👨🏽✈️ 👩🏽🚀 👨🏽🚀 👩🏽⚖️ 👨🏽⚖️ 🤶🏽 🎅🏽 👸🏽 🤴🏽 👰🏽 🤵🏽 👼🏽 🤰🏽 🙇🏽♀️ 🙇🏽 💁🏽 💁🏽♂️ 🙅🏽 🙅🏽♂️ 🙆🏽 🙆🏽♂️ 🙋🏽 🙋🏽♂️ 🤦🏽♀️ 🤦🏽♂️ 🤷🏽♀️ 🤷🏽♂️ 🙎🏽 🙎🏽♂️ 🙍🏽 🙍🏽♂️ 💇🏽 💇🏽♂️ 💆🏽 💆🏽♂️ 🕴🏼 💃🏽 🕺🏽 🚶🏽♀️ 🚶🏽 🏃🏽♀️ 🏃🏽 🤲🏽 👐🏽 🙌🏽 👏🏽 🙏🏽 👍🏽 👎🏽 👊🏽 ✊🏽 🤛🏽 🤜🏽 🤞🏽 ✌🏽 🤟🏽 🤘🏽 👌🏽 👈🏽 👉🏽 👆🏽 👇🏽 ☝🏽 ✋🏽 🤚🏽 🖐🏽 🖖🏽 👋🏽 🤙🏽 💪🏽 🖕🏽 ✍🏽 🤳🏽 💅🏽 👂🏽 👃🏽
+👶🏾 👦🏾 👧🏾 👨🏾 👩🏾 👱🏾♀️ 👱🏾 👴🏾 👵🏾 👲🏾 👳🏾♀️ 👳🏾 👮🏾♀️ 👮🏾 👷🏾♀️ 👷🏾 💂🏾♀️ 💂🏾 🕵🏾♀️ 🕵🏾 👩🏾⚕️ 👨🏾⚕️ 👩🏾🌾 👨🏾🌾 👩🏾🍳 👨🏾🍳 👩🏾🎓 👨🏾🎓 👩🏾🎤 👨🏾🎤 👩🏾🏫 👨🏾🏫 👩🏾🏭 👨🏾🏭 👩🏾💻 👨🏾💻 👩🏾💼 👨🏾💼 👩🏾🔧 👨🏾🔧 👩🏾🔬 👨🏾🔬 👩🏾🎨 👨🏾🎨 👩🏾🚒 👨🏾🚒 👩🏾✈️ 👨🏾✈️ 👩🏾🚀 👨🏾🚀 👩🏾⚖️ 👨🏾⚖️ 🤶🏾 🎅🏾 👸🏾 🤴🏾 👰🏾 🤵🏾 👼🏾 🤰🏾 🙇🏾♀️ 🙇🏾 💁🏾 💁🏾♂️ 🙅🏾 🙅🏾♂️ 🙆🏾 🙆🏾♂️ 🙋🏾 🙋🏾♂️ 🤦🏾♀️ 🤦🏾♂️ 🤷🏾♀️ 🤷🏾♂️ 🙎🏾 🙎🏾♂️ 🙍🏾 🙍🏾♂️ 💇🏾 💇🏾♂️ 💆🏾 💆🏾♂️ 🕴🏾 💃🏾 🕺🏾 🚶🏾♀️ 🚶🏾 🏃🏾♀️ 🏃🏾 🤲🏾 👐🏾 🙌🏾 👏🏾 🙏🏾 👍🏾 👎🏾 👊🏾 ✊🏾 🤛🏾 🤜🏾 🤞🏾 ✌🏾 🤟🏾 🤘🏾 👌🏾 👈🏾 👉🏾 👆🏾 👇🏾 ☝🏾 ✋🏾 🤚🏾 🖐🏾 🖖🏾 👋🏾 🤙🏾 💪🏾 🖕🏾 ✍🏾 🤳🏾 💅🏾 👂🏾 👃🏾
+👶🏿 👦🏿 👧🏿 👨🏿 👩🏿 👱🏿♀️ 👱🏿 👴🏿 👵🏿 👲🏿 👳🏿♀️ 👳🏿 👮🏿♀️ 👮🏿 👷🏿♀️ 👷🏿 💂🏿♀️ 💂🏿 🕵🏿♀️ 🕵🏿 👩🏿⚕️ 👨🏿⚕️ 👩🏿🌾 👨🏿🌾 👩🏿🍳 👨🏿🍳 👩🏿🎓 👨🏿🎓 👩🏿🎤 👨🏿🎤 👩🏿🏫 👨🏿🏫 👩🏿🏭 👨🏿🏭 👩🏿💻 👨🏿💻 👩🏿💼 👨🏿💼 👩🏿🔧 👨🏿🔧 👩🏿🔬 👨🏿🔬 👩🏿🎨 👨🏿🎨 👩🏿🚒 👨🏿🚒 👩🏿✈️ 👨🏿✈️ 👩🏿🚀 👨🏿🚀 👩🏿⚖️ 👨🏿⚖️ 🤶🏿 🎅🏿 👸🏿 🤴🏿 👰🏿 🤵🏿 👼🏿 🤰🏿 🙇🏿♀️ 🙇🏿 💁🏿 💁🏿♂️ 🙅🏿 🙅🏿♂️ 🙆🏿 🙆🏿♂️ 🙋🏿 🙋🏿♂️ 🤦🏿♀️ 🤦🏿♂️ 🤷🏿♀️ 🤷🏿♂️ 🙎🏿 🙎🏿♂️ 🙍🏿 🙍🏿♂️ 💇🏿 💇🏿♂️ 💆🏿 💆🏿♂️ 🕴🏿 💃🏿 🕺🏿 🚶🏿♀️ 🚶🏿 🏃🏿♀️ 🏃🏿 🤲🏿 👐🏿 🙌🏿 👏🏿 🙏🏿 👍🏿 👎🏿 👊🏿 ✊🏿 🤛🏿 🤜🏿 🤞🏿 ✌🏿 🤟🏿 🤘🏿 👌🏿 👈🏿 👉🏿 👆🏿 👇🏿 ☝🏿 ✋🏿 🤚🏿 🖐🏿 🖖🏿 👋🏿 🤙🏿 💪🏿 🖕🏿 ✍🏿 🤳🏿 💅🏿 👂🏿 👃🏿
+🐶 🐱 🐭 🐹 🐰 🦊 🦝 🐻 🐼 🦘 🦡 🐨 🐯 🦁 🐮 🐷 🐽 🐸 🐵 🙈 🙉 🙊 🐒 🐔 🐧 🐦 🐤 🐣 🐥 🦆 🦢 🦅 🦉 🦚 🦜 🦇 🐺 🐗 🐴 🦄 🐝 🐛 🦋 🐌 🐚 🐞 🐜 🦗 🕷 🕸 🦂 🦟 🦠 🐢 🐍 🦎 🦖 🦕 🐙 🦑 🦐 🦀 🐡 🐠 🐟 🐬 🐳 🐋 🦈 🐊 🐅 🐆 🦓 🦍 🐘 🦏 🦛 🐪 🐫 🦙 🦒 🐃 🐂 🐄 🐎 🐖 🐏 🐑 🐐 🦌 🐕 🐩 🐈 🐓 🦃 🕊 🐇 🐁 🐀 🐿 🦔 🐾 🐉 🐲 🌵 🎄 🌲 🌳 🌴 🌱 🌿 ☘️ 🍀 🎍 🎋 🍃 🍂 🍁 🍄 🌾 💐 🌷 🌹 🥀 🌺 🌸 🌼 🌻 🌞 🌝 🌛 🌜 🌚 🌕 🌖 🌗 🌘 🌑 🌒 🌓 🌔 🌙 🌎 🌍 🌏 💫 ⭐️ 🌟 ✨ ⚡️ ☄️ 💥 🔥 🌪 🌈 ☀️ 🌤 ⛅️ 🌥 ☁️ 🌦 🌧 ⛈ 🌩 🌨 ❄️ ☃️ ⛄️ 🌬 💨 💧 💦 ☔️ ☂️ 🌊 🌫
+🍏 🍎 🍐 🍊 🍋 🍌 🍉 🍇 🍓 🍈 🍒 🍑 🍍 🥭 🥥 🥝 🍅 🍆 🥑 🥦 🥒 🥬 🌶 🌽 🥕 🥔 🍠 🥐 🍞 🥖 🥨 🥯 🧀 🥚 🍳 🥞 🥓 🥩 🍗 🍖 🌭 🍔 🍟 🍕 🥪 🥙 🌮 🌯 🥗 🥘 🥫 🍝 🍜 🍲 🍛 🍣 🍱 🥟 🍤 🍙 🍚 🍘 🍥 🥮 🥠 🍢 🍡 🍧 🍨 🍦 🥧 🍰 🎂 🍮 🍭 🍬 🍫 🍿 🧂 🍩 🍪 🌰 🥜 🍯 🥛 🍼 ☕️ 🍵 🥤 🍶 🍺 🍻 🥂 🍷 🥃 🍸 🍹 🍾 🥄 🍴 🍽 🥣 🥡 🥢
+⚽️ 🏀 🏈 ⚾️ 🥎 🏐 🏉 🎾 🥏 🎱 🏓 🏸 🥅 🏒 🏑 🥍 🏏 ⛳️ 🏹 🎣 🥊 🥋 🎽 ⛸ 🥌 🛷 🛹 🎿 ⛷ 🏂 🏋️♀️ 🏋🏻♀️ 🏋🏼♀️ 🏋🏽♀️ 🏋🏾♀️ 🏋🏿♀️ 🏋️♂️ 🏋🏻♂️ 🏋🏼♂️ 🏋🏽♂️ 🏋🏾♂️ 🏋🏿♂️ 🤼♀️ 🤼♂️ 🤸♀️ 🤸🏻♀️ 🤸🏼♀️ 🤸🏽♀️ 🤸🏾♀️ 🤸🏿♀️ 🤸♂️ 🤸🏻♂️ 🤸🏼♂️ 🤸🏽♂️ 🤸🏾♂️ 🤸🏿♂️ ⛹️♀️ ⛹🏻♀️ ⛹🏼♀️ ⛹🏽♀️ ⛹🏾♀️ ⛹🏿♀️ ⛹️♂️ ⛹🏻♂️ ⛹🏼♂️ ⛹🏽♂️ ⛹🏾♂️ ⛹🏿♂️ 🤺 🤾♀️ 🤾🏻♀️ 🤾🏼♀️ 🤾🏾♀️ 🤾🏾♀️ 🤾🏿♀️ 🤾♂️ 🤾🏻♂️ 🤾🏼♂️ 🤾🏽♂️ 🤾🏾♂️ 🤾🏿♂️ 🏌️♀️ 🏌🏻♀️ 🏌🏼♀️ 🏌🏽♀️ 🏌🏾♀️ 🏌🏿♀️ 🏌️♂️ 🏌🏻♂️ 🏌🏼♂️ 🏌🏽♂️ 🏌🏾♂️ 🏌🏿♂️ 🏇 🏇🏻 🏇🏼 🏇🏽 🏇🏾 🏇🏿 🧘♀️ 🧘🏻♀️ 🧘🏼♀️ 🧘🏽♀️ 🧘🏾♀️ 🧘🏿♀️ 🧘♂️ 🧘🏻♂️ 🧘🏼♂️ 🧘🏽♂️ 🧘🏾♂️ 🧘🏿♂️ 🏄♀️ 🏄🏻♀️ 🏄🏼♀️ 🏄🏽♀️ 🏄🏾♀️ 🏄🏿♀️ 🏄♂️ 🏄🏻♂️ 🏄🏼♂️ 🏄🏽♂️ 🏄🏾♂️ 🏄🏿♂️ 🏊♀️ 🏊🏻♀️ 🏊🏼♀️ 🏊🏽♀️ 🏊🏾♀️ 🏊🏿♀️ 🏊♂️ 🏊🏻♂️ 🏊🏼♂️ 🏊🏽♂️ 🏊🏾♂️ 🏊🏿♂️ 🤽♀️ 🤽🏻♀️ 🤽🏼♀️ 🤽🏽♀️ 🤽🏾♀️ 🤽🏿♀️ 🤽♂️ 🤽🏻♂️ 🤽🏼♂️ 🤽🏽♂️ 🤽🏾♂️ 🤽🏿♂️ 🚣♀️ 🚣🏻♀️ 🚣🏼♀️ 🚣🏽♀️ 🚣🏾♀️ 🚣🏿♀️ 🚣♂️ 🚣🏻♂️ 🚣🏼♂️ 🚣🏽♂️ 🚣🏾♂️ 🚣🏿♂️ 🧗♀️ 🧗🏻♀️ 🧗🏼♀️ 🧗🏽♀️ 🧗🏾♀️ 🧗🏿♀️ 🧗♂️ 🧗🏻♂️ 🧗🏼♂️ 🧗🏽♂️ 🧗🏾♂️ 🧗🏿♂️ 🚵♀️ 🚵🏻♀️ 🚵🏼♀️ 🚵🏽♀️ 🚵🏾♀️ 🚵🏿♀️ 🚵♂️ 🚵🏻♂️ 🚵🏼♂️ 🚵🏽♂️ 🚵🏾♂️ 🚵🏿♂️ 🚴♀️ 🚴🏻♀️ 🚴🏼♀️ 🚴🏽♀️ 🚴🏾♀️ 🚴🏿♀️ 🚴♂️ 🚴🏻♂️ 🚴🏼♂️ 🚴🏽♂️ 🚴🏾♂️ 🚴🏿♂️ 🏆 🥇 🥈 🥉 🏅 🎖 🏵 🎗 🎫 🎟 🎪 🤹♀️ 🤹🏻♀️ 🤹🏼♀️ 🤹🏽♀️ 🤹🏾♀️ 🤹🏿♀️ 🤹♂️ 🤹🏻♂️ 🤹🏼♂️ 🤹🏽♂️ 🤹🏾♂️ 🤹🏿♂️ 🎭 🎨 🎬 🎤 🎧 🎼 🎹 🥁 🎷 🎺 🎸 🎻 🎲 🧩 ♟ 🎯 🎳 🎮 🎰
+🚗 🚕 🚙 🚌 🚎 🏎 🚓 🚑 🚒 🚐 🚚 🚛 🚜 🛴 🚲 🛵 🏍 🚨 🚔 🚍 🚘 🚖 🚡 🚠 🚟 🚃 🚋 🚞 🚝 🚄 🚅 🚈 🚂 🚆 🚇 🚊 🚉 ✈️ 🛫 🛬 🛩 💺 🛰 🚀 🛸 🚁 🛶 ⛵️ 🚤 🛥 🛳 ⛴ 🚢 ⚓️ ⛽️ 🚧 🚦 🚥 🚏 🗺 🗿 🗽 🗼 🏰 🏯 🏟 🎡 🎢 🎠 ⛲️ ⛱ 🏖 🏝 🏜 🌋 ⛰ 🏔 🗻 🏕 ⛺️ 🏠 🏡 🏘 🏚 🏗 🏭 🏢 🏬 🏣 🏤 🏥 🏦 🏨 🏪 🏫 🏩 💒 🏛 ⛪️ 🕌 🕍 🕋 ⛩ 🛤 🛣 🗾 🎑 🏞 🌅 🌄 🌠 🎇 🎆 🌇 🌆 🏙 🌃 🌌 🌉 🌁
+⌚️ 📱 📲 💻 ⌨️ 🖥 🖨 🖱 🖲 🕹 🗜 💽 💾 💿 📀 📼 📷 📸 📹 🎥 📽 🎞 📞 ☎️ 📟 📠 📺 📻 🎙 🎚 🎛 ⏱ ⏲ ⏰ 🕰 ⌛️ ⏳ 📡 🔋 🔌 💡 🔦 🕯 🗑 🛢 💸 💵 💴 💶 💷 💰 💳 🧾 💎 ⚖️ 🔧 🔨 ⚒ 🛠 ⛏ 🔩 ⚙️ ⛓ 🔫 💣 🔪 🗡 ⚔️ 🛡 🚬 ⚰️ ⚱️ 🏺 🧭 🧱 🔮 🧿 🧸 📿 💈 ⚗️ 🔭 🧰 🧲 🧪 🧫 🧬 🧯 🔬 🕳 💊 💉 🌡 🚽 🚰 🚿 🛁 🛀 🛀🏻 🛀🏼 🛀🏽 🛀🏾 🛀🏿 🧴 🧵 🧶 🧷 🧹 🧺 🧻 🧼 🧽 🛎 🔑 🗝 🚪 🛋 🛏 🛌 🖼 🛍 🧳 🛒 🎁 🎈 🎏 🎀 🎊 🎉 🧨 🎎 🏮 🎐 🧧 ✉️ 📩 📨 📧 💌 📥 📤 📦 🏷 📪 📫 📬 📭 📮 📯 📜 📃 📄 📑 📊 📈 📉 🗒 🗓 📆 📅 📇 🗃 🗳 🗄 📋 📁 📂 🗂 🗞 📰 📓 📔 📒 📕 📗 📘 📙 📚 📖 🔖 🔗 📎 🖇 📐 📏 📌 📍 ✂️ 🖊 🖋 ✒️ 🖌 🖍 📝 ✏️ 🔍 🔎 🔏 🔐 🔒 🔓
+❤️ 🧡 💛 💚 💙 💜 🖤 💔 ❣️ 💕 💞 💓 💗 💖 💘 💝 💟 ☮️ ✝️ ☪️ 🕉 ☸️ ✡️ 🔯 🕎 ☯️ ☦️ 🛐 ⛎ ♈️ ♉️ ♊️ ♋️ ♌️ ♍️ ♎️ ♏️ ♐️ ♑️ ♒️ ♓️ 🆔 ⚛️ 🉑 ☢️ ☣️ 📴 📳 🈶 🈚️ 🈸 🈺 🈷️ ✴️ 🆚 💮 🉐 ㊙️ ㊗️ 🈴 🈵 🈹 🈲 🅰️ 🅱️ 🆎 🆑 🅾️ 🆘 ❌ ⭕️ 🛑 ⛔️ 📛 🚫 💯 💢 ♨️ 🚷 🚯 🚳 🚱 🔞 📵 🚭 ❗️ ❕ ❓ ❔ ‼️ ⁉️ 🔅 🔆 〽️ ⚠️ 🚸 🔱 ⚜️ 🔰 ♻️ ✅ 🈯️ 💹 ❇️ ✳️ ❎ 🌐 💠 Ⓜ️ 🌀 💤 🏧 🚾 ♿️ 🅿️ 🈳 🈂️ 🛂 🛃 🛄 🛅 🚹 🚺 🚼 🚻 🚮 🎦 📶 🈁 🔣 ℹ️ 🔤 🔡 🔠 🆖 🆗 🆙 🆒 🆕 🆓 0️⃣ 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣ 9️⃣ 🔟 🔢 #️⃣ *️⃣ ⏏️ ▶️ ⏸ ⏯ ⏹ ⏺ ⏭ ⏮ ⏩ ⏪ ⏫ ⏬ ◀️ 🔼 🔽 ➡️ ⬅️ ⬆️ ⬇️ ↗️ ↘️ ↙️ ↖️ ↕️ ↔️ ↪️ ↩️ ⤴️ ⤵️ 🔀 🔁 🔂 🔄 🔃 🎵 🎶 ➕ ➖ ➗ ✖️ ♾ 💲 💱 ™️ ©️ ®️ 〰️ ➰ ➿ 🔚 🔙 🔛 🔝 🔜 ✔️ ☑️ 🔘 ⚪️ ⚫️ 🔴 🔵 🔺 🔻 🔸 🔹 🔶 🔷 🔳 🔲 ▪️ ▫️ ◾️ ◽️ ◼️ ◻️ ⬛️ ⬜️ 🔈 🔇 🔉 🔊 🔔 🔕 📣 📢 👁🗨 💬 💭 🗯 ♠️ ♣️ ♥️ ♦️ 🃏 🎴 🀄️ 🕐 🕑 🕒 🕓 🕔 🕕 🕖 🕗 🕘 🕙 🕚 🕛 🕜 🕝 🕞 🕟 🕠 🕡 🕢 🕣 🕤 🕥 🕦 🕧
+🏳️ 🏴 🏁 🚩 🏳️🌈 🏴☠️ 🇦🇫 🇦🇽 🇦🇱 🇩🇿 🇦🇸 🇦🇩 🇦🇴 🇦🇮 🇦🇶 🇦🇬 🇦🇷 🇦🇲 🇦🇼 🇦🇺 🇦🇹 🇦🇿 🇧🇸 🇧🇭 🇧🇩 🇧🇧 🇧🇾 🇧🇪 🇧🇿 🇧🇯 🇧🇲 🇧🇹 🇧🇴 🇧🇦 🇧🇼 🇧🇷 🇮🇴 🇻🇬 🇧🇳 🇧🇬 🇧🇫 🇧🇮 🇰🇭 🇨🇲 🇨🇦 🇮🇨 🇨🇻 🇧🇶 🇰🇾 🇨🇫 🇹🇩 🇨🇱 🇨🇳 🇨🇽 🇨🇨 🇨🇴 🇰🇲 🇨🇬 🇨🇩 🇨🇰 🇨🇷 🇨🇮 🇭🇷 🇨🇺 🇨🇼 🇨🇾 🇨🇿 🇩🇰 🇩🇯 🇩🇲 🇩🇴 🇪🇨 🇪🇬 🇸🇻 🇬🇶 🇪🇷 🇪🇪 🇪🇹 🇪🇺 🇫🇰 🇫🇴 🇫🇯 🇫🇮 🇫🇷 🇬🇫 🇵🇫 🇹🇫 🇬🇦 🇬🇲 🇬🇪 🇩🇪 🇬🇭 🇬🇮 🇬🇷 🇬🇱 🇬🇩 🇬🇵 🇬🇺 🇬🇹 🇬🇬 🇬🇳 🇬🇼 🇬🇾 🇭🇹 🇭🇳 🇭🇰 🇭🇺 🇮🇸 🇮🇳 🇮🇩 🇮🇷 🇮🇶 🇮🇪 🇮🇲 🇮🇱 🇮🇹 🇯🇲 🇯🇵 🎌 🇯🇪 🇯🇴 🇰🇿 🇰🇪 🇰🇮 🇽🇰 🇰🇼 🇰🇬 🇱🇦 🇱🇻 🇱🇧 🇱🇸 🇱🇷 🇱🇾 🇱🇮 🇱🇹 🇱🇺 🇲🇴 🇲🇰 🇲🇬 🇲🇼 🇲🇾 🇲🇻 🇲🇱 🇲🇹 🇲🇭 🇲🇶 🇲🇷 🇲🇺 🇾🇹 🇲🇽 🇫🇲 🇲🇩 🇲🇨 🇲🇳 🇲🇪 🇲🇸 🇲🇦 🇲🇿 🇲🇲 🇳🇦 🇳🇷 🇳🇵 🇳🇱 🇳🇨 🇳🇿 🇳🇮 🇳🇪 🇳🇬 🇳🇺 🇳🇫 🇰🇵 🇲🇵 🇳🇴 🇴🇲 🇵🇰 🇵🇼 🇵🇸 🇵🇦 🇵🇬 🇵🇾 🇵🇪 🇵🇭 🇵🇳 🇵🇱 🇵🇹 🇵🇷 🇶🇦 🇷🇪 🇷🇴 🇷🇺 🇷🇼 🇼🇸 🇸🇲 🇸🇦 🇸🇳 🇷🇸 🇸🇨 🇸🇱 🇸🇬 🇸🇽 🇸🇰 🇸🇮 🇬🇸 🇸🇧 🇸🇴 🇿🇦 🇰🇷 🇸🇸 🇪🇸 🇱🇰 🇧🇱 🇸🇭 🇰🇳 🇱🇨 🇵🇲 🇻🇨 🇸🇩 🇸🇷 🇸🇿 🇸🇪 🇨🇭 🇸🇾 🇹🇼 🇹🇯 🇹🇿 🇹🇭 🇹🇱 🇹🇬 🇹🇰 🇹🇴 🇹🇹 🇹🇳 🇹🇷 🇹🇲 🇹🇨 🇹🇻 🇻🇮 🇺🇬 🇺🇦 🇦🇪 🇬🇧 🏴 🏴 🏴 🇺🇳 🇺🇸 🇺🇾 🇺🇿 🇻🇺 🇻🇦 🇻🇪 🇻🇳 🇼🇫 🇪🇭 🇾🇪 🇿🇲 🇿🇼
+🥱 🤏 🦾 🦿 🦻 🧏 🧏♂️ 🧏♀️ 🧍 🧍♂️ 🧍♀️ 🧎 🧎♂️ 🧎♀️ 👨🦯 👩🦯 👨🦼 👩🦼 👨🦽 👩🦽 🦧 🦮 🐕🦺 🦥 🦦 🦨 🦩 🧄 🧅 🧇 🧆 🧈 🦪 🧃 🧉 🧊 🛕 🦽 🦼 🛺 🪂 🪐 🤿 🪀 🪁 🦺 🥻 🩱 🩲 🩳 🩰 🪕 🪔 🪓 🦯 🩸 🩹 🩺 🪑 🪒 🤎 🤍 🟠 🟡 🟢 🟣 🟤 🟥 🟧 🟨 🟩 🟦 🟪 🟫";
+
+ [Benchmark]
+ public TextLayout BuildEmojisTextLayout() => new TextLayout(Emojis, Typeface.Default, 12d, Brushes.Black);
+
+ public void Dispose()
+ {
+ _app?.Dispose();
+ }
+}
diff --git a/tests/Avalonia.Controls.DataGrid.UnitTests/Avalonia.Controls.DataGrid.UnitTests.csproj b/tests/Avalonia.Controls.DataGrid.UnitTests/Avalonia.Controls.DataGrid.UnitTests.csproj
index eb1bf24d0c..20c2f711ad 100644
--- a/tests/Avalonia.Controls.DataGrid.UnitTests/Avalonia.Controls.DataGrid.UnitTests.csproj
+++ b/tests/Avalonia.Controls.DataGrid.UnitTests/Avalonia.Controls.DataGrid.UnitTests.csproj
@@ -1,7 +1,6 @@
net6.0
- latest
Library
true
diff --git a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj
index 12eb290fde..471f19f948 100644
--- a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj
+++ b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj
@@ -1,7 +1,6 @@
net6.0
- latest
Library
true
diff --git a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
index d6c521decd..baf933bd66 100644
--- a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
@@ -596,7 +596,7 @@ namespace Avalonia.Controls.UnitTests
private static Window PreparedWindow(object content = null)
{
var renderer = new Mock();
- var platform = AvaloniaLocator.Current.GetService();
+ var platform = AvaloniaLocator.Current.GetRequiredService();
var windowImpl = Mock.Get(platform.CreateWindow());
windowImpl.Setup(x => x.CreateRenderer(It.IsAny())).Returns(renderer.Object);
diff --git a/tests/Avalonia.Controls.UnitTests/FlyoutTests.cs b/tests/Avalonia.Controls.UnitTests/FlyoutTests.cs
index 496b5bc1b6..02767a21eb 100644
--- a/tests/Avalonia.Controls.UnitTests/FlyoutTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/FlyoutTests.cs
@@ -570,7 +570,7 @@ namespace Avalonia.Controls.UnitTests
private static Window PreparedWindow(object content = null)
{
var renderer = new Mock();
- var platform = AvaloniaLocator.Current.GetService();
+ var platform = AvaloniaLocator.Current.GetRequiredService();
var windowImpl = Mock.Get(platform.CreateWindow());
windowImpl.Setup(x => x.CreateRenderer(It.IsAny())).Returns(renderer.Object);
diff --git a/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs
index 90c6fd3b21..c1d9fad6f4 100644
--- a/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs
@@ -827,7 +827,7 @@ namespace Avalonia.Controls.UnitTests
{
AvaloniaLocator.CurrentMutable.Bind().ToSingleton();
- var clipboard = AvaloniaLocator.CurrentMutable.GetService();
+ var clipboard = AvaloniaLocator.CurrentMutable.GetRequiredService();
clipboard.SetTextAsync(textInput).GetAwaiter().GetResult();
RaiseKeyEvent(target, Key.V, KeyModifiers.Control);
diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs
index 2d1dad6be0..469bcecfb9 100644
--- a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs
+++ b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs
@@ -569,7 +569,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
var target = CreateTarget(itemCount: 10);
var items = (IList)target.Items;
target.ApplyTemplate();
- target.Measure(default(Size));
+ target.Measure(default);
target.Arrange(default);
// Check for issue #591: this should not throw.
diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
index d4193d33ee..65957fda6d 100644
--- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
@@ -564,7 +564,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
using (CreateServices())
{
var renderer = new Mock();
- var platform = AvaloniaLocator.Current.GetService();
+ var platform = AvaloniaLocator.Current.GetRequiredService();
var windowImpl = Mock.Get(platform.CreateWindow());
windowImpl.Setup(x => x.CreateRenderer(It.IsAny())).Returns(renderer.Object);
diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
index bd6d5d55e2..531a2869cd 100644
--- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
@@ -767,7 +767,7 @@ namespace Avalonia.Controls.UnitTests
{
AvaloniaLocator.CurrentMutable.Bind().ToSingleton();
- var clipboard = AvaloniaLocator.CurrentMutable.GetService();
+ var clipboard = AvaloniaLocator.CurrentMutable.GetRequiredService();
clipboard.SetTextAsync(textInput).GetAwaiter().GetResult();
RaiseKeyEvent(target, Key.V, KeyModifiers.Control);
@@ -876,7 +876,7 @@ namespace Avalonia.Controls.UnitTests
AvaloniaLocator.CurrentMutable.Bind().ToSingleton();
- var clipboard = AvaloniaLocator.CurrentMutable.GetService();
+ var clipboard = AvaloniaLocator.CurrentMutable.GetRequiredService();
clipboard.SetTextAsync(Environment.NewLine).GetAwaiter().GetResult();
RaiseKeyEvent(target, Key.V, KeyModifiers.Control);
diff --git a/tests/Avalonia.Controls.UnitTests/TransitioningContentControlTests.cs b/tests/Avalonia.Controls.UnitTests/TransitioningContentControlTests.cs
new file mode 100644
index 0000000000..aaa1de4da4
--- /dev/null
+++ b/tests/Avalonia.Controls.UnitTests/TransitioningContentControlTests.cs
@@ -0,0 +1,66 @@
+using System;
+using Avalonia.LogicalTree;
+using Avalonia.UnitTests;
+using Xunit;
+using System.Threading;
+using System.Threading.Tasks;
+using Avalonia.Animation;
+
+namespace Avalonia.Controls.UnitTests
+{
+ public class TransitioningContentControlTests
+ {
+ [Fact]
+ public void Old_Content_Shuold_Be_Removed__From_Logical_Tree_After_Out_Animation()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var testTransition = new TestTransition();
+
+ var target = new TransitioningContentControl();
+ target.PageTransition = testTransition;
+
+ var root = new TestRoot() { Child = target };
+
+ var oldControl = new Control();
+ var newControl = new Control();
+
+ target.Content = oldControl;
+ Threading.Dispatcher.UIThread.RunJobs();
+
+ Assert.Equal(target, oldControl.GetLogicalParent());
+ Assert.Equal(null, newControl.GetLogicalParent());
+
+ testTransition.BeginTransition += isFrom =>
+ {
+ // Old out
+ if (isFrom)
+ {
+ Assert.Equal(target, oldControl.GetLogicalParent());
+ Assert.Equal(null, newControl.GetLogicalParent());
+ }
+ // New in
+ else
+ {
+ Assert.Equal(null, oldControl.GetLogicalParent());
+ Assert.Equal(target, newControl.GetLogicalParent());
+ }
+ };
+
+ target.Content = newControl;
+ Threading.Dispatcher.UIThread.RunJobs();
+ }
+ }
+ }
+ public class TestTransition : IPageTransition
+ {
+ public event Action BeginTransition;
+
+ public Task Start(Visual from, Visual to, bool forward, CancellationToken cancellationToken)
+ {
+ bool isFrom = from != null && to == null;
+ BeginTransition?.Invoke(isFrom);
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
index 81936711ef..f526465b9b 100644
--- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
@@ -1248,7 +1248,7 @@ namespace Avalonia.Controls.UnitTests
using (Application())
{
var focus = FocusManager.Instance;
- var navigation = AvaloniaLocator.Current.GetService();
+ var navigation = AvaloniaLocator.Current.GetRequiredService();
var data = CreateTestTreeData();
var target = new TreeView
@@ -1293,7 +1293,6 @@ namespace Avalonia.Controls.UnitTests
using (Application())
{
var focus = FocusManager.Instance;
- var navigation = AvaloniaLocator.Current.GetService();
var data = CreateTestTreeData();
var selectedNode = new Node { Value = "Out of Tree Selected Item" };
@@ -1353,7 +1352,7 @@ namespace Avalonia.Controls.UnitTests
var rootNode = tree[0];
- var keymap = AvaloniaLocator.Current.GetService();
+ var keymap = AvaloniaLocator.Current.GetRequiredService();
var selectAllGesture = keymap.SelectAll.First();
var keyEvent = new KeyEventArgs
@@ -1400,7 +1399,7 @@ namespace Avalonia.Controls.UnitTests
ClickContainer(fromContainer, KeyModifiers.None);
ClickContainer(toContainer, KeyModifiers.Shift);
- var keymap = AvaloniaLocator.Current.GetService();
+ var keymap = AvaloniaLocator.Current.GetRequiredService();
var selectAllGesture = keymap.SelectAll.First();
var keyEvent = new KeyEventArgs
@@ -1447,7 +1446,7 @@ namespace Avalonia.Controls.UnitTests
ClickContainer(fromContainer, KeyModifiers.None);
ClickContainer(toContainer, KeyModifiers.Shift);
- var keymap = AvaloniaLocator.Current.GetService();
+ var keymap = AvaloniaLocator.Current.GetRequiredService();
var selectAllGesture = keymap.SelectAll.First();
var keyEvent = new KeyEventArgs
diff --git a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json
index eb57cfb8da..0c0857b680 100644
--- a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json
+++ b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package-lock.json
@@ -389,9 +389,9 @@
"dev": true
},
"ansi-regex": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz",
- "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"ansi-styles": {
@@ -405,9 +405,9 @@
}
},
"anymatch": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
- "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
@@ -444,18 +444,6 @@
"sprintf-js": "~1.0.2"
}
},
- "array.prototype.map": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz",
- "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "es-array-method-boxes-properly": "^1.0.0",
- "is-string": "^1.0.4"
- }
- },
"assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
@@ -469,9 +457,9 @@
"dev": true
},
"binary-extensions": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
- "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true
},
"brace-expansion": {
@@ -538,9 +526,9 @@
}
},
"chalk": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
- "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
@@ -554,19 +542,19 @@
"dev": true
},
"chokidar": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
- "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"dev": true,
"requires": {
- "anymatch": "~3.1.1",
+ "anymatch": "~3.1.2",
"braces": "~3.0.2",
- "fsevents": "~2.1.2",
- "glob-parent": "~5.1.0",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
- "readdirp": "~3.4.0"
+ "readdirp": "~3.6.0"
}
},
"clean-stack": {
@@ -576,42 +564,14 @@
"dev": true
},
"cliui": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
- "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"requires": {
- "string-width": "^3.1.0",
- "strip-ansi": "^5.2.0",
- "wrap-ansi": "^5.1.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
- "dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
}
},
"color-convert": {
@@ -708,15 +668,6 @@
"strip-bom": "^4.0.0"
}
},
- "define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "dev": true,
- "requires": {
- "object-keys": "^1.0.12"
- }
- },
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
@@ -724,68 +675,23 @@
"dev": true
},
"emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
- "dev": true
- },
- "es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- },
- "es-array-method-boxes-properly": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
- "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
- "es-get-iterator": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz",
- "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==",
- "dev": true,
- "requires": {
- "es-abstract": "^1.17.4",
- "has-symbols": "^1.0.1",
- "is-arguments": "^1.0.4",
- "is-map": "^2.0.1",
- "is-set": "^2.0.1",
- "is-string": "^1.0.5",
- "isarray": "^2.0.5"
- }
- },
- "es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- }
- },
"es6-error": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
"dev": true
},
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true
+ },
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -829,13 +735,10 @@
}
},
"flat": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
- "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
- "dev": true,
- "requires": {
- "is-buffer": "~2.0.3"
- }
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true
},
"foreground-child": {
"version": "2.0.0",
@@ -860,18 +763,12 @@
"dev": true
},
"fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
"gensync": {
"version": "1.0.0-beta.1",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
@@ -911,9 +808,9 @@
}
},
"glob-parent": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
@@ -931,33 +828,12 @@
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
"dev": true
},
- "growl": {
- "version": "1.10.5",
- "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
- "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
- "dev": true
- },
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
- "has-symbols": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
- "dev": true
- },
"hasha": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz",
@@ -1008,12 +884,6 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
- "is-arguments": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
- "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==",
- "dev": true
- },
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -1023,51 +893,27 @@
"binary-extensions": "^2.0.0"
}
},
- "is-buffer": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
- "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
- "dev": true
- },
- "is-callable": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz",
- "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==",
- "dev": true
- },
- "is-date-object": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
- "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
- "dev": true
- },
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true
},
"is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"is-glob": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
- "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
- "is-map": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz",
- "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==",
- "dev": true
- },
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -1075,24 +921,9 @@
"dev": true
},
"is-plain-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
- "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
- "dev": true
- },
- "is-regex": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
- "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.1"
- }
- },
- "is-set": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz",
- "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"dev": true
},
"is-stream": {
@@ -1101,39 +932,24 @@
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
"dev": true
},
- "is-string": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
- "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
- "dev": true
- },
- "is-symbol": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
- "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.1"
- }
- },
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true
+ },
"is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
"dev": true
},
- "isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true
- },
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -1222,22 +1038,6 @@
"istanbul-lib-report": "^3.0.0"
}
},
- "iterate-iterator": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz",
- "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==",
- "dev": true
- },
- "iterate-value": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz",
- "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==",
- "dev": true,
- "requires": {
- "es-get-iterator": "^1.0.2",
- "iterate-iterator": "^1.0.1"
- }
- },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -1261,13 +1061,10 @@
"dev": true
},
"json5": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
- "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.2.tgz",
+ "integrity": "sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==",
+ "dev": true
},
"locate-path": {
"version": "6.0.0",
@@ -1291,12 +1088,13 @@
"dev": true
},
"log-symbols": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
- "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"dev": true,
"requires": {
- "chalk": "^4.0.0"
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
}
},
"loose-envify": {
@@ -1332,43 +1130,133 @@
"brace-expansion": "^1.1.7"
}
},
- "minimist": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
- "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
- "dev": true
- },
"mocha": {
- "version": "8.1.3",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.3.tgz",
- "integrity": "sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw==",
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
+ "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
"dev": true,
"requires": {
"ansi-colors": "4.1.1",
"browser-stdout": "1.3.1",
- "chokidar": "3.4.2",
- "debug": "4.1.1",
- "diff": "4.0.2",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
"escape-string-regexp": "4.0.0",
"find-up": "5.0.0",
- "glob": "7.1.6",
- "growl": "1.10.5",
+ "glob": "7.2.0",
"he": "1.2.0",
- "js-yaml": "3.14.0",
- "log-symbols": "4.0.0",
- "minimatch": "3.0.4",
- "ms": "2.1.2",
- "object.assign": "4.1.0",
- "promise.allsettled": "1.0.2",
- "serialize-javascript": "4.0.0",
- "strip-json-comments": "3.0.1",
- "supports-color": "7.1.0",
- "which": "2.0.2",
- "wide-align": "1.1.3",
- "workerpool": "6.0.0",
- "yargs": "13.3.2",
- "yargs-parser": "13.1.2",
- "yargs-unparser": "1.6.1"
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "dependencies": {
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ }
+ }
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
}
},
"moq.ts": {
@@ -1386,6 +1274,12 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
+ "nanoid": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+ "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
+ "dev": true
+ },
"node-preload": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
@@ -1570,30 +1464,6 @@
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"dev": true
},
- "object-inspect": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
- "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
- "dev": true
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- },
- "object.assign": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
- "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.2",
- "function-bind": "^1.1.1",
- "has-symbols": "^1.0.0",
- "object-keys": "^1.0.11"
- }
- },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -1604,12 +1474,12 @@
}
},
"p-limit": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz",
- "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"requires": {
- "p-try": "^2.0.0"
+ "yocto-queue": "^0.1.0"
}
},
"p-locate": {
@@ -1679,9 +1549,9 @@
"dev": true
},
"picomatch": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
- "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true
},
"pkg-dir": {
@@ -1741,19 +1611,6 @@
"fromentries": "^1.2.0"
}
},
- "promise.allsettled": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz",
- "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==",
- "dev": true,
- "requires": {
- "array.prototype.map": "^1.0.1",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "function-bind": "^1.1.1",
- "iterate-value": "^1.0.0"
- }
- },
"prop-types": {
"version": "15.7.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
@@ -1792,9 +1649,9 @@
"dev": true
},
"readdirp": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
- "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
@@ -1858,9 +1715,9 @@
"dev": true
},
"serialize-javascript": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
- "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
@@ -1938,42 +1795,23 @@
"dev": true
},
"string-width": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
- "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
- "dev": true,
- "requires": {
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^4.0.0"
- }
- },
- "string.prototype.trimend": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
- "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
- }
- },
- "string.prototype.trimstart": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
- "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
}
},
"strip-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
- "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": {
- "ansi-regex": "^3.0.0"
+ "ansi-regex": "^5.0.1"
}
},
"strip-bom": {
@@ -1983,9 +1821,9 @@
"dev": true
},
"strip-json-comments": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
- "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"supports-color": {
@@ -2090,82 +1928,21 @@
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
"dev": true
},
- "wide-align": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
- "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
- "dev": true,
- "requires": {
- "string-width": "^1.0.2 || 2"
- }
- },
"workerpool": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz",
- "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+ "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
"dev": true
},
"wrap-ansi": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
- "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"requires": {
- "ansi-styles": "^3.2.0",
- "string-width": "^3.0.0",
- "strip-ansi": "^5.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
- "dev": true
- },
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
- "dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
}
},
"wrappy": {
@@ -2193,214 +1970,57 @@
"dev": true
},
"yargs": {
- "version": "13.3.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
- "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"requires": {
- "cliui": "^5.0.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^2.0.1",
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^3.0.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^13.1.2"
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
},
"dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true
- },
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
}
}
},
"yargs-parser": {
- "version": "13.1.2",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
- "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
- "dev": true,
- "requires": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- }
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "dev": true
},
"yargs-unparser": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz",
- "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
"dev": true,
"requires": {
- "camelcase": "^5.3.1",
- "decamelize": "^1.2.0",
- "flat": "^4.1.0",
- "is-plain-obj": "^1.1.0",
- "yargs": "^14.2.3"
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
},
"dependencies": {
- "ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true
},
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
"dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- },
- "yargs": {
- "version": "14.2.3",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
- "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
- "dev": true,
- "requires": {
- "cliui": "^5.0.0",
- "decamelize": "^1.2.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^2.0.1",
- "require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^3.0.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^15.0.1"
- }
- },
- "yargs-parser": {
- "version": "15.0.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz",
- "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
- "dev": true,
- "requires": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- }
}
}
},
@@ -2409,6 +2029,12 @@
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true
}
}
}
diff --git a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json
index dbb12e192a..580c4059ba 100644
--- a/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json
+++ b/tests/Avalonia.DesignerSupport.Tests/Remote/HtmlTransport/webapp/package.json
@@ -16,7 +16,7 @@
"@types/mocha": "8.0.3",
"@types/react": "^16.3.14",
"chai": "^4.2.0",
- "mocha": "^8.1.3",
+ "mocha": "^10.2.0",
"moq.ts": "^6.4.0",
"nyc": "^15.1.0",
"react": "^16.3.2",
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
index 6dce5eaab5..fa4957c24c 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
@@ -3,7 +3,6 @@
net6.0;net47
Library
true
- latest
diff --git a/tests/Avalonia.ReactiveUI.UnitTests/AutoSuspendHelperTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/AutoSuspendHelperTest.cs
index 196375fb40..30326adba5 100644
--- a/tests/Avalonia.ReactiveUI.UnitTests/AutoSuspendHelperTest.cs
+++ b/tests/Avalonia.ReactiveUI.UnitTests/AutoSuspendHelperTest.cs
@@ -47,7 +47,7 @@ namespace Avalonia.ReactiveUI.UnitTests
using (var lifetime = new ClassicDesktopStyleApplicationLifetime())
{
var isLaunchingReceived = false;
- var application = AvaloniaLocator.Current.GetService();
+ var application = AvaloniaLocator.Current.GetRequiredService();
application.ApplicationLifetime = lifetime;
// Initialize ReactiveUI Suspension as in real-world scenario.
@@ -65,7 +65,7 @@ namespace Avalonia.ReactiveUI.UnitTests
using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
using (var lifetime = new ExoticApplicationLifetimeWithoutLifecycleEvents())
{
- var application = AvaloniaLocator.Current.GetService();
+ var application = AvaloniaLocator.Current.GetRequiredService();
application.ApplicationLifetime = lifetime;
Assert.Throws(() => new AutoSuspendHelper(application.ApplicationLifetime));
}
@@ -88,7 +88,7 @@ namespace Avalonia.ReactiveUI.UnitTests
using (var lifetime = new ClassicDesktopStyleApplicationLifetime())
{
var shouldPersistReceived = false;
- var application = AvaloniaLocator.Current.GetService();
+ var application = AvaloniaLocator.Current.GetRequiredService();
application.ApplicationLifetime = lifetime;
// Initialize ReactiveUI Suspension as in real-world scenario.
diff --git a/tests/Avalonia.RenderTests/Controls/AdornerTests.cs b/tests/Avalonia.RenderTests/Controls/AdornerTests.cs
new file mode 100644
index 0000000000..c833017212
--- /dev/null
+++ b/tests/Avalonia.RenderTests/Controls/AdornerTests.cs
@@ -0,0 +1,73 @@
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using Avalonia.Layout;
+using Avalonia.Media;
+using Xunit;
+
+#if AVALONIA_SKIA
+namespace Avalonia.Skia.RenderTests;
+#else
+namespace Avalonia.Direct2D1.RenderTests.Controls;
+#endif
+
+public class AdornerTests : TestBase
+{
+ public AdornerTests()
+ : base(@"Controls\Adorner")
+ {
+ }
+
+ [Fact]
+ public async Task Focus_Adorner_Is_Properly_Clipped()
+ {
+ Border adorned;
+ var tree = new Decorator
+ {
+ Child = new VisualLayerManager
+ {
+ Child = new Border
+ {
+ Background = Brushes.Red,
+ Padding = new Thickness(10, 50, 10,10),
+ Child = new Border()
+ {
+ Background = Brushes.White,
+ ClipToBounds = true,
+ Padding = new Thickness(0, -30, 0, 0),
+ Child = adorned = new Border
+ {
+ Background = Brushes.Green,
+ VerticalAlignment = VerticalAlignment.Top,
+ Height = 100,
+ Width = 50
+ }
+ }
+ }
+ },
+ Width = 200,
+ Height = 200
+ };
+ var adorner = new Border
+ {
+ BorderThickness = new Thickness(2),
+ BorderBrush = Brushes.Black
+ };
+
+ var size = new Size(tree.Width, tree.Height);
+ tree.Measure(size);
+ tree.Arrange(new Rect(size));
+
+
+ adorned.AttachedToVisualTree += delegate
+ {
+ AdornerLayer.SetAdornedElement(adorner, adorned);
+ AdornerLayer.GetAdornerLayer(adorned)!.Children.Add(adorner);
+ };
+ tree.Measure(size);
+ tree.Arrange(new Rect(size));
+
+ await RenderToFile(tree);
+ CompareImages(skipImmediate: true, skipDeferred: true);
+ }
+}
\ No newline at end of file
diff --git a/tests/Avalonia.RenderTests/TestBase.cs b/tests/Avalonia.RenderTests/TestBase.cs
index 8a127897d7..edde62f041 100644
--- a/tests/Avalonia.RenderTests/TestBase.cs
+++ b/tests/Avalonia.RenderTests/TestBase.cs
@@ -91,7 +91,7 @@ namespace Avalonia.Direct2D1.RenderTests
var immediatePath = Path.Combine(OutputPath, testName + ".immediate.out.png");
var deferredPath = Path.Combine(OutputPath, testName + ".deferred.out.png");
var compositedPath = Path.Combine(OutputPath, testName + ".composited.out.png");
- var factory = AvaloniaLocator.Current.GetService();
+ var factory = AvaloniaLocator.Current.GetRequiredService();
var pixelSize = new PixelSize((int)target.Width, (int)target.Height);
var size = new Size(target.Width, target.Height);
var dpiVector = new Vector(dpi, dpi);
@@ -156,7 +156,8 @@ namespace Avalonia.Direct2D1.RenderTests
public ILockedFramebuffer Lock() => _bitmap.Lock();
}
- protected void CompareImages([CallerMemberName] string testName = "")
+ protected void CompareImages([CallerMemberName] string testName = "",
+ bool skipImmediate = false, bool skipDeferred = false, bool skipCompositor = false)
{
var expectedPath = Path.Combine(OutputPath, testName + ".expected.png");
var immediatePath = Path.Combine(OutputPath, testName + ".immediate.out.png");
@@ -172,17 +173,17 @@ namespace Avalonia.Direct2D1.RenderTests
var deferredError = CompareImages(deferred, expected);
var compositedError = CompareImages(composited, expected);
- if (immediateError > 0.022)
+ if (immediateError > 0.022 && !skipImmediate)
{
Assert.True(false, immediatePath + ": Error = " + immediateError);
}
- if (deferredError > 0.022)
+ if (deferredError > 0.022 && !skipDeferred)
{
Assert.True(false, deferredPath + ": Error = " + deferredError);
}
- if (compositedError > 0.022)
+ if (compositedError > 0.022 && !skipCompositor)
{
Assert.True(false, compositedPath + ": Error = " + compositedError);
}
diff --git a/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj b/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj
index ccde66a50e..ea91b8c196 100644
--- a/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj
+++ b/tests/Avalonia.Skia.UnitTests/Avalonia.Skia.UnitTests.csproj
@@ -1,7 +1,6 @@
net6.0
- latest
diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
index 33d4fba5f1..7fc27b01f4 100644
--- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
+++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextFormatterTests.cs
@@ -520,7 +520,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var expectedTextLine = formatter.FormatLine(new SingleBufferTextSource(text, defaultProperties),
0, double.PositiveInfinity, paragraphProperties);
- var expectedRuns = expectedTextLine.TextRuns.Cast().ToList();
+ var expectedRuns = expectedTextLine.TextRuns.Cast().ToList();
var expectedGlyphs = expectedRuns.SelectMany(x => x.GlyphRun.GlyphIndices).ToList();
@@ -539,7 +539,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var textLine =
formatter.FormatLine(textSource, 0, double.PositiveInfinity, paragraphProperties);
- var shapedRuns = textLine.TextRuns.Cast().ToList();
+ var shapedRuns = textLine.TextRuns.Cast().ToList();
var actualGlyphs = shapedRuns.SelectMany(x => x.GlyphRun.GlyphIndices).ToList();
diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
index a407b38eb1..7501bf21fe 100644
--- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
+++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs
@@ -141,7 +141,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
black,
textWrapping: TextWrapping.Wrap);
- var expectedGlyphs = expected.TextLines.Select(x => string.Join('|', x.TextRuns.Cast()
+ var expectedGlyphs = expected.TextLines.Select(x => string.Join('|', x.TextRuns.Cast()
.SelectMany(x => x.ShapedBuffer.GlyphIndices))).ToList();
var outer = new GraphemeEnumerator(new CharacterBufferRange(text));
@@ -153,7 +153,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
while (inner.MoveNext())
{
- j += inner.Current.Text.Length;
+ j += inner.Current.Length;
if (j + i > text.Length)
{
@@ -174,7 +174,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
textWrapping: TextWrapping.Wrap,
textStyleOverrides: spans);
- var actualGlyphs = actual.TextLines.Select(x => string.Join('|', x.TextRuns.Cast()
+ var actualGlyphs = actual.TextLines.Select(x => string.Join('|', x.TextRuns.Cast()
.SelectMany(x => x.ShapedBuffer.GlyphIndices))).ToList();
Assert.Equal(expectedGlyphs.Count, actualGlyphs.Count);
@@ -192,7 +192,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
inner = new GraphemeEnumerator(new CharacterBufferRange(text));
- i += outer.Current.Text.Length;
+ i += outer.Current.Length;
}
}
}
@@ -447,7 +447,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
12.0f,
Brushes.Black.ToImmutable());
- var shapedRun = (ShapedTextCharacters)layout.TextLines[0].TextRuns[0];
+ var shapedRun = (ShapedTextRun)layout.TextLines[0].TextRuns[0];
var glyphRun = shapedRun.GlyphRun;
@@ -481,7 +481,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
foreach (var textRun in textLine.TextRuns)
{
- var shapedRun = (ShapedTextCharacters)textRun;
+ var shapedRun = (ShapedTextRun)textRun;
var glyphClusters = shapedRun.ShapedBuffer.GlyphClusters;
@@ -514,13 +514,13 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal(1, layout.TextLines[0].TextRuns.Count);
- Assert.Equal(expectedLength, ((ShapedTextCharacters)layout.TextLines[0].TextRuns[0]).GlyphRun.GlyphClusters.Count);
+ Assert.Equal(expectedLength, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).GlyphRun.GlyphClusters.Count);
- Assert.Equal(5, ((ShapedTextCharacters)layout.TextLines[0].TextRuns[0]).ShapedBuffer.GlyphClusters[5]);
+ Assert.Equal(5, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).ShapedBuffer.GlyphClusters[5]);
if (expectedLength == 7)
{
- Assert.Equal(5, ((ShapedTextCharacters)layout.TextLines[0].TextRuns[0]).ShapedBuffer.GlyphClusters[6]);
+ Assert.Equal(5, ((ShapedTextRun)layout.TextLines[0].TextRuns[0]).ShapedBuffer.GlyphClusters[6]);
}
}
}
@@ -555,7 +555,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var textLine = layout.TextLines[0];
- var textRun = (ShapedTextCharacters)textLine.TextRuns[0];
+ var textRun = (ShapedTextRun)textLine.TextRuns[0];
Assert.Equal(7, textRun.Length);
@@ -775,7 +775,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Assert.Equal(textLine.WidthIncludingTrailingWhitespace, rect.Width);
}
- var rects = layout.TextLines.SelectMany(x => x.TextRuns.Cast())
+ var rects = layout.TextLines.SelectMany(x => x.TextRuns.Cast())
.SelectMany(x => x.ShapedBuffer.GlyphAdvances).ToArray();
for (var i = 0; i < SingleLineText.Length; i++)
@@ -814,7 +814,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
Assert.True(textLine.Width <= maxWidth);
- var actual = new string(textLine.TextRuns.Cast()
+ var actual = new string(textLine.TextRuns.Cast()
.OrderBy(x => x.CharacterBufferReference.OffsetToFirstChar)
.SelectMany(x => new CharacterBufferRange(x.CharacterBufferReference, x.Length)).ToArray());
@@ -855,7 +855,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
Brushes.Black,
flowDirection: FlowDirection.RightToLeft);
- var firstRun = layout.TextLines[0].TextRuns[0] as ShapedTextCharacters;
+ var firstRun = layout.TextLines[0].TextRuns[0] as ShapedTextRun;
var hit = layout.HitTestPoint(new Point());
@@ -881,7 +881,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
currentX += advance;
}
- var secondRun = layout.TextLines[0].TextRuns[1] as ShapedTextCharacters;
+ var secondRun = layout.TextLines[0].TextRuns[1] as ShapedTextRun;
hit = layout.HitTestPoint(new Point(firstRun.Size.Width, 0));
@@ -928,7 +928,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var textLine = layout.TextLines[0];
- var firstRun = (ShapedTextCharacters)textLine.TextRuns[0];
+ var firstRun = (ShapedTextRun)textLine.TextRuns[0];
var firstCluster = firstRun.ShapedBuffer.GlyphClusters[0];
@@ -974,9 +974,9 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
{
var grapheme = graphemeEnumerator.Current;
- var textStyleOverrides = new[] { new ValueSpan(i, grapheme.Text.Length, new GenericTextRunProperties(Typeface.Default, 12, foregroundBrush: Brushes.Red)) };
+ var textStyleOverrides = new[] { new ValueSpan(i, grapheme.Length, new GenericTextRunProperties(Typeface.Default, 12, foregroundBrush: Brushes.Red)) };
- i += grapheme.Text.Length;
+ i += grapheme.Length;
var layout = new TextLayout(
text,
@@ -987,7 +987,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var textLine = layout.TextLines[0];
- var shapedRuns = textLine.TextRuns.Cast().ToList();
+ var shapedRuns = textLine.TextRuns.Cast().ToList();
var clusters = shapedRuns.SelectMany(x => x.ShapedBuffer.GlyphClusters).ToList();
diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs
index d6257a0de8..ac2467407b 100644
--- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs
+++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLineTests.cs
@@ -92,7 +92,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
foreach (var textRun in textLine.TextRuns.OrderBy(x => x.CharacterBufferReference.OffsetToFirstChar))
{
- var shapedRun = (ShapedTextCharacters)textRun;
+ var shapedRun = (ShapedTextRun)textRun;
clusters.AddRange(shapedRun.IsReversed ?
shapedRun.ShapedBuffer.GlyphClusters.Reverse() :
@@ -139,7 +139,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
foreach (var textRun in textLine.TextRuns.OrderBy(x => x.CharacterBufferReference.OffsetToFirstChar))
{
- var shapedRun = (ShapedTextCharacters)textRun;
+ var shapedRun = (ShapedTextRun)textRun;
clusters.AddRange(shapedRun.IsReversed ?
shapedRun.ShapedBuffer.GlyphClusters.Reverse() :
@@ -246,7 +246,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
new GenericTextParagraphProperties(defaultProperties));
- var clusters = textLine.TextRuns.Cast().SelectMany(x => x.ShapedBuffer.GlyphClusters)
+ var clusters = textLine.TextRuns.Cast().SelectMany(x => x.ShapedBuffer.GlyphClusters)
.ToArray();
var previousCharacterHit = new CharacterHit(text.Length);
@@ -308,7 +308,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
foreach (var run in textLine.TextRuns)
{
- var textRun = (ShapedTextCharacters)run;
+ var textRun = (ShapedTextRun)run;
var glyphRun = textRun.GlyphRun;
@@ -634,7 +634,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
new GenericTextParagraphProperties(defaultProperties));
- var textRuns = textLine.TextRuns.Cast().ToList();
+ var textRuns = textLine.TextRuns.Cast().ToList();
var lineWidth = textLine.WidthIncludingTrailingWhitespace;
@@ -732,14 +732,14 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
private static bool IsRightToLeft(TextLine textLine)
{
- return textLine.TextRuns.Cast().Any(x => !x.ShapedBuffer.IsLeftToRight);
+ return textLine.TextRuns.Cast().Any(x => !x.ShapedBuffer.IsLeftToRight);
}
private static List BuildGlyphClusters(TextLine textLine)
{
var glyphClusters = new List();
- var shapedTextRuns = textLine.TextRuns.Cast().ToList();
+ var shapedTextRuns = textLine.TextRuns.Cast().ToList();
var lastCluster = -1;
@@ -774,7 +774,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var lastCluster = -1;
- var shapedTextRuns = textLine.TextRuns.Cast().ToList();
+ var shapedTextRuns = textLine.TextRuns.Cast().ToList();
foreach (var textRun in shapedTextRuns)
{
@@ -820,16 +820,16 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var text = "0123";
var shaperOption = new TextShaperOptions(Typeface.Default.GlyphTypeface, 10, 0, CultureInfo.CurrentCulture);
- var firstRun = new ShapedTextCharacters(TextShaper.Current.ShapeText(text, shaperOption), defaultProperties);
+ var firstRun = new ShapedTextRun(TextShaper.Current.ShapeText(text, shaperOption), defaultProperties);
var textRuns = new List
{
new CustomDrawableRun(),
firstRun,
new CustomDrawableRun(),
- new ShapedTextCharacters(TextShaper.Current.ShapeText(text, shaperOption), defaultProperties),
+ new ShapedTextRun(TextShaper.Current.ShapeText(text, shaperOption), defaultProperties),
new CustomDrawableRun(),
- new ShapedTextCharacters(TextShaper.Current.ShapeText(text, shaperOption), defaultProperties)
+ new ShapedTextRun(TextShaper.Current.ShapeText(text, shaperOption), defaultProperties)
};
var textSource = new FixedRunsTextSource(textRuns);
@@ -885,14 +885,14 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var textBounds = textLine.GetTextBounds(0, 3);
- var firstRun = textLine.TextRuns[0] as ShapedTextCharacters;
+ var firstRun = textLine.TextRuns[0] as ShapedTextRun;
Assert.Equal(1, textBounds.Count);
Assert.Equal(firstRun.Size.Width, textBounds.Sum(x => x.Rectangle.Width));
textBounds = textLine.GetTextBounds(3, 4);
- var secondRun = textLine.TextRuns[1] as ShapedTextCharacters;
+ var secondRun = textLine.TextRuns[1] as ShapedTextRun;
Assert.Equal(1, textBounds.Count);
Assert.Equal(secondRun.Size.Width, textBounds.Sum(x => x.Rectangle.Width));
@@ -932,14 +932,14 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
var textBounds = textLine.GetTextBounds(0, 4);
- var secondRun = textLine.TextRuns[1] as ShapedTextCharacters;
+ var secondRun = textLine.TextRuns[1] as ShapedTextRun;
Assert.Equal(1, textBounds.Count);
Assert.Equal(secondRun.Size.Width, textBounds.Sum(x => x.Rectangle.Width));
textBounds = textLine.GetTextBounds(4, 3);
- var firstRun = textLine.TextRuns[0] as ShapedTextCharacters;
+ var firstRun = textLine.TextRuns[0] as ShapedTextRun;
Assert.Equal(1, textBounds.Count);
diff --git a/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj b/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
index cb6884cad8..17448ade76 100644
--- a/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
+++ b/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
@@ -1,11 +1,9 @@
netstandard2.0
- latest
false
Library
false
- latest
..\..\build\avalonia.snk
false
true
diff --git a/tests/Avalonia.UnitTests/HarfBuzzFontManagerImpl.cs b/tests/Avalonia.UnitTests/HarfBuzzFontManagerImpl.cs
index 2b1685f358..55ac16054d 100644
--- a/tests/Avalonia.UnitTests/HarfBuzzFontManagerImpl.cs
+++ b/tests/Avalonia.UnitTests/HarfBuzzFontManagerImpl.cs
@@ -76,13 +76,8 @@ namespace Avalonia.UnitTests
var asset = fontAssets.First();
- var assetLoader = AvaloniaLocator.Current.GetService();
+ var assetLoader = AvaloniaLocator.Current.GetRequiredService();
- if (assetLoader == null)
- {
- throw new NotSupportedException("IAssetLoader is not registered.");
- }
-
var stream = assetLoader.Open(asset);
return new HarfBuzzGlyphTypefaceImpl(stream);
diff --git a/tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png b/tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png
new file mode 100644
index 0000000000..6a67087d41
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png differ
diff --git a/tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png b/tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png
new file mode 100644
index 0000000000..6a67087d41
Binary files /dev/null and b/tests/TestFiles/Skia/Controls/Adorner/Focus_Adorner_Is_Properly_Clipped.expected.png differ