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/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/global.json b/global.json
index a3e251852f..e4a0cc20c2 100644
--- a/global.json
+++ b/global.json
@@ -4,8 +4,6 @@
"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/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/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/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/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/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/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..db035b8750 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);
}
@@ -199,7 +199,7 @@ namespace Avalonia.Media.TextFormatting
count += grapheme.Text.Length;
}
- return new ShapeableTextCharacters(characterBufferRange.CharacterBufferReference, count, defaultProperties, biDiLevel);
+ return new UnshapedTextRun(characterBufferRange.CharacterBufferReference, count, defaultProperties, biDiLevel);
}
///
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/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/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/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/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 0c25d89722..8fc91a02d8 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 5930df5483..7e22303964 100644
--- a/src/Avalonia.Base/Visual.cs
+++ b/src/Avalonia.Base/Visual.cs
@@ -480,6 +480,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 cadecc03bc..81715e022b 100644
--- a/src/Avalonia.Controls.DataGrid/DataGrid.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs
@@ -1118,7 +1118,7 @@ namespace Avalonia.Controls
EnsureColumnHeadersVisibility();
if (!newValueCols)
{
- _columnHeadersPresenter.Measure(default(Size));
+ _columnHeadersPresenter.Measure(default);
}
else
{
@@ -1159,7 +1159,7 @@ namespace Avalonia.Controls
_topLeftCornerHeader.IsVisible = newValueRows && newValueCols;
if (_topLeftCornerHeader.IsVisible)
{
- _topLeftCornerHeader.Measure(default(Size));
+ _topLeftCornerHeader.Measure(default);
}
}
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 63e7e1e2b3..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();
///
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/AutoCompleteBox/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs
index e0d986f2b4..f9978d2795 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/Control.cs b/src/Avalonia.Controls/Control.cs
index 26db431a0e..ed24c3c7c2 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -392,14 +392,6 @@ namespace Avalonia.Controls
OnUnloadedCore();
}
- ///
- protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
- {
- base.OnAttachedToVisualTree(e);
-
- InvalidateMirrorTransform();
- }
-
///
protected override void OnGotFocus(GotFocusEventArgs e)
{
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 5b2356a7ce..196fd898cf 100644
--- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs
+++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs
@@ -41,7 +41,7 @@ namespace Avalonia.Platform
{
_draggedData = data;
_lastRoot = null;
- _lastPosition = default(Point);
+ _lastPosition = default;
_allowedEffects = allowedEffects;
using (_inputManager.PreProcess.OfType().Subscribe(ProcessMouseEvents))
diff --git a/src/Avalonia.Controls/Platform/PlatformManager.cs b/src/Avalonia.Controls/Platform/PlatformManager.cs
index de7708e869..79ace0b329 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 328facba0b..c9bf135bbe 100644
--- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
@@ -94,6 +94,7 @@ namespace Avalonia.Controls.Presenters
{
AddHandler(RequestBringIntoViewEvent, BringIntoViewRequested);
AddHandler(Gestures.ScrollGestureEvent, OnScrollGesture);
+ AddHandler(Gestures.ScrollGestureEndedEvent, OnScrollGestureEnded);
this.GetObservable(ChildProperty).Subscribe(UpdateScrollableSubscription);
}
@@ -500,7 +501,7 @@ namespace Avalonia.Controls.Presenters
if (e.OldValue != null)
{
- Offset = default(Vector);
+ Offset = default;
}
}
@@ -542,7 +543,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/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