diff --git a/Avalonia.sln b/Avalonia.sln
index 4e7b4cc318..0354e20d4f 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -60,20 +60,17 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
+ src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}"
EndProject
-Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlatformSupport", "src\Shared\PlatformSupport\PlatformSupport.shproj", "{E4D9629C-F168-4224-3F51-A5E482FFBC42}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup", "src\Markup\Avalonia.Markup\Avalonia.Markup.csproj", "{6417E941-21BC-467B-A771-0DE389353CE6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BindingDemo", "samples\BindingDemo\BindingDemo.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}"
EndProject
-Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "RenderHelpers", "src\Shared\RenderHelpers\RenderHelpers.shproj", "{3C4C0CB4-0C0F-4450-A37B-148C84FF905F}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Skia", "Skia", "{3743B0F2-CC41-4F14-A8C8-267F579BF91E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}"
@@ -235,15 +232,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsInteropTest", "sampl
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlSamples", "samples\SampleControls\ControlSamples.csproj", "{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport", "src\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj", "{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}"
+EndProject
Global
- GlobalSection(SharedMSBuildProjectFiles) = preSolution
- src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
- src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 5
- src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*SharedItemsImports = 5
- src\Shared\RenderHelpers\RenderHelpers.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 5
- src\Shared\PlatformSupport\PlatformSupport.projitems*{88060192-33d5-4932-b0f9-8bd2763e857d}*SharedItemsImports = 5
- src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13
- EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
Ad-Hoc|iPhone = Ad-Hoc|iPhone
@@ -2169,6 +2160,30 @@ Global
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhone.Build.0 = Release|Any CPU
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhone.Build.0 = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2187,11 +2202,9 @@ Global
{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{99135EAB-653D-47E4-A378-C96E1278CA44} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{3E53A01A-B331-47F3-B828-4A5717E77A24} = {8B6A8209-894F-4BA1-B880-965FD453982C}
- {E4D9629C-F168-4224-3F51-A5E482FFBC42} = {A689DEF5-D50F-4975-8B72-124C9EB54066}
{6417E941-21BC-467B-A771-0DE389353CE6} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{8EF392D5-1416-45AA-9956-7CBBC3229E8A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162} = {9B9E3891-2366-4253-A952-D08BCEB71098}
- {3C4C0CB4-0C0F-4450-A37B-148C84FF905F} = {A689DEF5-D50F-4975-8B72-124C9EB54066}
{7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
{FF69B927-C545-49AE-8E16-3D14D621AA12} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
{4488AD85-1495-4809-9AA4-DDFE0A48527E} = {0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}
diff --git a/build/CoreLibraries.props b/build/CoreLibraries.props
index fff00041c3..3fccad2641 100644
--- a/build/CoreLibraries.props
+++ b/build/CoreLibraries.props
@@ -17,5 +17,6 @@
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 7d75901288..7f24ef35bc 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -3,7 +3,7 @@
Avalonia
0.10.999
- Copyright 2021 © The AvaloniaUI Project
+ Copyright 2022 © The AvaloniaUI Project
https://avaloniaui.net
https://github.com/AvaloniaUI/Avalonia/
true
diff --git a/samples/ControlCatalog.Android/Assets/AboutAssets.txt b/samples/ControlCatalog.Android/Assets/AboutAssets.txt
index ee39886295..a9b0638eb1 100644
--- a/samples/ControlCatalog.Android/Assets/AboutAssets.txt
+++ b/samples/ControlCatalog.Android/Assets/AboutAssets.txt
@@ -1,7 +1,7 @@
Any raw assets you want to be deployed with your application can be placed in
this directory (and child directories) and given a Build Action of "AndroidAsset".
-These files will be deployed with you package and will be accessible using Android's
+These files will be deployed with your package and will be accessible using Android's
AssetManager, like this:
public class ReadAsset : Activity
@@ -16,4 +16,4 @@ public class ReadAsset : Activity
Additionally, some Android functions will automatically load asset files:
-Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
\ No newline at end of file
+Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
diff --git a/samples/ControlCatalog/Pages/PointersPage.cs b/samples/ControlCatalog/Pages/PointersPage.cs
index fddc503a90..2901013cea 100644
--- a/samples/ControlCatalog/Pages/PointersPage.cs
+++ b/samples/ControlCatalog/Pages/PointersPage.cs
@@ -1,15 +1,37 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
+using System.Reactive.Linq;
+using System.Runtime.InteropServices;
+using System.Threading;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
+using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Media.Immutable;
+using Avalonia.Threading;
+using Avalonia.VisualTree;
-namespace ControlCatalog.Pages
+namespace ControlCatalog.Pages;
+
+public class PointersPage : Decorator
{
- public class PointersPage : Control
+ public PointersPage()
+ {
+ Child = new TabControl
+ {
+ Items = new[]
+ {
+ new TabItem() { Header = "Contacts", Content = new PointerContactsTab() },
+ new TabItem() { Header = "IntermediatePoints", Content = new PointerIntermediatePointsTab() }
+ }
+ };
+ }
+
+
+ class PointerContactsTab : Control
{
class PointerInfo
{
@@ -45,7 +67,7 @@ namespace ControlCatalog.Pages
private Dictionary _pointers = new Dictionary();
- public PointersPage()
+ public PointerContactsTab()
{
ClipToBounds = true;
}
@@ -104,4 +126,196 @@ namespace ControlCatalog.Pages
}
}
}
+
+ public class PointerIntermediatePointsTab : Decorator
+ {
+ public PointerIntermediatePointsTab()
+ {
+ this[TextBlock.ForegroundProperty] = Brushes.Black;
+ var slider = new Slider
+ {
+ Margin = new Thickness(5),
+ Minimum = 0,
+ Maximum = 500
+ };
+
+ var status = new TextBlock()
+ {
+ HorizontalAlignment = HorizontalAlignment.Left,
+ VerticalAlignment = VerticalAlignment.Top,
+ };
+ Child = new Grid
+ {
+ Children =
+ {
+ new PointerCanvas(slider, status),
+ new Border
+ {
+ Background = Brushes.LightYellow,
+ Child = new StackPanel
+ {
+ Children =
+ {
+ new StackPanel
+ {
+ Orientation = Orientation.Horizontal,
+ Children =
+ {
+ new TextBlock { Text = "Thread sleep:" },
+ new TextBlock()
+ {
+ [!TextBlock.TextProperty] =slider.GetObservable(Slider.ValueProperty)
+ .Select(x=>x.ToString()).ToBinding()
+ }
+ }
+ },
+ slider
+ }
+ },
+
+ HorizontalAlignment = HorizontalAlignment.Right,
+ VerticalAlignment = VerticalAlignment.Top,
+ Width = 300,
+ Height = 60
+ },
+ status
+ }
+ };
+ }
+
+ class PointerCanvas : Control
+ {
+ private readonly Slider _slider;
+ private readonly TextBlock _status;
+ private int _events;
+ private Stopwatch _stopwatch = Stopwatch.StartNew();
+ private Dictionary _pointers = new();
+ class PointerPoints
+ {
+ struct CanvasPoint
+ {
+ public IBrush Brush;
+ public Point Point;
+ public double Radius;
+ }
+
+ readonly CanvasPoint[] _points = new CanvasPoint[1000];
+ int _index;
+
+ public void Render(DrawingContext context)
+ {
+
+ CanvasPoint? prev = null;
+ for (var c = 0; c < _points.Length; c++)
+ {
+ var i = (c + _index) % _points.Length;
+ var pt = _points[i];
+ if (prev.HasValue && prev.Value.Brush != null && pt.Brush != null)
+ context.DrawLine(new Pen(Brushes.Black), prev.Value.Point, pt.Point);
+ prev = pt;
+ if (pt.Brush != null)
+ context.DrawEllipse(pt.Brush, null, pt.Point, pt.Radius, pt.Radius);
+
+ }
+
+ }
+
+ void AddPoint(Point pt, IBrush brush, double radius)
+ {
+ _points[_index] = new CanvasPoint { Point = pt, Brush = brush, Radius = radius };
+ _index = (_index + 1) % _points.Length;
+ }
+
+ public void HandleEvent(PointerEventArgs e, Visual v)
+ {
+ e.Handled = true;
+ if (e.RoutedEvent == PointerPressedEvent)
+ AddPoint(e.GetPosition(v), Brushes.Green, 10);
+ else if (e.RoutedEvent == PointerReleasedEvent)
+ AddPoint(e.GetPosition(v), Brushes.Red, 10);
+ else
+ {
+ var pts = e.GetIntermediatePoints(v);
+ for (var c = 0; c < pts.Count; c++)
+ {
+ var pt = pts[c];
+ AddPoint(pt.Position, c == pts.Count - 1 ? Brushes.Blue : Brushes.Black,
+ c == pts.Count - 1 ? 5 : 2);
+ }
+ }
+ }
+ }
+
+ public PointerCanvas(Slider slider, TextBlock status)
+ {
+ _slider = slider;
+ _status = status;
+ DispatcherTimer.Run(() =>
+ {
+ if (_stopwatch.Elapsed.TotalSeconds > 1)
+ {
+ _status.Text = "Events per second: " + (_events / _stopwatch.Elapsed.TotalSeconds);
+ _stopwatch.Restart();
+ _events = 0;
+ }
+
+ return this.GetVisualRoot() != null;
+ }, TimeSpan.FromMilliseconds(10));
+ }
+
+
+ void HandleEvent(PointerEventArgs e)
+ {
+ _events++;
+ Thread.Sleep((int)_slider.Value);
+ InvalidateVisual();
+
+ if (e.RoutedEvent == PointerReleasedEvent && e.Pointer.Type == PointerType.Touch)
+ {
+ _pointers.Remove(e.Pointer.Id);
+ return;
+ }
+
+ if (!_pointers.TryGetValue(e.Pointer.Id, out var pt))
+ _pointers[e.Pointer.Id] = pt = new PointerPoints();
+ pt.HandleEvent(e, this);
+
+
+ }
+
+ public override void Render(DrawingContext context)
+ {
+ context.FillRectangle(Brushes.White, Bounds);
+ foreach(var pt in _pointers.Values)
+ pt.Render(context);
+ base.Render(context);
+ }
+
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
+ {
+ if (e.ClickCount == 2)
+ {
+ _pointers.Clear();
+ InvalidateVisual();
+ return;
+ }
+
+ HandleEvent(e);
+ base.OnPointerPressed(e);
+ }
+
+ protected override void OnPointerMoved(PointerEventArgs e)
+ {
+ HandleEvent(e);
+ base.OnPointerMoved(e);
+ }
+
+ protected override void OnPointerReleased(PointerReleasedEventArgs e)
+ {
+ HandleEvent(e);
+ base.OnPointerReleased(e);
+ }
+ }
+
+ }
}
diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs
index 4edb0f137a..caad8b0854 100644
--- a/samples/ControlCatalog/Pages/ScreenPage.cs
+++ b/samples/ControlCatalog/Pages/ScreenPage.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
@@ -49,25 +50,33 @@ namespace ControlCatalog.Pages
context.DrawRectangle(p, boundsRect);
context.DrawRectangle(p, workingAreaRect);
- var text = new FormattedText() { Typeface = new Typeface("Arial"), FontSize = 18 };
- text.Text = $"Bounds: {screen.Bounds.TopLeft} {screen.Bounds.Width}:{screen.Bounds.Height}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height), text);
-
- text.Text = $"WorkArea: {screen.WorkingArea.TopLeft} {screen.WorkingArea.Width}:{screen.WorkingArea.Height}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text);
+ var formattedText = CreateFormattedText($"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height));
- text.Text = $"Scaling: {screen.PixelDensity * 100}%";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
-
- text.Text = $"Primary: {screen.Primary}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
-
- text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 80), text);
+ formattedText =
+ CreateFormattedText($"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 20));
+
+ formattedText = CreateFormattedText($"Scaling: {screen.PixelDensity * 100}%");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40));
+
+ formattedText = CreateFormattedText($"Primary: {screen.Primary}");
+ 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));
}
+
+ private FormattedText CreateFormattedText(string textToFormat)
+ {
+ return new FormattedText(textToFormat, CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
+ Typeface.Default, 12, Brushes.Green);
+ }
}
}
diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml b/samples/ControlCatalog/Pages/ViewboxPage.xaml
index 81e5046636..e7e3007d35 100644
--- a/samples/ControlCatalog/Pages/ViewboxPage.xaml
+++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml
@@ -1,5 +1,6 @@
@@ -12,8 +13,8 @@
+ Stretch="{Binding #StretchSelector.SelectedItem, FallbackValue={x:Static Stretch.Uniform}}"
+ StretchDirection="{Binding #StretchDirectionSelector.SelectedItem, FallbackValue={x:Static StretchDirection.Both}}">
@@ -25,9 +26,22 @@
-
+
+
+ Uniform
+ UniformToFill
+ Fill
+ None
+
+
-
+
+
+ Both
+ DownOnly
+ UpOnly
+
+
diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
index 94b3f3ea14..12b5086e12 100644
--- a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
@@ -1,6 +1,5 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
-using Avalonia.Media;
namespace ControlCatalog.Pages
{
@@ -9,24 +8,6 @@ namespace ControlCatalog.Pages
public ViewboxPage()
{
InitializeComponent();
-
- var stretchSelector = this.FindControl("StretchSelector");
-
- stretchSelector.Items = new[]
- {
- Stretch.Uniform, Stretch.UniformToFill, Stretch.Fill, Stretch.None
- };
-
- stretchSelector.SelectedIndex = 0;
-
- var stretchDirectionSelector = this.FindControl("StretchDirectionSelector");
-
- stretchDirectionSelector.Items = new[]
- {
- StretchDirection.Both, StretchDirection.DownOnly, StretchDirection.UpOnly
- };
-
- stretchDirectionSelector.SelectedIndex = 0;
}
private void InitializeComponent()
diff --git a/samples/RenderDemo/MainWindow.xaml b/samples/RenderDemo/MainWindow.xaml
index a4c6299278..4a8fb819ca 100644
--- a/samples/RenderDemo/MainWindow.xaml
+++ b/samples/RenderDemo/MainWindow.xaml
@@ -57,6 +57,9 @@
+
+
+
diff --git a/samples/RenderDemo/Pages/ClippingPage.xaml b/samples/RenderDemo/Pages/ClippingPage.xaml
index 10225f7c49..698e18d496 100644
--- a/samples/RenderDemo/Pages/ClippingPage.xaml
+++ b/samples/RenderDemo/Pages/ClippingPage.xaml
@@ -19,30 +19,36 @@
-
+
+
+
+
diff --git a/samples/RenderDemo/Pages/ClippingPage.xaml.cs b/samples/RenderDemo/Pages/ClippingPage.xaml.cs
index 5357181838..c5b669343a 100644
--- a/samples/RenderDemo/Pages/ClippingPage.xaml.cs
+++ b/samples/RenderDemo/Pages/ClippingPage.xaml.cs
@@ -1,35 +1,18 @@
-using System;
-using System.Reactive.Linq;
-using Avalonia;
-using Avalonia.Animation;
using Avalonia.Controls;
-using Avalonia.Data;
using Avalonia.Markup.Xaml;
-using Avalonia.Media;
namespace RenderDemo.Pages
{
public class ClippingPage : UserControl
{
- private Geometry _clip;
-
public ClippingPage()
{
InitializeComponent();
- WireUpCheckbox();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
-
- private void WireUpCheckbox()
- {
- var useMask = this.FindControl("useMask");
- var clipped = this.FindControl("clipped");
- _clip = clipped.Clip;
- useMask.Click += (s, e) => clipped.Clip = clipped.Clip == null ? _clip : null;
- }
}
}
diff --git a/samples/RenderDemo/Pages/CustomSkiaPage.cs b/samples/RenderDemo/Pages/CustomSkiaPage.cs
index 2e59d934a1..9c524a7932 100644
--- a/samples/RenderDemo/Pages/CustomSkiaPage.cs
+++ b/samples/RenderDemo/Pages/CustomSkiaPage.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
+using System.Globalization;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
@@ -41,7 +42,10 @@ namespace RenderDemo.Pages
{
var canvas = (context as ISkiaDrawingContextImpl)?.SkCanvas;
if (canvas == null)
- context.DrawText(Brushes.Black, new Point(), _noSkia.PlatformImpl);
+ using (var c = new DrawingContext(context, false))
+ {
+ c.DrawText(_noSkia, new Point());
+ }
else
{
canvas.Save();
@@ -108,10 +112,9 @@ namespace RenderDemo.Pages
public override void Render(DrawingContext context)
{
- var noSkia = new FormattedText()
- {
- Text = "Current rendering API is not Skia"
- };
+ var noSkia = new FormattedText("Current rendering API is not Skia", CultureInfo.CurrentCulture,
+ FlowDirection.LeftToRight, Typeface.Default, 12, Brushes.Black);
+
context.Custom(new CustomDrawOp(new Rect(0, 0, Bounds.Width, Bounds.Height), noSkia));
Dispatcher.UIThread.InvokeAsync(InvalidateVisual, DispatcherPriority.Background);
}
diff --git a/samples/RenderDemo/Pages/FormattedTextPage.axaml b/samples/RenderDemo/Pages/FormattedTextPage.axaml
new file mode 100644
index 0000000000..92775bec9e
--- /dev/null
+++ b/samples/RenderDemo/Pages/FormattedTextPage.axaml
@@ -0,0 +1,7 @@
+
+
diff --git a/samples/RenderDemo/Pages/FormattedTextPage.axaml.cs b/samples/RenderDemo/Pages/FormattedTextPage.axaml.cs
new file mode 100644
index 0000000000..25e29c67a9
--- /dev/null
+++ b/samples/RenderDemo/Pages/FormattedTextPage.axaml.cs
@@ -0,0 +1,60 @@
+using System.Globalization;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.Media;
+
+namespace RenderDemo.Pages
+{
+ public class FormattedTextPage : UserControl
+ {
+ public FormattedTextPage()
+ {
+ this.InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void Render(DrawingContext context)
+ {
+ const string testString = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor";
+
+ // Create the initial formatted text string.
+ var formattedText = new FormattedText(
+ testString,
+ CultureInfo.GetCultureInfo("en-us"),
+ FlowDirection.LeftToRight,
+ new Typeface("Verdana"),
+ 32,
+ Brushes.Black) { MaxTextWidth = 300, MaxTextHeight = 240 };
+
+ // Set a maximum width and height. If the text overflows these values, an ellipsis "..." appears.
+
+ // Use a larger font size beginning at the first (zero-based) character and continuing for 5 characters.
+ // The font size is calculated in terms of points -- not as device-independent pixels.
+ formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5);
+
+ // Use a Bold font weight beginning at the 6th character and continuing for 11 characters.
+ formattedText.SetFontWeight(FontWeight.Bold, 6, 11);
+
+ var gradient = new LinearGradientBrush
+ {
+ GradientStops =
+ new GradientStops { new GradientStop(Colors.Orange, 0), new GradientStop(Colors.Teal, 1) },
+ StartPoint = new RelativePoint(0,0, RelativeUnit.Relative),
+ EndPoint = new RelativePoint(0,1, RelativeUnit.Relative)
+ };
+
+ // Use a linear gradient brush beginning at the 6th character and continuing for 11 characters.
+ formattedText.SetForegroundBrush(gradient, 6, 11);
+
+ // Use an Italic font style beginning at the 28th character and continuing for 28 characters.
+ formattedText.SetFontStyle(FontStyle.Italic, 28, 28);
+
+ context.DrawText(formattedText, new Point(10, 0));
+ }
+ }
+}
diff --git a/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs b/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
index 857358f6b2..7f85606957 100644
--- a/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
+++ b/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
@@ -13,6 +13,7 @@ namespace RenderDemo.Pages
private GlyphTypeface _glyphTypeface = Typeface.Default.GlyphTypeface;
private readonly Random _rand = new Random();
private ushort[] _glyphIndices = new ushort[1];
+ private char[] _characters = new char[1];
private float _fontSize = 20;
private int _direction = 10;
@@ -38,7 +39,7 @@ namespace RenderDemo.Pages
private void UpdateGlyphRun()
{
- var c = (uint)_rand.Next(65, 90);
+ var c = (char)_rand.Next(65, 90);
if (_fontSize + _direction > 200)
{
@@ -54,6 +55,8 @@ namespace RenderDemo.Pages
_glyphIndices[0] = _glyphTypeface.GetGlyph(c);
+ _characters[0] = c;
+
var scale = (double)_fontSize / _glyphTypeface.DesignEmHeight;
var drawingGroup = new DrawingGroup();
@@ -61,7 +64,7 @@ namespace RenderDemo.Pages
var glyphRunDrawing = new GlyphRunDrawing
{
Foreground = Brushes.Black,
- GlyphRun = new GlyphRun(_glyphTypeface, _fontSize, _glyphIndices),
+ GlyphRun = new GlyphRun(_glyphTypeface, _fontSize, _characters, _glyphIndices)
};
drawingGroup.Children.Add(glyphRunDrawing);
diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs
index 6a940a54f1..2d4f6a305f 100644
--- a/src/Android/Avalonia.Android/AndroidPlatform.cs
+++ b/src/Android/Avalonia.Android/AndroidPlatform.cs
@@ -10,7 +10,7 @@ using Avalonia.Input.Platform;
using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
using Avalonia.Rendering;
-using Avalonia.Shared.PlatformSupport;
+using Avalonia.PlatformSupport;
using Avalonia.Skia;
namespace Avalonia
@@ -59,8 +59,7 @@ namespace Avalonia.Android
.Bind().ToSingleton()
.Bind().ToConstant(new ChoreographerTimer())
.Bind().ToConstant(new RenderLoop())
- .Bind().ToSingleton()
- .Bind().ToConstant(new AssetLoader(appType.Assembly));
+ .Bind().ToSingleton();
SkiaPlatform.Initialize();
diff --git a/src/Android/Avalonia.Android/AppBuilder.cs b/src/Android/Avalonia.Android/AppBuilder.cs
index 805bb61655..04f1ff00d0 100644
--- a/src/Android/Avalonia.Android/AppBuilder.cs
+++ b/src/Android/Avalonia.Android/AppBuilder.cs
@@ -1,5 +1,5 @@
using Avalonia.Controls;
-using Avalonia.Shared.PlatformSupport;
+using Avalonia.PlatformSupport;
namespace Avalonia
{
diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj
index 8c6775733f..5c33dbcea6 100644
--- a/src/Android/Avalonia.Android/Avalonia.Android.csproj
+++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj
@@ -5,9 +5,11 @@
+
+ TargetFramework=netstandard2.0
+
-
diff --git a/src/Android/Avalonia.Android/RuntimeInfo.cs b/src/Android/Avalonia.Android/RuntimeInfo.cs
deleted file mode 100644
index bb2466c357..0000000000
--- a/src/Android/Avalonia.Android/RuntimeInfo.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Avalonia.Platform;
-
-namespace Avalonia.Shared.PlatformSupport
-{
- internal partial class StandardRuntimePlatform
- {
- public RuntimePlatformInfo GetRuntimeInfo() => new RuntimePlatformInfo
- {
- IsCoreClr = false,
- IsDesktop = false,
- IsMobile = true,
- IsDotNetFramework = false,
- IsMono = true,
- IsUnix = true,
- OperatingSystem = OperatingSystemType.Android
- };
- }
-}
\ No newline at end of file
diff --git a/src/Avalonia.Base/Collections/AvaloniaDictionary.cs b/src/Avalonia.Base/Collections/AvaloniaDictionary.cs
index 0e027712e0..2fe68e824d 100644
--- a/src/Avalonia.Base/Collections/AvaloniaDictionary.cs
+++ b/src/Avalonia.Base/Collections/AvaloniaDictionary.cs
@@ -146,6 +146,7 @@ namespace Avalonia.Collections
{
if (_inner.TryGetValue(key, out var value))
{
+ _inner.Remove(key);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs($"Item[{key}]"));
diff --git a/src/Avalonia.Base/Platform/IRuntimePlatform.cs b/src/Avalonia.Base/Platform/IRuntimePlatform.cs
index a0d5d611b3..850757a1ee 100644
--- a/src/Avalonia.Base/Platform/IRuntimePlatform.cs
+++ b/src/Avalonia.Base/Platform/IRuntimePlatform.cs
@@ -1,5 +1,4 @@
using System;
-using System.Reflection;
namespace Avalonia.Platform
{
@@ -23,6 +22,7 @@ namespace Avalonia.Platform
public OperatingSystemType OperatingSystem { get; set; }
public bool IsDesktop { get; set; }
public bool IsMobile { get; set; }
+ public bool IsBrowser { get; set; }
public bool IsCoreClr { get; set; }
public bool IsMono { get; set; }
public bool IsDotNetFramework { get; set; }
@@ -36,6 +36,7 @@ namespace Avalonia.Platform
Linux,
OSX,
Android,
- iOS
+ iOS,
+ Browser
}
}
diff --git a/src/Avalonia.Base/Threading/Dispatcher.cs b/src/Avalonia.Base/Threading/Dispatcher.cs
index 908f431776..49cee441d0 100644
--- a/src/Avalonia.Base/Threading/Dispatcher.cs
+++ b/src/Avalonia.Base/Threading/Dispatcher.cs
@@ -74,6 +74,13 @@ namespace Avalonia.Threading
///
///
public void RunJobs(DispatcherPriority minimumPriority) => _jobRunner.RunJobs(minimumPriority);
+
+ ///
+ /// Use this method to check if there are more prioritized tasks
+ ///
+ ///
+ public bool HasJobsWithPriority(DispatcherPriority minimumPriority) =>
+ _jobRunner.HasJobsWithPriority(minimumPriority);
///
public Task InvokeAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal)
diff --git a/src/Avalonia.Base/Threading/JobRunner.cs b/src/Avalonia.Base/Threading/JobRunner.cs
index f2aef0414c..4b304d44f6 100644
--- a/src/Avalonia.Base/Threading/JobRunner.cs
+++ b/src/Avalonia.Base/Threading/JobRunner.cs
@@ -121,6 +121,21 @@ namespace Avalonia.Threading
return null;
}
+ public bool HasJobsWithPriority(DispatcherPriority minimumPriority)
+ {
+ for (int c = (int)minimumPriority; c < (int)DispatcherPriority.MaxValue; c++)
+ {
+ var q = _queues[c];
+ lock (q)
+ {
+ if (q.Count > 0)
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private interface IJob
{
///
diff --git a/src/Avalonia.Base/Utilities/ImmutableReadOnlyListStructEnumerator.cs b/src/Avalonia.Base/Utilities/ImmutableReadOnlyListStructEnumerator.cs
index 90d1c52ff5..251dfe4351 100644
--- a/src/Avalonia.Base/Utilities/ImmutableReadOnlyListStructEnumerator.cs
+++ b/src/Avalonia.Base/Utilities/ImmutableReadOnlyListStructEnumerator.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace Avalonia.Utilities
{
- public struct ImmutableReadOnlyListStructEnumerator : IEnumerator, IEnumerator
+ public struct ImmutableReadOnlyListStructEnumerator : IEnumerator
{
private readonly IReadOnlyList _readOnlyList;
private int _pos;
diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs
index 95ee73be4e..5d71a499e3 100644
--- a/src/Avalonia.Controls.DataGrid/DataGrid.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs
@@ -2215,7 +2215,14 @@ namespace Avalonia.Controls
/// PointerWheelEventArgs
protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
{
- e.Handled = e.Handled || UpdateScroll(e.Delta * DATAGRID_mouseWheelDelta);
+ if(UpdateScroll(e.Delta * DATAGRID_mouseWheelDelta))
+ {
+ e.Handled = true;
+ }
+ else
+ {
+ e.Handled = e.Handled || !ScrollViewer.GetIsScrollChainingEnabled(this);
+ }
}
internal bool UpdateScroll(Vector delta)
diff --git a/src/Avalonia.Controls/ApiCompatBaseline.txt b/src/Avalonia.Controls/ApiCompatBaseline.txt
index a7560c37f2..2c206b53f6 100644
--- a/src/Avalonia.Controls/ApiCompatBaseline.txt
+++ b/src/Avalonia.Controls/ApiCompatBaseline.txt
@@ -43,6 +43,10 @@ MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.Off
MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Notifications.NotificationCard.CloseOnClickProperty' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.Platform.ITopLevelNativeMenuExporter.SetNativeMenu(Avalonia.Controls.NativeMenu)' is present in the contract but not in the implementation.
+MembersMustExist : Member 'protected Avalonia.Media.FormattedText Avalonia.Controls.Presenters.TextPresenter.CreateFormattedText()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'public Avalonia.Media.FormattedText Avalonia.Controls.Presenters.TextPresenter.FormattedText.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'public System.Int32 Avalonia.Controls.Presenters.TextPresenter.GetCaretIndex(Avalonia.Point)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.Presenters.TextPresenter.InvalidateFormattedText()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Primitives.PopupRoot' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract.
EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints Avalonia.Platform.ExtendClientAreaChromeHints.Default' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Nullable Avalonia.Platform.ITopLevelImpl.FrameSize' is present in the implementation but not in the contract.
@@ -63,4 +67,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platfor
MembersMustExist : Member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size, Avalonia.Platform.PlatformResizeReason)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.ITrayIconImpl Avalonia.Platform.IWindowingPlatform.CreateTrayIcon()' is present in the implementation but not in the contract.
-Total Issues: 64
+Total Issues: 68
diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs
index d44b2ab0db..8779ae9122 100644
--- a/src/Avalonia.Controls/AppBuilderBase.cs
+++ b/src/Avalonia.Controls/AppBuilderBase.cs
@@ -14,9 +14,9 @@ namespace Avalonia.Controls
public abstract class AppBuilderBase where TAppBuilder : AppBuilderBase, new()
{
private static bool s_setupWasAlreadyCalled;
- private Action _optionsInitializers;
- private Func _appFactory;
- private IApplicationLifetime _lifetime;
+ private Action? _optionsInitializers;
+ private Func? _appFactory;
+ private IApplicationLifetime? _lifetime;
///
/// Gets or sets the instance.
@@ -31,32 +31,32 @@ namespace Avalonia.Controls
///
/// Gets the instance being initialized.
///
- public Application Instance { get; private set; }
+ public Application? Instance { get; private set; }
///
/// Gets the type of the Instance (even if it's not created yet)
///
- public Type ApplicationType { get; private set; }
+ public Type? ApplicationType { get; private set; }
///
/// Gets or sets a method to call the initialize the windowing subsystem.
///
- public Action WindowingSubsystemInitializer { get; private set; }
+ public Action? WindowingSubsystemInitializer { get; private set; }
///
/// Gets the name of the currently selected windowing subsystem.
///
- public string WindowingSubsystemName { get; private set; }
+ public string? WindowingSubsystemName { get; private set; }
///
/// Gets or sets a method to call the initialize the windowing subsystem.
///
- public Action RenderingSubsystemInitializer { get; private set; }
+ public Action? RenderingSubsystemInitializer { get; private set; }
///
/// Gets the name of the currently selected rendering subsystem.
///
- public string RenderingSubsystemName { get; private set; }
+ public string? RenderingSubsystemName { get; private set; }
///
/// Gets or sets a method to call after the is setup.
@@ -126,7 +126,7 @@ namespace Avalonia.Controls
/// The window type.
/// A delegate that will be called to create a data context for the window (optional).
[Obsolete("Use either lifetimes or AppMain overload. See see https://github.com/AvaloniaUI/Avalonia/wiki/Application-lifetimes for details")]
- public void Start(Func
/// The object that raised the event.
/// The event data.
- private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void ItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
// Update the cache
if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems != null)
{
for (int index = 0; index < e.OldItems.Count; index++)
{
- _items.RemoveAt(e.OldStartingIndex);
+ _items!.RemoveAt(e.OldStartingIndex);
}
}
- if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null && _items.Count >= e.NewStartingIndex)
+ if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null && _items!.Count >= e.NewStartingIndex)
{
for (int index = 0; index < e.NewItems.Count; index++)
{
- _items.Insert(e.NewStartingIndex + index, e.NewItems[index]);
+ _items.Insert(e.NewStartingIndex + index, e.NewItems[index]!);
}
}
if (e.Action == NotifyCollectionChangedAction.Replace && e.NewItems != null && e.OldItems != null)
{
for (int index = 0; index < e.NewItems.Count; index++)
{
- _items[e.NewStartingIndex] = e.NewItems[index];
+ _items![e.NewStartingIndex] = e.NewItems[index]!;
}
}
@@ -2228,7 +2229,7 @@ namespace Avalonia.Controls
{
for (int index = 0; index < e.OldItems.Count; index++)
{
- _view.Remove(e.OldItems[index]);
+ _view!.Remove(e.OldItems[index]!);
}
}
@@ -2270,7 +2271,7 @@ namespace Avalonia.Controls
RefreshView();
// Fire the Populated event containing the read-only view data.
- PopulatedEventArgs populated = new PopulatedEventArgs(new ReadOnlyCollection(_view));
+ PopulatedEventArgs populated = new PopulatedEventArgs(new ReadOnlyCollection(_view!));
OnPopulated(populated);
if (SelectionAdapter != null && SelectionAdapter.Items != _view)
@@ -2278,7 +2279,7 @@ namespace Avalonia.Controls
SelectionAdapter.Items = _view;
}
- bool isDropDownOpen = _userCalledPopulate && (_view.Count > 0);
+ bool isDropDownOpen = _userCalledPopulate && (_view!.Count > 0);
if (isDropDownOpen != IsDropDownOpen)
{
_ignorePropertyChange = true;
@@ -2306,20 +2307,20 @@ namespace Avalonia.Controls
private void UpdateTextCompletion(bool userInitiated)
{
// By default this method will clear the selected value
- object newSelectedItem = null;
- string text = Text;
+ object? newSelectedItem = null;
+ string? text = Text;
// Text search is StartsWith explicit and only when enabled, in
// line with WPF's ComboBox lookup. When in use it will associate
// a Value with the Text if it is found in ItemsSource. This is
// only valid when there is data and the user initiated the action.
- if (_view.Count > 0)
+ if (_view!.Count > 0)
{
if (IsTextCompletionEnabled && TextBox != null && userInitiated)
{
int currentLength = TextBox.Text?.Length ?? 0;
int selectionStart = TextBoxSelectionStart;
- if (selectionStart == text.Length && selectionStart > _textSelectionStart)
+ if (selectionStart == text?.Length && selectionStart > _textSelectionStart)
{
// When the FilterMode dependency property is set to
// either StartsWith or StartsWithCaseSensitive, the
@@ -2327,7 +2328,7 @@ namespace Avalonia.Controls
// performance on the lookup. It assumes that the
// FilterMode the user has selected is an acceptable
// case sensitive matching function for their scenario.
- object top = FilterMode == AutoCompleteFilterMode.StartsWith || FilterMode == AutoCompleteFilterMode.StartsWithCaseSensitive
+ object? top = FilterMode == AutoCompleteFilterMode.StartsWith || FilterMode == AutoCompleteFilterMode.StartsWithCaseSensitive
? _view[0]
: TryGetMatch(text, _view, AutoCompleteSearch.GetFilter(AutoCompleteFilterMode.StartsWith));
@@ -2335,18 +2336,18 @@ namespace Avalonia.Controls
if (top != null)
{
newSelectedItem = top;
- string topString = FormatValue(top, true);
+ string? topString = FormatValue(top, true);
// Only replace partially when the two words being the same
- int minLength = Math.Min(topString.Length, Text.Length);
- if (AutoCompleteSearch.Equals(Text.Substring(0, minLength), topString.Substring(0, minLength)))
+ int minLength = Math.Min(topString?.Length ?? 0, Text?.Length ?? 0);
+ if (AutoCompleteSearch.Equals(Text?.Substring(0, minLength), topString?.Substring(0, minLength)))
{
// Update the text
UpdateTextValue(topString);
// Select the text past the user's caret
TextBox.SelectionStart = currentLength;
- TextBox.SelectionEnd = topString.Length;
+ TextBox.SelectionEnd = topString?.Length ?? 0;
}
}
}
@@ -2392,8 +2393,11 @@ namespace Avalonia.Controls
/// The predicate to use for the partial or
/// exact match.
/// Returns the object or null.
- private object TryGetMatch(string searchText, AvaloniaList view, AutoCompleteFilterPredicate predicate)
+ private object? TryGetMatch(string? searchText, AvaloniaList view, AutoCompleteFilterPredicate? predicate)
{
+ if (predicate is null)
+ return null;
+
if (view != null && view.Count > 0)
{
foreach (object o in view)
@@ -2428,9 +2432,9 @@ namespace Avalonia.Controls
/// that is displayed in the text box part.
///
/// The new item.
- private void OnSelectedItemChanged(object newItem)
+ private void OnSelectedItemChanged(object? newItem)
{
- string text;
+ string? text;
if (newItem == null)
{
@@ -2461,9 +2465,9 @@ namespace Avalonia.Controls
///
/// The source object.
/// The selection changed event data.
- private void OnAdapterSelectionChanged(object sender, SelectionChangedEventArgs e)
+ private void OnAdapterSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
- SelectedItem = _adapter.SelectedItem;
+ SelectedItem = _adapter!.SelectedItem;
}
//TODO Check UpdateTextCompletion
@@ -2472,7 +2476,7 @@ namespace Avalonia.Controls
///
/// The source object.
/// The event data.
- private void OnAdapterSelectionComplete(object sender, RoutedEventArgs e)
+ private void OnAdapterSelectionComplete(object? sender, RoutedEventArgs e)
{
IsDropDownOpen = false;
@@ -2482,7 +2486,7 @@ namespace Avalonia.Controls
// Text should not be selected
ClearTextBoxSelection();
- TextBox.Focus();
+ TextBox!.Focus();
}
///
@@ -2490,7 +2494,7 @@ namespace Avalonia.Controls
///
/// The source object.
/// The event data.
- private void OnAdapterSelectionCanceled(object sender, RoutedEventArgs e)
+ private void OnAdapterSelectionCanceled(object? sender, RoutedEventArgs e)
{
UpdateTextValue(SearchText);
@@ -2510,7 +2514,7 @@ namespace Avalonia.Controls
///
/// The built-in search mode.
/// Returns the string-based comparison function.
- public static AutoCompleteFilterPredicate GetFilter(AutoCompleteFilterMode FilterMode)
+ public static AutoCompleteFilterPredicate? GetFilter(AutoCompleteFilterMode FilterMode)
{
switch (FilterMode)
{
@@ -2566,9 +2570,11 @@ namespace Avalonia.Controls
/// The string value to search for.
/// The string comparison type.
/// Returns true when the substring is found.
- private static bool Contains(string s, string value, StringComparison comparison)
+ private static bool Contains(string? s, string? value, StringComparison comparison)
{
- return s.IndexOf(value, comparison) >= 0;
+ if (s is not null && value is not null)
+ return s.IndexOf(value, comparison) >= 0;
+ return false;
}
///
@@ -2577,9 +2583,11 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool StartsWith(string text, string value)
+ public static bool StartsWith(string? text, string? value)
{
- return value.StartsWith(text, StringComparison.CurrentCultureIgnoreCase);
+ if (value is not null && text is not null)
+ return value.StartsWith(text, StringComparison.CurrentCultureIgnoreCase);
+ return false;
}
///
@@ -2588,9 +2596,11 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool StartsWithCaseSensitive(string text, string value)
+ public static bool StartsWithCaseSensitive(string? text, string? value)
{
- return value.StartsWith(text, StringComparison.CurrentCulture);
+ if (value is not null && text is not null)
+ return value.StartsWith(text, StringComparison.CurrentCulture);
+ return false;
}
///
@@ -2599,9 +2609,11 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool StartsWithOrdinal(string text, string value)
+ public static bool StartsWithOrdinal(string? text, string? value)
{
- return value.StartsWith(text, StringComparison.OrdinalIgnoreCase);
+ if (value is not null && text is not null)
+ return value.StartsWith(text, StringComparison.OrdinalIgnoreCase);
+ return false;
}
///
@@ -2610,9 +2622,11 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool StartsWithOrdinalCaseSensitive(string text, string value)
+ public static bool StartsWithOrdinalCaseSensitive(string? text, string? value)
{
- return value.StartsWith(text, StringComparison.Ordinal);
+ if (value is not null && text is not null)
+ return value.StartsWith(text, StringComparison.Ordinal);
+ return false;
}
///
@@ -2622,7 +2636,7 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool Contains(string text, string value)
+ public static bool Contains(string? text, string? value)
{
return Contains(value, text, StringComparison.CurrentCultureIgnoreCase);
}
@@ -2633,7 +2647,7 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool ContainsCaseSensitive(string text, string value)
+ public static bool ContainsCaseSensitive(string? text, string? value)
{
return Contains(value, text, StringComparison.CurrentCulture);
}
@@ -2644,7 +2658,7 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool ContainsOrdinal(string text, string value)
+ public static bool ContainsOrdinal(string? text, string? value)
{
return Contains(value, text, StringComparison.OrdinalIgnoreCase);
}
@@ -2655,7 +2669,7 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool ContainsOrdinalCaseSensitive(string text, string value)
+ public static bool ContainsOrdinalCaseSensitive(string? text, string? value)
{
return Contains(value, text, StringComparison.Ordinal);
}
@@ -2666,9 +2680,9 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool Equals(string text, string value)
+ public static bool Equals(string? text, string? value)
{
- return value.Equals(text, StringComparison.CurrentCultureIgnoreCase);
+ return string.Equals(value, text, StringComparison.CurrentCultureIgnoreCase);
}
///
@@ -2677,9 +2691,9 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool EqualsCaseSensitive(string text, string value)
+ public static bool EqualsCaseSensitive(string? text, string? value)
{
- return value.Equals(text, StringComparison.CurrentCulture);
+ return string.Equals(value, text, StringComparison.CurrentCulture);
}
///
@@ -2688,9 +2702,9 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool EqualsOrdinal(string text, string value)
+ public static bool EqualsOrdinal(string? text, string? value)
{
- return value.Equals(text, StringComparison.OrdinalIgnoreCase);
+ return string.Equals(value, text, StringComparison.OrdinalIgnoreCase);
}
///
@@ -2699,9 +2713,9 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool EqualsOrdinalCaseSensitive(string text, string value)
+ public static bool EqualsOrdinalCaseSensitive(string? text, string? value)
{
- return value.Equals(text, StringComparison.Ordinal);
+ return string.Equals(value, text, StringComparison.Ordinal);
}
}
@@ -2715,7 +2729,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the string value binding used by the control.
///
- private IBinding _binding;
+ private IBinding? _binding;
#region public T Value
@@ -2739,13 +2753,14 @@ namespace Avalonia.Controls
///
/// Gets or sets the value binding.
///
- public IBinding ValueBinding
+ public IBinding? ValueBinding
{
get { return _binding; }
set
{
_binding = value;
- AvaloniaObjectExtensions.Bind(this, ValueProperty, value);
+ if (value is not null)
+ AvaloniaObjectExtensions.Bind(this, ValueProperty, value);
}
}
@@ -2760,7 +2775,7 @@ namespace Avalonia.Controls
/// setting the initial binding to the provided parameter.
///
/// The initial string value binding.
- public BindingEvaluator(IBinding binding)
+ public BindingEvaluator(IBinding? binding)
: this()
{
ValueBinding = binding;
@@ -2802,7 +2817,7 @@ namespace Avalonia.Controls
/// The object to use as the data context.
/// Returns the evaluated T value of the bound dependency
/// property.
- public T GetDynamicValue(object o)
+ public T GetDynamicValue(object? o)
{
DataContext = o;
return Value;
diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj
index e2c6a714aa..543a513d57 100644
--- a/src/Avalonia.Controls/Avalonia.Controls.csproj
+++ b/src/Avalonia.Controls/Avalonia.Controls.csproj
@@ -18,4 +18,5 @@
+
diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs
index ee67f303f3..ee3be1d5b3 100644
--- a/src/Avalonia.Controls/Border.cs
+++ b/src/Avalonia.Controls/Border.cs
@@ -17,14 +17,14 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty BackgroundProperty =
- AvaloniaProperty.Register(nameof(Background));
+ public static readonly StyledProperty BackgroundProperty =
+ AvaloniaProperty.Register(nameof(Background));
///
/// Defines the property.
///
- public static readonly StyledProperty BorderBrushProperty =
- AvaloniaProperty.Register(nameof(BorderBrush));
+ public static readonly StyledProperty BorderBrushProperty =
+ AvaloniaProperty.Register(nameof(BorderBrush));
///
/// Defines the property.
@@ -91,7 +91,7 @@ namespace Avalonia.Controls
///
/// Gets or sets a brush with which to paint the background.
///
- public IBrush Background
+ public IBrush? Background
{
get { return GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
@@ -100,7 +100,7 @@ namespace Avalonia.Controls
///
/// Gets or sets a brush with which to paint the border.
///
- public IBrush BorderBrush
+ public IBrush? BorderBrush
{
get { return GetValue(BorderBrushProperty); }
set { SetValue(BorderBrushProperty, value); }
diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs
index 8537c9acbc..a2efc7fba0 100644
--- a/src/Avalonia.Controls/Button.cs
+++ b/src/Avalonia.Controls/Button.cs
@@ -42,30 +42,30 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly DirectProperty
/// The event sender.
/// The event args.
- private void RootDefaultKeyDown(object sender, KeyEventArgs e)
+ private void RootDefaultKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Enter && IsVisible && IsEnabled)
{
@@ -558,7 +542,7 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- private void RootCancelKeyDown(object sender, KeyEventArgs e)
+ private void RootCancelKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Escape && IsVisible && IsEnabled)
{
@@ -566,6 +550,9 @@ namespace Avalonia.Controls
}
}
+ ///
+ /// Updates the visual state of the control by applying latest PseudoClasses.
+ ///
private void UpdatePseudoClasses(bool isPressed)
{
PseudoClasses.Set(":pressed", isPressed);
diff --git a/src/Avalonia.Controls/ButtonSpinner.cs b/src/Avalonia.Controls/ButtonSpinner.cs
index f1c1a55a17..31aba024ae 100644
--- a/src/Avalonia.Controls/ButtonSpinner.cs
+++ b/src/Avalonia.Controls/ButtonSpinner.cs
@@ -42,11 +42,11 @@ namespace Avalonia.Controls
UpdatePseudoClasses(ButtonSpinnerLocation);
}
- private Button _decreaseButton;
+ private Button? _decreaseButton;
///
/// Gets or sets the DecreaseButton template part.
///
- private Button DecreaseButton
+ private Button? DecreaseButton
{
get { return _decreaseButton; }
set
@@ -63,11 +63,11 @@ namespace Avalonia.Controls
}
}
- private Button _increaseButton;
+ private Button? _increaseButton;
///
/// Gets or sets the IncreaseButton template part.
///
- private Button IncreaseButton
+ private Button? IncreaseButton
{
get
{
@@ -241,8 +241,8 @@ namespace Avalonia.Controls
{
if (e.Sender is ButtonSpinner spinner)
{
- var oldValue = (bool)e.OldValue;
- var newValue = (bool)e.NewValue;
+ var oldValue = (bool)e.OldValue!;
+ var newValue = (bool)e.NewValue!;
spinner.OnAllowSpinChanged(oldValue, newValue);
}
}
@@ -268,7 +268,7 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- private void OnButtonClick(object sender, RoutedEventArgs e)
+ private void OnButtonClick(object? sender, RoutedEventArgs e)
{
if (AllowSpin)
{
diff --git a/src/Avalonia.Controls/Calendar/Calendar.cs b/src/Avalonia.Controls/Calendar/Calendar.cs
index 2c8a7c0831..6c83308b39 100644
--- a/src/Avalonia.Controls/Calendar/Calendar.cs
+++ b/src/Avalonia.Controls/Calendar/Calendar.cs
@@ -240,11 +240,11 @@ namespace Avalonia.Controls
private bool _isShiftPressed;
private bool _displayDateIsChanging = false;
- internal CalendarDayButton FocusButton { get; set; }
- internal CalendarButton FocusCalendarButton { get; set; }
+ internal CalendarDayButton? FocusButton { get; set; }
+ internal CalendarButton? FocusCalendarButton { get; set; }
- internal Panel Root { get; set; }
- internal CalendarItem MonthControl
+ internal Panel? Root { get; set; }
+ internal CalendarItem? MonthControl
{
get
{
@@ -280,7 +280,7 @@ namespace Avalonia.Controls
private void OnFirstDayOfWeekChanged(AvaloniaPropertyChangedEventArgs e)
{
- if (IsValidFirstDayOfWeek(e.NewValue))
+ if (IsValidFirstDayOfWeek(e.NewValue!))
{
UpdateMonths();
}
@@ -373,9 +373,9 @@ namespace Avalonia.Controls
/// The DependencyPropertyChangedEventArgs.
private void OnDisplayModePropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
- CalendarMode mode = (CalendarMode)e.NewValue;
- CalendarMode oldMode = (CalendarMode)e.OldValue;
- CalendarItem monthControl = MonthControl;
+ CalendarMode mode = (CalendarMode)e.NewValue!;
+ CalendarMode oldMode = (CalendarMode)e.OldValue!;
+ CalendarItem? monthControl = MonthControl;
if (monthControl != null)
{
@@ -459,7 +459,7 @@ namespace Avalonia.Controls
}
private void OnSelectionModeChanged(AvaloniaPropertyChangedEventArgs e)
{
- if (IsValidSelectionMode(e.NewValue))
+ if (IsValidSelectionMode(e.NewValue!))
{
_displayDateIsChanging = true;
SelectedDate = null;
@@ -656,7 +656,7 @@ namespace Avalonia.Controls
{
FocusButton.IsCurrent = false;
}
- FocusButton = FindDayButtonFromDay(LastSelectedDate.Value);
+ FocusButton = FindDayButtonFromDay(LastSelectedDate!.Value);
if (FocusButton != null)
{
FocusButton.IsCurrent = HasFocusInternal;
@@ -754,11 +754,11 @@ namespace Avalonia.Controls
private void OnDisplayDateChanged(AvaloniaPropertyChangedEventArgs e)
{
- UpdateDisplayDate(this, (DateTime)e.NewValue, (DateTime)e.OldValue);
+ UpdateDisplayDate(this, (DateTime)e.NewValue!, (DateTime)e.OldValue!);
}
private static void UpdateDisplayDate(Calendar c, DateTime addedDate, DateTime removedDate)
{
- Contract.Requires(c != null);
+ _ = c ?? throw new ArgumentNullException(nameof(c));
// If DisplayDate < DisplayDateStart, DisplayDate = DisplayDateStart
if (DateTime.Compare(addedDate, c.DisplayDateRangeStart) < 0)
@@ -871,7 +871,7 @@ namespace Avalonia.Controls
if (cal.SelectedDates.Count > 0)
{
selectedDateMin = cal.SelectedDates[0];
- Debug.Assert(DateTime.Compare(cal.SelectedDate.Value, selectedDateMin) == 0, "The SelectedDate should be the minimum selected date!");
+ Debug.Assert(DateTime.Compare(cal.SelectedDate!.Value, selectedDateMin) == 0, "The SelectedDate should be the minimum selected date!");
}
else
{
@@ -959,7 +959,7 @@ namespace Avalonia.Controls
if (cal.SelectedDates.Count > 0)
{
selectedDateMax = cal.SelectedDates[0];
- Debug.Assert(DateTime.Compare(cal.SelectedDate.Value, selectedDateMax) == 0, "The SelectedDate should be the maximum SelectedDate!");
+ Debug.Assert(DateTime.Compare(cal.SelectedDate!.Value, selectedDateMax) == 0, "The SelectedDate should be the maximum SelectedDate!");
}
else
{
@@ -1003,9 +1003,9 @@ namespace Avalonia.Controls
///
internal bool CalendarDatePickerDisplayDateFlag { get; set; }
- internal CalendarDayButton FindDayButtonFromDay(DateTime day)
+ internal CalendarDayButton? FindDayButtonFromDay(DateTime day)
{
- CalendarItem monthControl = MonthControl;
+ CalendarItem? monthControl = MonthControl;
// REMOVE_RTM: should be updated if we support MultiCalendar
int count = RowsPerMonth * ColumnsPerMonth;
@@ -1054,7 +1054,7 @@ namespace Avalonia.Controls
internal void OnHeaderClick()
{
Debug.Assert(DisplayMode == CalendarMode.Year || DisplayMode == CalendarMode.Decade, "The DisplayMode should be Year or Decade");
- CalendarItem monthControl = MonthControl;
+ CalendarItem? monthControl = MonthControl;
if (monthControl != null && monthControl.MonthView != null && monthControl.YearView != null)
{
monthControl.MonthView.IsVisible = false;
@@ -1065,7 +1065,7 @@ namespace Avalonia.Controls
internal void ResetStates()
{
- CalendarItem monthControl = MonthControl;
+ CalendarItem? monthControl = MonthControl;
int count = RowsPerMonth * ColumnsPerMonth;
if (monthControl != null)
{
@@ -1083,7 +1083,7 @@ namespace Avalonia.Controls
internal void UpdateMonths()
{
- CalendarItem monthControl = MonthControl;
+ CalendarItem? monthControl = MonthControl;
if (monthControl != null)
{
switch (DisplayMode)
@@ -1163,6 +1163,8 @@ namespace Avalonia.Controls
{
if (HoverEnd != null && HoverStart != null)
{
+ Debug.Assert(MonthControl is not null);
+
int startIndex, endIndex, i;
CalendarItem monthControl = MonthControl;
@@ -1173,7 +1175,7 @@ namespace Avalonia.Controls
for (i = startIndex; i <= endIndex; i++)
{
- if (monthControl.MonthView.Children[i] is CalendarDayButton b)
+ if (monthControl.MonthView!.Children[i] is CalendarDayButton b)
{
b.IsSelected = true;
var d = b.DataContext as DateTime?;
@@ -1201,6 +1203,8 @@ namespace Avalonia.Controls
{
if (HoverEnd != null && HoverStart != null)
{
+ Debug.Assert(MonthControl is not null);
+
CalendarItem monthControl = MonthControl;
if (HoverEndIndex != null && HoverStartIndex != null)
@@ -1212,7 +1216,7 @@ namespace Avalonia.Controls
{
for (i = startIndex; i <= endIndex; i++)
{
- if (monthControl.MonthView.Children[i] is CalendarDayButton b)
+ if (monthControl.MonthView!.Children[i] is CalendarDayButton b)
{
var d = b.DataContext as DateTime?;
@@ -1231,7 +1235,7 @@ namespace Avalonia.Controls
// It is SingleRange
for (i = startIndex; i <= endIndex; i++)
{
- ((CalendarDayButton)monthControl.MonthView.Children[i]).IsSelected = false;
+ ((CalendarDayButton)monthControl.MonthView!.Children[i]).IsSelected = false;
}
}
}
@@ -1239,6 +1243,11 @@ namespace Avalonia.Controls
}
internal void SortHoverIndexes(out int startIndex, out int endIndex)
{
+ Debug.Assert(HoverStart.HasValue);
+ Debug.Assert(HoverEnd.HasValue);
+ Debug.Assert(HoverStartIndex.HasValue);
+ Debug.Assert(HoverEndIndex.HasValue);
+
if (DateTimeHelper.CompareDays(HoverEnd.Value, HoverStart.Value) > 0)
{
startIndex = HoverStartIndex.Value;
@@ -1373,6 +1382,8 @@ namespace Avalonia.Controls
}
private void OnMonthClick()
{
+ Debug.Assert(MonthControl is not null);
+
CalendarItem monthControl = MonthControl;
if (monthControl != null && monthControl.YearView != null && monthControl.MonthView != null)
{
@@ -1400,7 +1411,7 @@ namespace Avalonia.Controls
}
}
- public event EventHandler SelectedDatesChanged;
+ public event EventHandler? SelectedDatesChanged;
///
/// Occurs when the
@@ -1410,19 +1421,19 @@ namespace Avalonia.Controls
///
/// This event occurs after DisplayDate is assigned its new value.
///
- public event EventHandler DisplayDateChanged;
+ public event EventHandler? DisplayDateChanged;
///
/// Occurs when the
///
/// property is changed.
///
- public event EventHandler DisplayModeChanged;
+ public event EventHandler? DisplayModeChanged;
///
/// Inherited code: Requires comment.
///
- internal event EventHandler DayButtonMouseUp;
+ internal event EventHandler? DayButtonMouseUp;
///
/// This method adds the days that were selected by Keyboard to the
@@ -1461,7 +1472,7 @@ namespace Avalonia.Controls
SelectedDates.ClearInternal();
if (shift)
{
- CalendarDayButton b;
+ CalendarDayButton? b;
_isShiftPressed = true;
if (HoverStart == null)
{
@@ -1513,6 +1524,8 @@ namespace Avalonia.Controls
}
else
{
+ Debug.Assert(HoverEndInternal is not null);
+
// For Home, End, PageUp and PageDown Keys there
// is no easy way to predict the index value
b = FindDayButtonFromDay(HoverEndInternal.Value);
@@ -1524,6 +1537,7 @@ namespace Avalonia.Controls
}
}
+ Debug.Assert(HoverEnd is not null);
OnDayClick(HoverEnd.Value);
HighlightDays();
}
@@ -1557,7 +1571,7 @@ namespace Avalonia.Controls
base.OnPointerReleased(e);
if (!HasFocusInternal && e.InitialPressMouseButton == MouseButton.Left)
{
- FocusManager.Instance.Focus(this);
+ FocusManager.Instance?.Focus(this);
}
}
@@ -1876,8 +1890,8 @@ namespace Avalonia.Controls
// since DisplayDate is not equal to
// DateTime.MaxValue we are sure selectedDate is\
// not null
- selectedDate = DateTimeHelper.AddMonths(selectedDate.Value, 1).Value;
- selectedDate = DateTimeHelper.AddDays(selectedDate.Value, -1).Value;
+ selectedDate = DateTimeHelper.AddMonths(selectedDate.Value, 1)!.Value;
+ selectedDate = DateTimeHelper.AddDays(selectedDate.Value, -1)!.Value;
}
else
{
@@ -2098,7 +2112,7 @@ namespace Avalonia.Controls
if (Root != null)
{
- CalendarItem month = e.NameScope.Find(PART_ElementMonth);
+ CalendarItem? month = e.NameScope.Find(PART_ElementMonth);
if (month != null)
{
diff --git a/src/Avalonia.Controls/Calendar/CalendarButton.cs b/src/Avalonia.Controls/Calendar/CalendarButton.cs
index 76af933b55..0a8e4dfae8 100644
--- a/src/Avalonia.Controls/Calendar/CalendarButton.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarButton.cs
@@ -45,7 +45,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets or sets the Calendar associated with this button.
///
- internal Calendar Owner { get; set; }
+ internal Calendar? Owner { get; set; }
///
/// Gets or sets a value indicating whether the button is focused.
@@ -120,7 +120,7 @@ namespace Avalonia.Controls.Primitives
/// stylus touches the tablet PC) while the mouse pointer is over a
/// UIElement.
///
- public event EventHandler CalendarLeftMouseButtonDown;
+ public event EventHandler? CalendarLeftMouseButtonDown;
///
/// Occurs when the left mouse button is released (or the tip of the
@@ -128,7 +128,7 @@ namespace Avalonia.Controls.Primitives
/// stylus) is over a UIElement (or while a UIElement holds mouse
/// capture).
///
- public event EventHandler CalendarLeftMouseButtonUp;
+ public event EventHandler? CalendarLeftMouseButtonUp;
///
/// Provides class handling for the MouseLeftButtonDown event that
diff --git a/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs b/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
index cd9c80d3e0..c1f487c32d 100644
--- a/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
@@ -123,15 +123,15 @@ namespace Avalonia.Controls
private const string ElementPopup = "PART_Popup";
private const string ElementCalendar = "PART_Calendar";
- private Calendar _calendar;
+ private Calendar? _calendar;
private string _defaultText;
- private Button _dropDownButton;
+ private Button? _dropDownButton;
//private Canvas _outsideCanvas;
//private Canvas _outsidePopupCanvas;
- private Popup _popUp;
- private TextBox _textBox;
- private IDisposable _textBoxTextChangedSubscription;
- private IDisposable _buttonPointerPressedSubscription;
+ private Popup? _popUp;
+ private TextBox? _textBox;
+ private IDisposable? _textBoxTextChangedSubscription;
+ private IDisposable? _buttonPointerPressedSubscription;
private DateTime? _onOpenSelectedDate;
private bool _settingSelectedDate;
@@ -141,7 +141,7 @@ namespace Avalonia.Controls
private DateTime? _displayDateEnd;
private bool _isDropDownOpen;
private DateTime? _selectedDate;
- private string _text;
+ private string? _text;
private bool _suspendTextChangeHandler = false;
private bool _isPopupClosing = false;
private bool _ignoreButtonClick = false;
@@ -153,7 +153,7 @@ namespace Avalonia.Controls
/// A collection of dates that cannot be selected. The default value is
/// an empty collection.
///
- public CalendarBlackoutDatesCollection BlackoutDates { get; private set; }
+ public CalendarBlackoutDatesCollection? BlackoutDates { get; private set; }
public static readonly DirectProperty DisplayDateProperty =
AvaloniaProperty.RegisterDirect(
@@ -200,12 +200,12 @@ namespace Avalonia.Controls
defaultValue: "d",
validate: IsValidDateFormatString);
- public static readonly DirectProperty TextProperty =
- AvaloniaProperty.RegisterDirect(
+ public static readonly DirectProperty TextProperty =
+ AvaloniaProperty.RegisterDirect(
nameof(Text),
o => o.Text,
(o, v) => o.Text = v);
- public static readonly StyledProperty WatermarkProperty =
+ public static readonly StyledProperty WatermarkProperty =
TextBox.WatermarkProperty.AddOwner();
public static readonly StyledProperty UseFloatingWatermarkProperty =
TextBox.UseFloatingWatermarkProperty.AddOwner();
@@ -361,13 +361,13 @@ namespace Avalonia.Controls
///
/// The text entered parses to a date that is not selectable.
///
- public string Text
+ public string? Text
{
get { return _text; }
set { SetAndRaise(TextProperty, ref _text, value); }
}
- public string Watermark
+ public string? Watermark
{
get { return GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
@@ -401,26 +401,26 @@ namespace Avalonia.Controls
/// Occurs when the drop-down
/// is closed.
///
- public event EventHandler CalendarClosed;
+ public event EventHandler? CalendarClosed;
///
/// Occurs when the drop-down
/// is opened.
///
- public event EventHandler CalendarOpened;
+ public event EventHandler? CalendarOpened;
///
/// Occurs when
/// is assigned a value that cannot be interpreted as a date.
///
- public event EventHandler DateValidationError;
+ public event EventHandler? DateValidationError;
///
/// Occurs when the
///
/// property is changed.
///
- public event EventHandler SelectedDateChanged;
+ public event EventHandler? SelectedDateChanged;
static CalendarDatePicker()
{
@@ -579,14 +579,14 @@ namespace Avalonia.Controls
private void OnIsDropDownOpenChanged(AvaloniaPropertyChangedEventArgs e)
{
- var oldValue = (bool)e.OldValue;
- var value = (bool)e.NewValue;
+ var oldValue = (bool)e.OldValue!;
+ var value = (bool)e.NewValue!;
if (_popUp != null && _popUp.Child != null)
{
if (value != oldValue)
{
- if (_calendar.DisplayMode != CalendarMode.Month)
+ if (_calendar!.DisplayMode != CalendarMode.Month)
{
_calendar.DisplayMode = CalendarMode.Month;
}
@@ -660,7 +660,7 @@ namespace Avalonia.Controls
if (date != null)
{
- string s = DateTimeToString((DateTime)date);
+ string? s = DateTimeToString((DateTime)date);
Text = s;
}
}
@@ -679,8 +679,8 @@ namespace Avalonia.Controls
}
private void OnTextChanged(AvaloniaPropertyChangedEventArgs e)
{
- var oldValue = (string)e.OldValue;
- var value = (string)e.NewValue;
+ var oldValue = (string?)e.OldValue;
+ var value = (string?)e.NewValue;
if (!_suspendTextChangeHandler)
{
@@ -731,7 +731,7 @@ namespace Avalonia.Controls
}
private void OnDateSelected(DateTime? addedDate, DateTime? removedDate)
{
- EventHandler handler = this.SelectedDateChanged;
+ EventHandler? handler = this.SelectedDateChanged;
if (null != handler)
{
Collection addedItems = new Collection();
@@ -759,23 +759,23 @@ namespace Avalonia.Controls
CalendarOpened?.Invoke(this, e);
}
- private void Calendar_DayButtonMouseUp(object sender, PointerReleasedEventArgs e)
+ private void Calendar_DayButtonMouseUp(object? sender, PointerReleasedEventArgs e)
{
Focus();
IsDropDownOpen = false;
}
- private void Calendar_DisplayDateChanged(object sender, CalendarDateChangedEventArgs e)
+ private void Calendar_DisplayDateChanged(object? sender, CalendarDateChangedEventArgs e)
{
if (e.AddedDate != this.DisplayDate)
{
- SetValue(DisplayDateProperty, (DateTime) e.AddedDate);
+ SetValue(DisplayDateProperty, (DateTime) e.AddedDate!);
}
}
- private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
+ private void Calendar_SelectedDatesChanged(object? sender, SelectionChangedEventArgs e)
{
Debug.Assert(e.AddedItems.Count < 2, "There should be less than 2 AddedItems!");
- if (e.AddedItems.Count > 0 && SelectedDate.HasValue && DateTime.Compare((DateTime)e.AddedItems[0], SelectedDate.Value) != 0)
+ if (e.AddedItems.Count > 0 && SelectedDate.HasValue && DateTime.Compare((DateTime)e.AddedItems[0]!, SelectedDate.Value) != 0)
{
SelectedDate = (DateTime?)e.AddedItems[0];
}
@@ -796,7 +796,7 @@ namespace Avalonia.Controls
}
}
}
- private void Calendar_PointerReleased(object sender, PointerReleasedEventArgs e)
+ private void Calendar_PointerReleased(object? sender, PointerReleasedEventArgs e)
{
if (e.InitialPressMouseButton == MouseButton.Left)
@@ -804,10 +804,9 @@ namespace Avalonia.Controls
e.Handled = true;
}
}
- private void Calendar_KeyDown(object sender, KeyEventArgs e)
+ private void Calendar_KeyDown(object? sender, KeyEventArgs e)
{
- Calendar c = sender as Calendar;
- Contract.Requires(c != null);
+ Calendar? c = sender as Calendar ?? throw new ArgumentException("Sender must be Calendar.", nameof(sender));
if (!e.Handled && (e.Key == Key.Enter || e.Key == Key.Space || e.Key == Key.Escape) && c.DisplayMode == CalendarMode.Month)
{
@@ -820,11 +819,11 @@ namespace Avalonia.Controls
}
}
}
- private void TextBox_GotFocus(object sender, RoutedEventArgs e)
+ private void TextBox_GotFocus(object? sender, RoutedEventArgs e)
{
IsDropDownOpen = false;
}
- private void TextBox_KeyDown(object sender, KeyEventArgs e)
+ private void TextBox_KeyDown(object? sender, KeyEventArgs e)
{
if (!e.Handled)
{
@@ -840,11 +839,11 @@ namespace Avalonia.Controls
_suspendTextChangeHandler = false;
}
}
- private void DropDownButton_PointerPressed(object sender, PointerPressedEventArgs e)
+ private void DropDownButton_PointerPressed(object? sender, PointerPressedEventArgs e)
{
_ignoreButtonClick = _isPopupClosing;
}
- private void DropDownButton_Click(object sender, RoutedEventArgs e)
+ private void DropDownButton_Click(object? sender, RoutedEventArgs e)
{
if (!_ignoreButtonClick)
{
@@ -855,7 +854,7 @@ namespace Avalonia.Controls
_ignoreButtonClick = false;
}
}
- private void PopUp_Closed(object sender, EventArgs e)
+ private void PopUp_Closed(object? sender, EventArgs e)
{
IsDropDownOpen = false;
@@ -891,7 +890,7 @@ namespace Avalonia.Controls
private void OpenPopUp()
{
_onOpenSelectedDate = SelectedDate;
- _popUp.IsOpen = true;
+ _popUp!.IsOpen = true;
}
///
@@ -914,7 +913,7 @@ namespace Avalonia.Controls
{
newSelectedDate = DateTime.Parse(text, DateTimeHelper.GetCurrentDateFormat());
- if (Calendar.IsValidDateSelection(this._calendar, newSelectedDate))
+ if (Calendar.IsValidDateSelection(this._calendar!, newSelectedDate))
{
return newSelectedDate;
}
@@ -941,7 +940,7 @@ namespace Avalonia.Controls
}
return null;
}
- private string DateTimeToString(DateTime d)
+ private string? DateTimeToString(DateTime d)
{
DateTimeFormatInfo dtfi = DateTimeHelper.GetCurrentDateFormat();
@@ -982,7 +981,7 @@ namespace Avalonia.Controls
{
SetSelectedDate();
IsDropDownOpen = true;
- _calendar.Focus();
+ _calendar!.Focus();
}
private void SetSelectedDate()
{
@@ -1001,7 +1000,7 @@ namespace Avalonia.Controls
// ex: SelectedDate = DateTime(1008,12,19) but when
// "12/19/08" is parsed it is interpreted as
// DateTime(2008,12,19)
- string selectedDate = DateTimeToString(SelectedDate.Value);
+ string? selectedDate = DateTimeToString(SelectedDate.Value);
if (selectedDate == s)
{
return;
@@ -1053,7 +1052,7 @@ namespace Avalonia.Controls
// SelectedDate value:
if (SelectedDate != null)
{
- string newtext = this.DateTimeToString(SelectedDate.Value);
+ string? newtext = this.DateTimeToString(SelectedDate.Value);
SetValue(TextProperty, newtext);
return SelectedDate;
}
diff --git a/src/Avalonia.Controls/Calendar/CalendarDateRange.cs b/src/Avalonia.Controls/Calendar/CalendarDateRange.cs
index 47a0ad047b..88bc5ed7bd 100644
--- a/src/Avalonia.Controls/Calendar/CalendarDateRange.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarDateRange.cs
@@ -65,7 +65,7 @@ namespace Avalonia.Controls
/// Inherited code: Requires comment 2.
internal bool ContainsAny(CalendarDateRange range)
{
- Contract.Requires(range != null);
+ _ = range ?? throw new ArgumentNullException(nameof(range));
int start = DateTime.Compare(Start, range.Start);
diff --git a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
index d5748bb9e4..2ba4e36260 100644
--- a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
@@ -40,7 +40,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets or sets the Calendar associated with this button.
///
- internal Calendar Owner { get; set; }
+ internal Calendar? Owner { get; set; }
internal int Index { get; set; }
///
@@ -177,7 +177,7 @@ namespace Avalonia.Controls.Primitives
/// stylus touches the tablet PC) while the mouse pointer is over a
/// UIElement.
///
- public event EventHandler CalendarDayButtonMouseDown;
+ public event EventHandler? CalendarDayButtonMouseDown;
///
/// Occurs when the left mouse button is released (or the tip of the
@@ -185,7 +185,7 @@ namespace Avalonia.Controls.Primitives
/// stylus) is over a UIElement (or while a UIElement holds mouse
/// capture).
///
- public event EventHandler CalendarDayButtonMouseUp;
+ public event EventHandler? CalendarDayButtonMouseUp;
///
/// Provides class handling for the MouseLeftButtonDown event that
diff --git a/src/Avalonia.Controls/Calendar/CalendarItem.cs b/src/Avalonia.Controls/Calendar/CalendarItem.cs
index e830717b95..616b9083ff 100644
--- a/src/Avalonia.Controls/Calendar/CalendarItem.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarItem.cs
@@ -33,10 +33,10 @@ namespace Avalonia.Controls.Primitives
private const string PART_ElementMonthView = "MonthView";
private const string PART_ElementYearView = "YearView";
- private Button _headerButton;
- private Button _nextButton;
- private Button _previousButton;
- private ITemplate _dayTitleTemplate;
+ private Button? _headerButton;
+ private Button? _nextButton;
+ private Button? _previousButton;
+ private ITemplate? _dayTitleTemplate;
private DateTime _currentMonth;
private bool _isMouseLeftButtonDown = false;
@@ -45,11 +45,11 @@ namespace Avalonia.Controls.Primitives
private System.Globalization.Calendar _calendar = new System.Globalization.GregorianCalendar();
- private PointerPressedEventArgs _downEventArg;
- private PointerPressedEventArgs _downEventArgYearView;
+ private PointerPressedEventArgs? _downEventArg;
+ private PointerPressedEventArgs? _downEventArgYearView;
- internal Calendar Owner { get; set; }
- internal CalendarDayButton CurrentButton { get; set; }
+ internal Calendar? Owner { get; set; }
+ internal CalendarDayButton? CurrentButton { get; set; }
public static readonly StyledProperty HeaderBackgroundProperty = Calendar.HeaderBackgroundProperty.AddOwner();
public IBrush HeaderBackground
@@ -57,13 +57,13 @@ namespace Avalonia.Controls.Primitives
get { return GetValue(HeaderBackgroundProperty); }
set { SetValue(HeaderBackgroundProperty, value); }
}
- public static readonly DirectProperty> DayTitleTemplateProperty =
- AvaloniaProperty.RegisterDirect>(
+ public static readonly DirectProperty?> DayTitleTemplateProperty =
+ AvaloniaProperty.RegisterDirect?>(
nameof(DayTitleTemplate),
o => o.DayTitleTemplate,
(o,v) => o.DayTitleTemplate = v,
defaultBindingMode: BindingMode.OneTime);
- public ITemplate DayTitleTemplate
+ public ITemplate? DayTitleTemplate
{
get { return _dayTitleTemplate; }
set { SetAndRaise(DayTitleTemplateProperty, ref _dayTitleTemplate, value); }
@@ -73,7 +73,7 @@ namespace Avalonia.Controls.Primitives
/// Gets the button that allows switching between month mode, year mode,
/// and decade mode.
///
- internal Button HeaderButton
+ internal Button? HeaderButton
{
get { return _headerButton; }
private set
@@ -94,7 +94,7 @@ namespace Avalonia.Controls.Primitives
/// Gets the button that displays the next page of the calendar when it
/// is clicked.
///
- internal Button NextButton
+ internal Button? NextButton
{
get { return _nextButton; }
private set
@@ -125,7 +125,7 @@ namespace Avalonia.Controls.Primitives
/// Gets the button that displays the previous page of the calendar when
/// it is clicked.
///
- internal Button PreviousButton
+ internal Button? PreviousButton
{
get { return _previousButton; }
private set
@@ -156,11 +156,11 @@ namespace Avalonia.Controls.Primitives
///
/// Gets the Grid that hosts the content when in month mode.
///
- internal Grid MonthView { get; set; }
+ internal Grid? MonthView { get; set; }
///
/// Gets the Grid that hosts the content when in year or decade mode.
///
- internal Grid YearView { get; set; }
+ internal Grid? YearView { get; set; }
private void PopulateGrids()
{
@@ -294,7 +294,7 @@ namespace Avalonia.Controls.Primitives
{
for (int childIndex = 0; childIndex < Calendar.ColumnsPerMonth; childIndex++)
{
- var daytitle = MonthView.Children[childIndex];
+ var daytitle = MonthView!.Children[childIndex];
if (daytitle != null)
{
if (Owner != null)
@@ -495,8 +495,7 @@ namespace Avalonia.Controls.Primitives
for (int childIndex = Calendar.ColumnsPerMonth; childIndex < count; childIndex++)
{
- CalendarDayButton childButton = MonthView.Children[childIndex] as CalendarDayButton;
- Contract.Requires(childButton != null);
+ CalendarDayButton childButton = (CalendarDayButton)MonthView!.Children[childIndex];
childButton.Index = childIndex;
SetButtonState(childButton, dateToAdd);
@@ -532,8 +531,7 @@ namespace Avalonia.Controls.Primitives
childIndex++;
for (int i = childIndex; i < count; i++)
{
- childButton = MonthView.Children[i] as CalendarDayButton;
- Contract.Requires(childButton != null);
+ childButton = (CalendarDayButton)MonthView.Children[i];
// button needs a content to occupy the necessary space
// for the content presenter
childButton.Content = i.ToString(DateTimeHelper.GetCurrentDateFormat());
@@ -626,10 +624,9 @@ namespace Avalonia.Controls.Primitives
private void SetMonthButtonsForYearMode()
{
int count = 0;
- foreach (object child in YearView.Children)
+ foreach (object child in YearView!.Children)
{
- CalendarButton childButton = child as CalendarButton;
- Contract.Requires(childButton != null);
+ CalendarButton childButton = (CalendarButton)child;
// There should be no time component. Time is 12:00 AM
DateTime day = new DateTime(_currentMonth.Year, count + 1, 1);
childButton.DataContext = day;
@@ -703,7 +700,7 @@ namespace Avalonia.Controls.Primitives
{
if (Owner != null && calendarButton != null && calendarButton.DataContext != null)
{
- Owner.FocusCalendarButton.IsCalendarButtonFocused = false;
+ Owner.FocusCalendarButton!.IsCalendarButtonFocused = false;
Owner.FocusCalendarButton = calendarButton;
calendarButton.IsCalendarButtonFocused = Owner.HasFocusInternal;
@@ -722,10 +719,9 @@ namespace Avalonia.Controls.Primitives
{
int year;
int count = -1;
- foreach (object child in YearView.Children)
+ foreach (object child in YearView!.Children)
{
- CalendarButton childButton = child as CalendarButton;
- Contract.Requires(childButton != null);
+ CalendarButton childButton = (CalendarButton)child;
year = decade + count;
if (year <= DateTime.MaxValue.Year && year >= DateTime.MinValue.Year)
@@ -797,7 +793,7 @@ namespace Avalonia.Controls.Primitives
}
}
- internal void HeaderButton_Click(object sender, RoutedEventArgs e)
+ internal void HeaderButton_Click(object? sender, RoutedEventArgs e)
{
if (Owner != null)
{
@@ -805,7 +801,7 @@ namespace Avalonia.Controls.Primitives
{
Owner.Focus();
}
- Button b = (Button)sender;
+ Button b = (Button)sender!;
DateTime d;
if (b.IsEnabled)
@@ -833,7 +829,7 @@ namespace Avalonia.Controls.Primitives
}
}
}
- internal void PreviousButton_Click(object sender, RoutedEventArgs e)
+ internal void PreviousButton_Click(object? sender, RoutedEventArgs e)
{
if (Owner != null)
{
@@ -842,14 +838,14 @@ namespace Avalonia.Controls.Primitives
Owner.Focus();
}
- Button b = (Button)sender;
+ Button b = (Button)sender!;
if (b.IsEnabled)
{
Owner.OnPreviousClick();
}
}
}
- internal void NextButton_Click(object sender, RoutedEventArgs e)
+ internal void NextButton_Click(object? sender, RoutedEventArgs e)
{
if (Owner != null)
{
@@ -857,7 +853,7 @@ namespace Avalonia.Controls.Primitives
{
Owner.Focus();
}
- Button b = (Button)sender;
+ Button b = (Button)sender!;
if (b.IsEnabled)
{
@@ -866,7 +862,7 @@ namespace Avalonia.Controls.Primitives
}
}
- internal void Cell_MouseEnter(object sender, PointerEventArgs e)
+ internal void Cell_MouseEnter(object? sender, PointerEventArgs e)
{
if (Owner != null)
{
@@ -878,7 +874,7 @@ namespace Avalonia.Controls.Primitives
{
case CalendarSelectionMode.SingleDate:
{
- DateTime selectedDate = (DateTime)b.DataContext;
+ DateTime selectedDate = (DateTime)b.DataContext!;
Owner.CalendarDatePickerDisplayDateFlag = true;
if (Owner.SelectedDates.Count == 0)
{
@@ -906,7 +902,7 @@ namespace Avalonia.Controls.Primitives
}
}
- internal void Cell_MouseLeftButtonDown(object sender, PointerPressedEventArgs e)
+ internal void Cell_MouseLeftButtonDown(object? sender, PointerPressedEventArgs e)
{
if (Owner != null)
{
@@ -917,15 +913,14 @@ namespace Avalonia.Controls.Primitives
bool ctrl, shift;
CalendarExtensions.GetMetaKeyState(e.KeyModifiers, out ctrl, out shift);
- CalendarDayButton b = sender as CalendarDayButton;
+ CalendarDayButton b = (CalendarDayButton)sender!;
if (b != null)
{
_isControlPressed = ctrl;
if (b.IsEnabled && !b.IsBlackout)
{
- DateTime selectedDate = (DateTime)b.DataContext;
- Contract.Requires(selectedDate != null);
+ DateTime selectedDate = (DateTime)b.DataContext!;
_isMouseLeftButtonDown = true;
// null check is added for unit tests
if (e != null)
@@ -1027,7 +1022,7 @@ namespace Avalonia.Controls.Primitives
if (Owner != null)
{
Owner.HoverEndIndex = b.Index;
- Owner.HoverEnd = (DateTime)b.DataContext;
+ Owner.HoverEnd = (DateTime)b.DataContext!;
if (Owner.HoverEnd != null && Owner.HoverStart != null)
{
@@ -1041,11 +1036,11 @@ namespace Avalonia.Controls.Primitives
}
}
}
- internal void Cell_MouseLeftButtonUp(object sender, PointerReleasedEventArgs e)
+ internal void Cell_MouseLeftButtonUp(object? sender, PointerReleasedEventArgs e)
{
if (Owner != null)
{
- CalendarDayButton b = sender as CalendarDayButton;
+ CalendarDayButton? b = sender as CalendarDayButton;
if (b != null && !b.IsBlackout)
{
Owner.OnDayButtonMouseUp(e);
@@ -1094,14 +1089,13 @@ namespace Avalonia.Controls.Primitives
}
}
}
- private void Cell_Click(object sender, RoutedEventArgs e)
+ private void Cell_Click(object? sender, RoutedEventArgs e)
{
if (Owner != null)
{
if (_isControlPressed && Owner.SelectionMode == CalendarSelectionMode.MultipleRange)
{
- CalendarDayButton b = sender as CalendarDayButton;
- Contract.Requires(b != null);
+ CalendarDayButton b = (CalendarDayButton)sender!;
if (b.IsSelected)
{
@@ -1118,10 +1112,9 @@ namespace Avalonia.Controls.Primitives
_isControlPressed = false;
}
- private void Month_CalendarButtonMouseDown(object sender, PointerPressedEventArgs e)
+ private void Month_CalendarButtonMouseDown(object? sender, PointerPressedEventArgs e)
{
- CalendarButton b = sender as CalendarButton;
- Contract.Requires(b != null);
+ CalendarButton b = (CalendarButton)sender!;
_isMouseLeftButtonDownYearView = true;
@@ -1133,13 +1126,13 @@ namespace Avalonia.Controls.Primitives
UpdateYearViewSelection(b);
}
- internal void Month_CalendarButtonMouseUp(object sender, PointerReleasedEventArgs e)
+ internal void Month_CalendarButtonMouseUp(object? sender, PointerReleasedEventArgs e)
{
_isMouseLeftButtonDownYearView = false;
if (Owner != null)
{
- DateTime newmonth = (DateTime)((CalendarButton)sender).DataContext;
+ DateTime newmonth = (DateTime)((CalendarButton)sender!).DataContext!;
if (Owner.DisplayMode == CalendarMode.Year)
{
@@ -1155,12 +1148,11 @@ namespace Avalonia.Controls.Primitives
}
}
- private void Month_MouseEnter(object sender, PointerEventArgs e)
+ private void Month_MouseEnter(object? sender, PointerEventArgs e)
{
if (_isMouseLeftButtonDownYearView)
{
- CalendarButton b = sender as CalendarButton;
- Contract.Requires(b != null);
+ CalendarButton b = (CalendarButton)sender!;
UpdateYearViewSelection(b);
}
}
diff --git a/src/Avalonia.Controls/Calendar/DateTimeHelper.cs b/src/Avalonia.Controls/Calendar/DateTimeHelper.cs
index 033bfc5726..eb90f6c399 100644
--- a/src/Avalonia.Controls/Calendar/DateTimeHelper.cs
+++ b/src/Avalonia.Controls/Calendar/DateTimeHelper.cs
@@ -5,6 +5,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace Avalonia.Controls
@@ -73,6 +74,7 @@ namespace Avalonia.Controls
return newD;
}
+ [return: NotNullIfNotNull("d")]
public static DateTime? DiscardTime(DateTime? d)
{
if (d == null)
diff --git a/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs b/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
index 3573c67057..c7c35718e0 100644
--- a/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
+++ b/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
@@ -49,7 +49,7 @@ namespace Avalonia.Controls.Primitives
private void InvokeCollectionChanged(System.Collections.IList removedItems, System.Collections.IList addedItems)
{
- _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(null, removedItems, addedItems));
+ _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(SelectingItemsControl.SelectionChangedEvent, removedItems, addedItems));
}
///
@@ -119,7 +119,7 @@ namespace Avalonia.Controls.Primitives
}
}
- _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(null, _owner.RemovedItems, _addedItems));
+ _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(SelectingItemsControl.SelectionChangedEvent, _owner.RemovedItems, _addedItems));
_owner.RemovedItems.Clear();
_owner.UpdateMonths();
_isRangeAdded = false;
diff --git a/src/Avalonia.Controls/Canvas.cs b/src/Avalonia.Controls/Canvas.cs
index 5cc823a6af..fabf8978c7 100644
--- a/src/Avalonia.Controls/Canvas.cs
+++ b/src/Avalonia.Controls/Canvas.cs
@@ -135,7 +135,7 @@ namespace Avalonia.Controls
/// The control from which movement begins.
/// Whether to wrap around when the first or last item is reached.
/// The control.
- IInputElement INavigableContainer.GetControl(NavigationDirection direction, IInputElement from, bool wrap)
+ IInputElement? INavigableContainer.GetControl(NavigationDirection direction, IInputElement? from, bool wrap)
{
// TODO: Implement this
return null;
diff --git a/src/Avalonia.Controls/Chrome/CaptionButtons.cs b/src/Avalonia.Controls/Chrome/CaptionButtons.cs
index be15d3d444..1cad1a4c69 100644
--- a/src/Avalonia.Controls/Chrome/CaptionButtons.cs
+++ b/src/Avalonia.Controls/Chrome/CaptionButtons.cs
@@ -3,8 +3,6 @@ using System.Reactive.Disposables;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
-#nullable enable
-
namespace Avalonia.Controls.Chrome
{
///
diff --git a/src/Avalonia.Controls/Chrome/TitleBar.cs b/src/Avalonia.Controls/Chrome/TitleBar.cs
index fbddb06952..4da50e7220 100644
--- a/src/Avalonia.Controls/Chrome/TitleBar.cs
+++ b/src/Avalonia.Controls/Chrome/TitleBar.cs
@@ -3,8 +3,6 @@ using System.Reactive.Disposables;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
-#nullable enable
-
namespace Avalonia.Controls.Chrome
{
///
@@ -36,7 +34,7 @@ namespace Avalonia.Controls.Chrome
}
}
- IsVisible = window.PlatformImpl.NeedsManagedDecorations;
+ IsVisible = window.PlatformImpl?.NeedsManagedDecorations ?? false;
}
}
diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs
index 274696d501..d38cd3a0fd 100644
--- a/src/Avalonia.Controls/ComboBox.cs
+++ b/src/Avalonia.Controls/ComboBox.cs
@@ -46,8 +46,8 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly DirectProperty SelectionBoxItemProperty =
- AvaloniaProperty.RegisterDirect(nameof(SelectionBoxItem), o => o.SelectionBoxItem);
+ public static readonly DirectProperty SelectionBoxItemProperty =
+ AvaloniaProperty.RegisterDirect(nameof(SelectionBoxItem), o => o.SelectionBoxItem);
///
/// Defines the property.
@@ -58,14 +58,14 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty PlaceholderTextProperty =
- AvaloniaProperty.Register(nameof(PlaceholderText));
+ public static readonly StyledProperty PlaceholderTextProperty =
+ AvaloniaProperty.Register(nameof(PlaceholderText));
///
/// Defines the property.
///
- public static readonly StyledProperty PlaceholderForegroundProperty =
- AvaloniaProperty.Register(nameof(PlaceholderForeground));
+ public static readonly StyledProperty PlaceholderForegroundProperty =
+ AvaloniaProperty.Register(nameof(PlaceholderForeground));
///
/// Defines the property.
@@ -80,8 +80,8 @@ namespace Avalonia.Controls
ContentControl.VerticalContentAlignmentProperty.AddOwner();
private bool _isDropDownOpen;
- private Popup _popup;
- private object _selectionBoxItem;
+ private Popup? _popup;
+ private object? _selectionBoxItem;
private readonly CompositeDisposable _subscriptionsOnOpen = new CompositeDisposable();
///
@@ -117,7 +117,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the item to display as the control's content.
///
- protected object SelectionBoxItem
+ protected object? SelectionBoxItem
{
get { return _selectionBoxItem; }
set { SetAndRaise(SelectionBoxItemProperty, ref _selectionBoxItem, value); }
@@ -126,7 +126,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the PlaceHolder text.
///
- public string PlaceholderText
+ public string? PlaceholderText
{
get { return GetValue(PlaceholderTextProperty); }
set { SetValue(PlaceholderTextProperty, value); }
@@ -135,7 +135,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the Brush that renders the placeholder text.
///
- public IBrush PlaceholderForeground
+ public IBrush? PlaceholderForeground
{
get { return GetValue(PlaceholderForegroundProperty); }
set { SetValue(PlaceholderForegroundProperty, value); }
@@ -262,9 +262,9 @@ namespace Avalonia.Controls
///
protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
- if (!e.Handled)
+ if (!e.Handled && e.Source is IVisual source)
{
- if (_popup?.IsInsidePopup((IVisual)e.Source) == true)
+ if (_popup?.IsInsidePopup(source) == true)
{
if (UpdateSelectionFromEventSource(e.Source))
{
@@ -304,7 +304,7 @@ namespace Avalonia.Controls
}
}
- private void PopupClosed(object sender, EventArgs e)
+ private void PopupClosed(object? sender, EventArgs e)
{
_subscriptionsOnOpen.Clear();
@@ -314,7 +314,7 @@ namespace Avalonia.Controls
}
}
- private void PopupOpened(object sender, EventArgs e)
+ private void PopupOpened(object? sender, EventArgs e)
{
TryFocusSelectedItem();
@@ -326,7 +326,7 @@ namespace Avalonia.Controls
toplevel.AddDisposableHandler(PointerWheelChangedEvent, (s, ev) =>
{
//eat wheel scroll event outside dropdown popup while it's open
- if (IsDropDownOpen && (ev.Source as IVisual).GetVisualRoot() == toplevel)
+ if (IsDropDownOpen && (ev.Source as IVisual)?.GetVisualRoot() == toplevel)
{
ev.Handled = true;
}
@@ -360,12 +360,12 @@ namespace Avalonia.Controls
var selectedIndex = SelectedIndex;
if (IsDropDownOpen && selectedIndex != -1)
{
- var container = ItemContainerGenerator.ContainerFromIndex(selectedIndex);
+ var container = ItemContainerGenerator!.ContainerFromIndex(selectedIndex);
if (container == null && SelectedIndex != -1)
{
ScrollIntoView(Selection.SelectedIndex);
- container = ItemContainerGenerator.ContainerFromIndex(selectedIndex);
+ container = ItemContainerGenerator!.ContainerFromIndex(selectedIndex);
}
if (container != null && CanFocus(container))
@@ -377,7 +377,7 @@ namespace Avalonia.Controls
private bool CanFocus(IControl control) => control.Focusable && control.IsEffectivelyEnabled && control.IsVisible;
- private void UpdateSelectionBoxItem(object item)
+ private void UpdateSelectionBoxItem(object? item)
{
var contentControl = item as IContentControl;
@@ -415,7 +415,7 @@ namespace Avalonia.Controls
private void SelectFocusedItem()
{
- foreach (ItemContainerInfo dropdownItem in ItemContainerGenerator.Containers)
+ foreach (ItemContainerInfo dropdownItem in ItemContainerGenerator!.Containers)
{
if (dropdownItem.ContainerControl.IsFocused)
{
diff --git a/src/Avalonia.Controls/ContentControl.cs b/src/Avalonia.Controls/ContentControl.cs
index 1329bd91c7..ac7d24be92 100644
--- a/src/Avalonia.Controls/ContentControl.cs
+++ b/src/Avalonia.Controls/ContentControl.cs
@@ -17,14 +17,14 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty ContentProperty =
- AvaloniaProperty.Register(nameof(Content));
+ public static readonly StyledProperty ContentProperty =
+ AvaloniaProperty.Register(nameof(Content));
///
/// Defines the property.
///
- public static readonly StyledProperty ContentTemplateProperty =
- AvaloniaProperty.Register(nameof(ContentTemplate));
+ public static readonly StyledProperty ContentTemplateProperty =
+ AvaloniaProperty.Register(nameof(ContentTemplate));
///
/// Defines the property.
@@ -48,7 +48,7 @@ namespace Avalonia.Controls
///
[Content]
[DependsOn(nameof(ContentTemplate))]
- public object Content
+ public object? Content
{
get { return GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
@@ -57,7 +57,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the data template used to display the content of the control.
///
- public IDataTemplate ContentTemplate
+ public IDataTemplate? ContentTemplate
{
get { return GetValue(ContentTemplateProperty); }
set { SetValue(ContentTemplateProperty, value); }
@@ -66,7 +66,7 @@ namespace Avalonia.Controls
///
/// Gets the presenter from the control's template.
///
- public IContentPresenter Presenter
+ public IContentPresenter? Presenter
{
get;
private set;
diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs
index d94bff37df..dff06a6369 100644
--- a/src/Avalonia.Controls/ContextMenu.cs
+++ b/src/Avalonia.Controls/ContextMenu.cs
@@ -14,8 +14,6 @@ using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Styling;
-#nullable enable
-
namespace Avalonia.Controls
{
///
@@ -368,7 +366,7 @@ namespace Avalonia.Controls
});
}
- private void PopupOpened(object sender, EventArgs e)
+ private void PopupOpened(object? sender, EventArgs e)
{
_previousFocus = FocusManager.Instance?.Current;
Focus();
@@ -376,12 +374,12 @@ namespace Avalonia.Controls
_popupHostChangedHandler?.Invoke(_popup!.Host);
}
- private void PopupClosing(object sender, CancelEventArgs e)
+ private void PopupClosing(object? sender, CancelEventArgs e)
{
e.Cancel = CancelClosing();
}
- private void PopupClosed(object sender, EventArgs e)
+ private void PopupClosed(object? sender, EventArgs e)
{
foreach (var i in LogicalChildren)
{
@@ -411,7 +409,7 @@ namespace Avalonia.Controls
_popupHostChangedHandler?.Invoke(null);
}
- private void PopupKeyUp(object sender, KeyEventArgs e)
+ private void PopupKeyUp(object? sender, KeyEventArgs e)
{
if (IsOpen)
{
@@ -426,7 +424,7 @@ namespace Avalonia.Controls
}
}
- private static void ControlContextRequested(object sender, ContextRequestedEventArgs e)
+ private static void ControlContextRequested(object? sender, ContextRequestedEventArgs e)
{
if (sender is Control control
&& control.ContextMenu is ContextMenu contextMenu
@@ -439,7 +437,7 @@ namespace Avalonia.Controls
}
}
- private static void ControlDetachedFromVisualTree(object sender, VisualTreeAttachmentEventArgs e)
+ private static void ControlDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
if (sender is Control control
&& control.ContextMenu is ContextMenu contextMenu)
diff --git a/src/Avalonia.Controls/ContextRequestedEventArgs.cs b/src/Avalonia.Controls/ContextRequestedEventArgs.cs
index 8dc798245c..ad5ffef267 100644
--- a/src/Avalonia.Controls/ContextRequestedEventArgs.cs
+++ b/src/Avalonia.Controls/ContextRequestedEventArgs.cs
@@ -1,8 +1,6 @@
using Avalonia.Input;
using Avalonia.Interactivity;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index 441421181c..b9f3bd8890 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -1,16 +1,16 @@
using System;
using System.ComponentModel;
+using System.Runtime.CompilerServices;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Interactivity;
+using Avalonia.Media;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls
{
///
@@ -60,7 +60,13 @@ namespace Avalonia.Controls
public static readonly RoutedEvent ContextRequestedEvent =
RoutedEvent.Register(nameof(ContextRequested),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
-
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly AttachedProperty FlowDirectionProperty =
+ AvaloniaProperty.RegisterAttached(nameof(FlowDirection), inherits: true);
+
private DataTemplates? _dataTemplates;
private IControl? _focusAdorner;
@@ -108,11 +114,20 @@ namespace Avalonia.Controls
get => GetValue(TagProperty);
set => SetValue(TagProperty, value);
}
+
+ ///
+ /// Gets or sets the text flow direction.
+ ///
+ public FlowDirection FlowDirection
+ {
+ get => GetValue(FlowDirectionProperty);
+ set => SetValue(FlowDirectionProperty, value);
+ }
///
/// Occurs when the user has completed a context input gesture, such as a right-click.
///
- public event EventHandler ContextRequested
+ public event EventHandler? ContextRequested
{
add => AddHandler(ContextRequestedEvent, value);
remove => RemoveHandler(ContextRequestedEvent, value);
diff --git a/src/Avalonia.Controls/ControlExtensions.cs b/src/Avalonia.Controls/ControlExtensions.cs
index c3cab0a729..1718679294 100644
--- a/src/Avalonia.Controls/ControlExtensions.cs
+++ b/src/Avalonia.Controls/ControlExtensions.cs
@@ -17,7 +17,7 @@ namespace Avalonia.Controls
/// The control.
public static void BringIntoView(this IControl control)
{
- Contract.Requires(control != null);
+ _ = control ?? throw new ArgumentNullException(nameof(control));
control.BringIntoView(new Rect(control.Bounds.Size));
}
@@ -29,7 +29,7 @@ namespace Avalonia.Controls
/// The area of the control to being into view.
public static void BringIntoView(this IControl control, Rect rect)
{
- Contract.Requires(control != null);
+ _ = control ?? throw new ArgumentNullException(nameof(control));
if (control.IsEffectivelyVisible)
{
@@ -51,10 +51,10 @@ namespace Avalonia.Controls
/// The control to look in.
/// The name of the control to find.
/// The control or null if not found.
- public static T FindControl(this IControl control, string name) where T : class, IControl
+ public static T? FindControl(this IControl control, string name) where T : class, IControl
{
- Contract.Requires(control != null);
- Contract.Requires(name != null);
+ _ = control ?? throw new ArgumentNullException(nameof(control));
+ _ = name ?? throw new ArgumentNullException(nameof(name));
var nameScope = control.FindNameScope();
@@ -66,6 +66,29 @@ namespace Avalonia.Controls
return nameScope.Find(name);
}
+ ///
+ /// Finds the named control in the scope of the specified control and throws if not found.
+ ///
+ /// The type of the control to find.
+ /// The control to look in.
+ /// The name of the control to find.
+ /// The control.
+ public static T GetControl(this IControl control, string name) where T : class, IControl
+ {
+ _ = control ?? throw new ArgumentNullException(nameof(control));
+ _ = name ?? throw new ArgumentNullException(nameof(name));
+
+ var nameScope = control.FindNameScope();
+
+ if (nameScope == null)
+ {
+ throw new InvalidOperationException("Could not find parent name scope.");
+ }
+
+ return nameScope.Find(name) ??
+ throw new ArgumentException($"Could not find control named '{name}'.");
+ }
+
///
/// Sets a pseudoclass depending on an observable trigger.
///
@@ -75,7 +98,7 @@ namespace Avalonia.Controls
/// A disposable used to cancel the subscription.
public static IDisposable Set(this IPseudoClasses classes, string name, IObservable trigger)
{
- Contract.Requires(classes != null);
+ _ = classes ?? throw new ArgumentNullException(nameof(classes));
return trigger.Subscribe(x => classes.Set(name, x));
}
diff --git a/src/Avalonia.Controls/Converters/CornerRadiusFilterConverter.cs b/src/Avalonia.Controls/Converters/CornerRadiusFilterConverter.cs
index 7587a9dacb..643c30178e 100644
--- a/src/Avalonia.Controls/Converters/CornerRadiusFilterConverter.cs
+++ b/src/Avalonia.Controls/Converters/CornerRadiusFilterConverter.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System;
+using System;
using System.Globalization;
using Avalonia.Data.Converters;
diff --git a/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs b/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs
index 46affcbe33..b0c30ea11f 100644
--- a/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs
+++ b/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs
@@ -16,7 +16,7 @@ namespace Avalonia.Controls.Converters
public bool Bottom { get; set; } = false;
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is int scalarDepth)
{
@@ -38,7 +38,7 @@ namespace Avalonia.Controls.Converters
}
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new System.NotImplementedException();
}
diff --git a/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs b/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs
index 65f95808ff..6ab2f4c517 100644
--- a/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs
+++ b/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Controls.Converters
{
public static readonly MenuScrollingVisibilityConverter Instance = new MenuScrollingVisibilityConverter();
- public object Convert(IList values, Type targetType, object parameter, CultureInfo culture)
+ public object? Convert(IList values, Type targetType, object? parameter, CultureInfo culture)
{
if (parameter == null ||
values == null ||
diff --git a/src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs b/src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs
index 2af8dba479..9a657cce68 100644
--- a/src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs
+++ b/src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs
@@ -13,7 +13,7 @@ namespace Avalonia.Controls.Converters
///
public class PlatformKeyGestureConverter : IValueConverter
{
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is null)
{
@@ -29,7 +29,7 @@ namespace Avalonia.Controls.Converters
}
}
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
diff --git a/src/Avalonia.Controls/DataValidationErrors.cs b/src/Avalonia.Controls/DataValidationErrors.cs
index 3c64691816..00a06101c5 100644
--- a/src/Avalonia.Controls/DataValidationErrors.cs
+++ b/src/Avalonia.Controls/DataValidationErrors.cs
@@ -21,8 +21,8 @@ namespace Avalonia.Controls
///
/// Defines the DataValidationErrors.Errors attached property.
///
- public static readonly AttachedProperty> ErrorsProperty =
- AvaloniaProperty.RegisterAttached>("Errors");
+ public static readonly AttachedProperty?> ErrorsProperty =
+ AvaloniaProperty.RegisterAttached?>("Errors");
///
/// Defines the DataValidationErrors.HasErrors attached property.
@@ -34,15 +34,15 @@ namespace Avalonia.Controls
AvaloniaProperty.Register(nameof(ErrorTemplate));
- private Control _owner;
+ private Control? _owner;
- public static readonly DirectProperty OwnerProperty =
- AvaloniaProperty.RegisterDirect(
+ public static readonly DirectProperty OwnerProperty =
+ AvaloniaProperty.RegisterDirect(
nameof(Owner),
o => o.Owner,
(o, v) => o.Owner = v);
- public Control Owner
+ public Control? Owner
{
get { return _owner; }
set { SetAndRaise(OwnerProperty, ref _owner, value); }
@@ -75,7 +75,7 @@ namespace Avalonia.Controls
private static void ErrorsChanged(AvaloniaPropertyChangedEventArgs e)
{
var control = (Control)e.Sender;
- var errors = (IEnumerable)e.NewValue;
+ var errors = (IEnumerable?)e.NewValue;
var hasErrors = false;
if (errors != null && errors.Any())
@@ -87,18 +87,18 @@ namespace Avalonia.Controls
{
var control = (Control)e.Sender;
var classes = (IPseudoClasses)control.Classes;
- classes.Set(":error", (bool)e.NewValue);
+ classes.Set(":error", (bool)e.NewValue!);
}
- public static IEnumerable GetErrors(Control control)
+ public static IEnumerable? GetErrors(Control control)
{
return control.GetValue(ErrorsProperty);
}
- public static void SetErrors(Control control, IEnumerable errors)
+ public static void SetErrors(Control control, IEnumerable? errors)
{
control.SetValue(ErrorsProperty, errors);
}
- public static void SetError(Control control, Exception error)
+ public static void SetError(Control control, Exception? error)
{
SetErrors(control, UnpackException(error));
}
@@ -111,7 +111,7 @@ namespace Avalonia.Controls
return control.GetValue(HasErrorsProperty);
}
- private static IEnumerable UnpackException(Exception exception)
+ private static IEnumerable? UnpackException(Exception? exception)
{
if (exception != null)
{
@@ -132,8 +132,9 @@ namespace Avalonia.Controls
private static object GetExceptionData(Exception exception)
{
- if (exception is DataValidationException dataValidationException)
- return dataValidationException.ErrorData;
+ if (exception is DataValidationException dataValidationException &&
+ dataValidationException.ErrorData is object data)
+ return data;
return exception;
}
diff --git a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
index 5893a02b04..8c6ac17280 100644
--- a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
@@ -93,15 +93,15 @@ namespace Avalonia.Controls
defaultBindingMode: BindingMode.TwoWay);
// Template Items
- private Button _flyoutButton;
- private TextBlock _dayText;
- private TextBlock _monthText;
- private TextBlock _yearText;
- private Grid _container;
- private Rectangle _spacer1;
- private Rectangle _spacer2;
- private Popup _popup;
- private DatePickerPresenter _presenter;
+ private Button? _flyoutButton;
+ private TextBlock? _dayText;
+ private TextBlock? _monthText;
+ private TextBlock? _yearText;
+ private Grid? _container;
+ private Rectangle? _spacer1;
+ private Rectangle? _spacer2;
+ private Popup? _popup;
+ private DatePickerPresenter? _presenter;
private bool _areControlsAvailable;
@@ -256,7 +256,7 @@ namespace Avalonia.Controls
///
/// Raised when the changes
///
- public event EventHandler SelectedDateChanged;
+ public event EventHandler? SelectedDateChanged;
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
@@ -307,16 +307,16 @@ namespace Avalonia.Controls
}
}
- private void OnDismissPicker(object sender, EventArgs e)
+ private void OnDismissPicker(object? sender, EventArgs e)
{
- _popup.Close();
+ _popup!.Close();
Focus();
}
- private void OnConfirmed(object sender, EventArgs e)
+ private void OnConfirmed(object? sender, EventArgs e)
{
- _popup.Close();
- SelectedDate = _presenter.Date;
+ _popup!.Close();
+ SelectedDate = _presenter!.Date;
}
private void SetGrid()
@@ -325,7 +325,7 @@ namespace Avalonia.Controls
return;
var fmt = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
- var columns = new List<(TextBlock, int)>
+ var columns = new List<(TextBlock?, int)>
{
(_monthText, MonthVisible ? fmt.IndexOf("m", StringComparison.OrdinalIgnoreCase) : -1),
(_yearText, YearVisible ? fmt.IndexOf("y", StringComparison.OrdinalIgnoreCase) : -1),
@@ -366,11 +366,11 @@ namespace Avalonia.Controls
var isSpacer1Visible = columnIndex > 1;
var isSpacer2Visible = columnIndex > 2;
// ternary conditional operator is used to make sure grid cells will be validated
- Grid.SetColumn(_spacer1, isSpacer1Visible ? 1 : 0);
- Grid.SetColumn(_spacer2, isSpacer2Visible ? 3 : 0);
+ Grid.SetColumn(_spacer1!, isSpacer1Visible ? 1 : 0);
+ Grid.SetColumn(_spacer2!, isSpacer2Visible ? 3 : 0);
- _spacer1.IsVisible = isSpacer1Visible;
- _spacer2.IsVisible = isSpacer2Visible;
+ _spacer1!.IsVisible = isSpacer1Visible;
+ _spacer2!.IsVisible = isSpacer2Visible;
}
private void SetSelectedDateText()
@@ -382,37 +382,37 @@ namespace Avalonia.Controls
{
PseudoClasses.Set(":hasnodate", false);
var selDate = SelectedDate.Value;
- _monthText.Text = selDate.ToString(MonthFormat);
- _yearText.Text = selDate.ToString(YearFormat);
- _dayText.Text = selDate.ToString(DayFormat);
+ _monthText!.Text = selDate.ToString(MonthFormat);
+ _yearText!.Text = selDate.ToString(YearFormat);
+ _dayText!.Text = selDate.ToString(DayFormat);
}
else
{
PseudoClasses.Set(":hasnodate", true);
- _monthText.Text = "month";
- _yearText.Text = "year";
- _dayText.Text = "day";
+ _monthText!.Text = "month";
+ _yearText!.Text = "year";
+ _dayText!.Text = "day";
}
}
- private void OnFlyoutButtonClicked(object sender, RoutedEventArgs e)
+ private void OnFlyoutButtonClicked(object? sender, RoutedEventArgs e)
{
if (_presenter == null)
throw new InvalidOperationException("No DatePickerPresenter found");
_presenter.Date = SelectedDate ?? DateTimeOffset.Now;
- _popup.IsOpen = true;
+ _popup!.IsOpen = true;
var deltaY = _presenter.GetOffsetForPopup();
// The extra 5 px I think is related to default popup placement behavior
- _popup.Host.ConfigurePosition(_popup.PlacementTarget, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
+ _popup!.Host!.ConfigurePosition(_popup.PlacementTarget!, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom,
Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY);
}
- protected virtual void OnSelectedDateChanged(object sender, DatePickerSelectedValueChangedEventArgs e)
+ protected virtual void OnSelectedDateChanged(object? sender, DatePickerSelectedValueChangedEventArgs e)
{
SelectedDateChanged?.Invoke(sender, e);
}
diff --git a/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs b/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
index eec4615736..eac6d83074 100644
--- a/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
@@ -78,23 +78,23 @@ namespace Avalonia.Controls
x.YearVisible, (x, v) => x.YearVisible = v);
// Template Items
- private Grid _pickerContainer;
- private Button _acceptButton;
- private Button _dismissButton;
- private Rectangle _spacer1;
- private Rectangle _spacer2;
- private Panel _monthHost;
- private Panel _yearHost;
- private Panel _dayHost;
- private DateTimePickerPanel _monthSelector;
- private DateTimePickerPanel _yearSelector;
- private DateTimePickerPanel _daySelector;
- private Button _monthUpButton;
- private Button _dayUpButton;
- private Button _yearUpButton;
- private Button _monthDownButton;
- private Button _dayDownButton;
- private Button _yearDownButton;
+ private Grid? _pickerContainer;
+ private Button? _acceptButton;
+ private Button? _dismissButton;
+ private Rectangle? _spacer1;
+ private Rectangle? _spacer2;
+ private Panel? _monthHost;
+ private Panel? _yearHost;
+ private Panel? _dayHost;
+ private DateTimePickerPanel? _monthSelector;
+ private DateTimePickerPanel? _yearSelector;
+ private DateTimePickerPanel? _daySelector;
+ private Button? _monthUpButton;
+ private Button? _dayUpButton;
+ private Button? _yearUpButton;
+ private Button? _monthDownButton;
+ private Button? _dayDownButton;
+ private Button? _yearDownButton;
private DateTimeOffset _date;
private string _dayFormat = "%d";
@@ -308,9 +308,12 @@ namespace Avalonia.Controls
e.Handled = true;
break;
case Key.Tab:
- var nextFocus = KeyboardNavigationHandler.GetNext(FocusManager.Instance.Current, NavigationDirection.Next);
- KeyboardDevice.Instance?.SetFocusedElement(nextFocus, NavigationMethod.Tab, KeyModifiers.None);
- e.Handled = true;
+ if (FocusManager.Instance?.Current is IInputElement focus)
+ {
+ var nextFocus = KeyboardNavigationHandler.GetNext(focus, NavigationDirection.Next);
+ KeyboardDevice.Instance?.SetFocusedElement(nextFocus, NavigationMethod.Tab, KeyModifiers.None);
+ e.Handled = true;
+ }
break;
case Key.Enter:
Date = _syncDate;
@@ -332,13 +335,13 @@ namespace Avalonia.Controls
_suppressUpdateSelection = true;
- _monthSelector.MaximumValue = 12;
+ _monthSelector!.MaximumValue = 12;
_monthSelector.MinimumValue = 1;
_monthSelector.ItemFormat = MonthFormat;
- _daySelector.ItemFormat = DayFormat;
+ _daySelector!.ItemFormat = DayFormat;
- _yearSelector.MaximumValue = MaxYear.Year;
+ _yearSelector!.MaximumValue = MaxYear.Year;
_yearSelector.MinimumValue = MinYear.Year;
_yearSelector.ItemFormat = YearFormat;
@@ -375,7 +378,7 @@ namespace Avalonia.Controls
private void SetGrid()
{
var fmt = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
- var columns = new List<(Panel, int)>
+ var columns = new List<(Panel?, int)>
{
(_monthHost, MonthVisible ? fmt.IndexOf("m", StringComparison.OrdinalIgnoreCase) : -1),
(_yearHost, YearVisible ? fmt.IndexOf("y", StringComparison.OrdinalIgnoreCase) : -1),
@@ -383,7 +386,7 @@ namespace Avalonia.Controls
};
columns.Sort((x, y) => x.Item2 - y.Item2);
- _pickerContainer.ColumnDefinitions.Clear();
+ _pickerContainer!.ColumnDefinitions.Clear();
var columnIndex = 0;
@@ -416,18 +419,18 @@ namespace Avalonia.Controls
var isSpacer1Visible = columnIndex > 1;
var isSpacer2Visible = columnIndex > 2;
// ternary conditional operator is used to make sure grid cells will be validated
- Grid.SetColumn(_spacer1, isSpacer1Visible ? 1 : 0);
- Grid.SetColumn(_spacer2, isSpacer2Visible ? 3 : 0);
+ Grid.SetColumn(_spacer1!, isSpacer1Visible ? 1 : 0);
+ Grid.SetColumn(_spacer2!, isSpacer2Visible ? 3 : 0);
- _spacer1.IsVisible = isSpacer1Visible;
- _spacer2.IsVisible = isSpacer2Visible;
+ _spacer1!.IsVisible = isSpacer1Visible;
+ _spacer2!.IsVisible = isSpacer2Visible;
}
private void SetInitialFocus()
{
- int monthCol = MonthVisible ? Grid.GetColumn(_monthHost) : int.MaxValue;
- int dayCol = DayVisible ? Grid.GetColumn(_dayHost) : int.MaxValue;
- int yearCol = YearVisible ? Grid.GetColumn(_yearHost) : int.MaxValue;
+ int monthCol = MonthVisible ? Grid.GetColumn(_monthHost!) : int.MaxValue;
+ int dayCol = DayVisible ? Grid.GetColumn(_dayHost!) : int.MaxValue;
+ int yearCol = YearVisible ? Grid.GetColumn(_yearHost!) : int.MaxValue;
if (monthCol < dayCol && monthCol < yearCol)
{
@@ -443,39 +446,39 @@ namespace Avalonia.Controls
}
}
- private void OnDismissButtonClicked(object sender, RoutedEventArgs e)
+ private void OnDismissButtonClicked(object? sender, RoutedEventArgs e)
{
OnDismiss();
}
- private void OnAcceptButtonClicked(object sender, RoutedEventArgs e)
+ private void OnAcceptButtonClicked(object? sender, RoutedEventArgs e)
{
Date = _syncDate;
OnConfirmed();
}
- private void OnSelectorButtonClick(object sender, RoutedEventArgs e)
+ private void OnSelectorButtonClick(object? sender, RoutedEventArgs e)
{
if (sender == _monthUpButton)
- _monthSelector.ScrollUp();
+ _monthSelector!.ScrollUp();
else if (sender == _monthDownButton)
- _monthSelector.ScrollDown();
+ _monthSelector!.ScrollDown();
else if (sender == _yearUpButton)
- _yearSelector.ScrollUp();
+ _yearSelector!.ScrollUp();
else if (sender == _yearDownButton)
- _yearSelector.ScrollDown();
+ _yearSelector!.ScrollDown();
else if (sender == _dayUpButton)
- _daySelector.ScrollUp();
+ _daySelector!.ScrollUp();
else if (sender == _dayDownButton)
- _daySelector.ScrollDown();
+ _daySelector!.ScrollDown();
}
- private void OnYearChanged(object sender, EventArgs e)
+ private void OnYearChanged(object? sender, EventArgs e)
{
if (_suppressUpdateSelection)
return;
- int maxDays = _calendar.GetDaysInMonth(_yearSelector.SelectedValue, _syncDate.Month);
+ int maxDays = _calendar.GetDaysInMonth(_yearSelector!.SelectedValue, _syncDate.Month);
var newDate = new DateTimeOffset(_yearSelector.SelectedValue, _syncDate.Month,
_syncDate.Day > maxDays ? maxDays : _syncDate.Day, 0, 0, 0, _syncDate.Offset);
@@ -487,7 +490,7 @@ namespace Avalonia.Controls
_suppressUpdateSelection = true;
- _daySelector.FormatDate = newDate.Date;
+ _daySelector!.FormatDate = newDate.Date;
if (_daySelector.MaximumValue != maxDays)
_daySelector.MaximumValue = maxDays;
@@ -497,19 +500,19 @@ namespace Avalonia.Controls
_suppressUpdateSelection = false;
}
- private void OnDayChanged(object sender, EventArgs e)
+ private void OnDayChanged(object? sender, EventArgs e)
{
if (_suppressUpdateSelection)
return;
- _syncDate = new DateTimeOffset(_syncDate.Year, _syncDate.Month, _daySelector.SelectedValue, 0, 0, 0, _syncDate.Offset);
+ _syncDate = new DateTimeOffset(_syncDate.Year, _syncDate.Month, _daySelector!.SelectedValue, 0, 0, 0, _syncDate.Offset);
}
- private void OnMonthChanged(object sender, EventArgs e)
+ private void OnMonthChanged(object? sender, EventArgs e)
{
if (_suppressUpdateSelection)
return;
- int maxDays = _calendar.GetDaysInMonth(_syncDate.Year, _monthSelector.SelectedValue);
+ int maxDays = _calendar.GetDaysInMonth(_syncDate.Year, _monthSelector!.SelectedValue);
var newDate = new DateTimeOffset(_syncDate.Year, _monthSelector.SelectedValue,
_syncDate.Day > maxDays ? maxDays : _syncDate.Day, 0, 0, 0, _syncDate.Offset);
@@ -521,7 +524,7 @@ namespace Avalonia.Controls
_suppressUpdateSelection = true;
- _daySelector.FormatDate = newDate.Date;
+ _daySelector!.FormatDate = newDate.Date;
_syncDate = newDate;
if (_daySelector.MaximumValue != maxDays)
@@ -535,7 +538,7 @@ namespace Avalonia.Controls
internal double GetOffsetForPopup()
{
var acceptDismissButtonHeight = _acceptButton != null ? _acceptButton.Bounds.Height : 41;
- return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_monthSelector.ItemHeight / 2);
+ return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_monthSelector!.ItemHeight / 2);
}
}
}
diff --git a/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs b/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
index e16e609a15..10b7f9bdf9 100644
--- a/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
@@ -58,7 +58,7 @@ namespace Avalonia.Controls.Primitives
private Vector _offset;
private bool _hasInit;
private bool _suppressUpdateOffset;
- private ListBoxItem _pressedItem;
+ private ListBoxItem? _pressedItem;
public DateTimePickerPanel()
{
@@ -271,9 +271,9 @@ namespace Avalonia.Controls.Primitives
public Size Viewport => new Size(0, ItemHeight);
- public event EventHandler ScrollInvalidated;
+ public event EventHandler? ScrollInvalidated;
- public event EventHandler SelectionChanged;
+ public event EventHandler? SelectionChanged;
protected override Size MeasureOverride(Size availableSize)
{
@@ -523,40 +523,44 @@ namespace Avalonia.Controls.Primitives
return newValue;
}
- private void OnItemPointerDown(object sender, PointerPressedEventArgs e)
+ private void OnItemPointerDown(object? sender, PointerPressedEventArgs e)
{
- if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
+ if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed &&
+ e.Source is IVisual source)
{
- _pressedItem = GetItemFromSource((IVisual)e.Source);
+ _pressedItem = GetItemFromSource(source);
e.Handled = true;
}
}
- private void OnItemPointerUp(object sender, PointerReleasedEventArgs e)
+ private void OnItemPointerUp(object? sender, PointerReleasedEventArgs e)
{
if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonReleased &&
- _pressedItem != null)
+ _pressedItem != null &&
+ e.Source is IVisual source &&
+ GetItemFromSource(source) is ListBoxItem item &&
+ item.Tag is int tag)
{
- SelectedValue = (int)GetItemFromSource((IVisual)e.Source).Tag;
+ SelectedValue = tag;
_pressedItem = null;
e.Handled = true;
}
}
//Helper to get ListBoxItem from pointerevent source
- private ListBoxItem GetItemFromSource(IVisual src)
+ private ListBoxItem? GetItemFromSource(IVisual src)
{
var item = src;
while (item != null && !(item is ListBoxItem))
{
item = item.VisualParent;
}
- return (ListBoxItem)item;
+ return (ListBoxItem?)item;
}
public bool BringIntoView(IControl target, Rect targetRect) { return false; }
- public IControl GetControlInDirection(NavigationDirection direction, IControl from) { return null; }
+ public IControl? GetControlInDirection(NavigationDirection direction, IControl from) { return null; }
public void RaiseScrollInvalidated(EventArgs e)
{
diff --git a/src/Avalonia.Controls/DateTimePickers/PickerPresenterBase.cs b/src/Avalonia.Controls/DateTimePickers/PickerPresenterBase.cs
index 639b187ad8..629b1a1766 100644
--- a/src/Avalonia.Controls/DateTimePickers/PickerPresenterBase.cs
+++ b/src/Avalonia.Controls/DateTimePickers/PickerPresenterBase.cs
@@ -16,10 +16,10 @@ namespace Avalonia.Controls.Primitives
protected virtual void OnDismiss()
{
- Dismissed.Invoke(this, EventArgs.Empty);
+ Dismissed?.Invoke(this, EventArgs.Empty);
}
- public event EventHandler Confirmed;
- public event EventHandler Dismissed;
+ public event EventHandler? Confirmed;
+ public event EventHandler? Dismissed;
}
}
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
index 6b3f66912f..a0a27bd4ed 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
@@ -49,18 +49,18 @@ namespace Avalonia.Controls
defaultBindingMode: BindingMode.TwoWay);
// Template Items
- private TimePickerPresenter _presenter;
- private Button _flyoutButton;
- private Border _firstPickerHost;
- private Border _secondPickerHost;
- private Border _thirdPickerHost;
- private TextBlock _hourText;
- private TextBlock _minuteText;
- private TextBlock _periodText;
- private Rectangle _firstSplitter;
- private Rectangle _secondSplitter;
- private Grid _contentGrid;
- private Popup _popup;
+ private TimePickerPresenter? _presenter;
+ private Button? _flyoutButton;
+ private Border? _firstPickerHost;
+ private Border? _secondPickerHost;
+ private Border? _thirdPickerHost;
+ private TextBlock? _hourText;
+ private TextBlock? _minuteText;
+ private TextBlock? _periodText;
+ private Rectangle? _firstSplitter;
+ private Rectangle? _secondSplitter;
+ private Grid? _contentGrid;
+ private Popup? _popup;
private TimeSpan? _selectedTime;
private int _minuteIncrement = 1;
@@ -142,7 +142,7 @@ namespace Avalonia.Controls
///
/// Raised when the property changes
///
- public event EventHandler SelectedTimeChanged;
+ public event EventHandler? SelectedTimeChanged;
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
@@ -200,15 +200,15 @@ namespace Avalonia.Controls
var columnsD = use24HourClock ? "*, Auto, *" : "*, Auto, *, Auto, *";
_contentGrid.ColumnDefinitions = new ColumnDefinitions(columnsD);
- _thirdPickerHost.IsVisible = !use24HourClock;
- _secondSplitter.IsVisible = !use24HourClock;
+ _thirdPickerHost!.IsVisible = !use24HourClock;
+ _secondSplitter!.IsVisible = !use24HourClock;
- Grid.SetColumn(_firstPickerHost, 0);
- Grid.SetColumn(_secondPickerHost, 2);
+ Grid.SetColumn(_firstPickerHost!, 0);
+ Grid.SetColumn(_secondPickerHost!, 2);
Grid.SetColumn(_thirdPickerHost, use24HourClock ? 0 : 4);
- Grid.SetColumn(_firstSplitter, 1);
+ Grid.SetColumn(_firstSplitter!, 1);
Grid.SetColumn(_secondSplitter, use24HourClock ? 0 : 3);
}
@@ -220,7 +220,7 @@ namespace Avalonia.Controls
var time = SelectedTime;
if (time.HasValue)
{
- var newTime = SelectedTime.Value;
+ var newTime = SelectedTime!.Value;
if (ClockIdentifier == "12HourClock")
{
@@ -252,30 +252,30 @@ namespace Avalonia.Controls
SelectedTimeChanged?.Invoke(this, new TimePickerSelectedValueChangedEventArgs(oldTime, newTime));
}
- private void OnFlyoutButtonClicked(object sender, Interactivity.RoutedEventArgs e)
+ private void OnFlyoutButtonClicked(object? sender, Interactivity.RoutedEventArgs e)
{
- _presenter.Time = SelectedTime ?? DateTime.Now.TimeOfDay;
+ _presenter!.Time = SelectedTime ?? DateTime.Now.TimeOfDay;
- _popup.IsOpen = true;
+ _popup!.IsOpen = true;
var deltaY = _presenter.GetOffsetForPopup();
// The extra 5 px I think is related to default popup placement behavior
- _popup.Host.ConfigurePosition(_popup.PlacementTarget, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
+ _popup.Host!.ConfigurePosition(_popup.PlacementTarget!, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom,
Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY);
}
- private void OnDismissPicker(object sender, EventArgs e)
+ private void OnDismissPicker(object? sender, EventArgs e)
{
- _popup.Close();
+ _popup!.Close();
Focus();
}
- private void OnConfirmed(object sender, EventArgs e)
+ private void OnConfirmed(object? sender, EventArgs e)
{
- _popup.Close();
- SelectedTime = _presenter.Time;
+ _popup!.Close();
+ SelectedTime = _presenter!.Time;
}
}
}
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs b/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
index 920eeeb406..55bc1af3a7 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
@@ -40,20 +40,20 @@ namespace Avalonia.Controls
}
// TemplateItems
- private Grid _pickerContainer;
- private Button _acceptButton;
- private Button _dismissButton;
- private Rectangle _spacer2;
- private Panel _periodHost;
- private DateTimePickerPanel _hourSelector;
- private DateTimePickerPanel _minuteSelector;
- private DateTimePickerPanel _periodSelector;
- private Button _hourUpButton;
- private Button _minuteUpButton;
- private Button _periodUpButton;
- private Button _hourDownButton;
- private Button _minuteDownButton;
- private Button _periodDownButton;
+ private Grid? _pickerContainer;
+ private Button? _acceptButton;
+ private Button? _dismissButton;
+ private Rectangle? _spacer2;
+ private Panel? _periodHost;
+ private DateTimePickerPanel? _hourSelector;
+ private DateTimePickerPanel? _minuteSelector;
+ private DateTimePickerPanel? _periodSelector;
+ private Button? _hourUpButton;
+ private Button? _minuteUpButton;
+ private Button? _periodUpButton;
+ private Button? _hourDownButton;
+ private Button? _minuteDownButton;
+ private Button? _periodDownButton;
// Backing Fields
private TimeSpan _time;
@@ -156,9 +156,12 @@ namespace Avalonia.Controls
e.Handled = true;
break;
case Key.Tab:
- var nextFocus = KeyboardNavigationHandler.GetNext(FocusManager.Instance.Current, NavigationDirection.Next);
- KeyboardDevice.Instance?.SetFocusedElement(nextFocus, NavigationMethod.Tab, KeyModifiers.None);
- e.Handled = true;
+ if (FocusManager.Instance?.Current is IInputElement focus)
+ {
+ var nextFocus = KeyboardNavigationHandler.GetNext(focus, NavigationDirection.Next);
+ KeyboardDevice.Instance?.SetFocusedElement(nextFocus, NavigationMethod.Tab, KeyModifiers.None);
+ e.Handled = true;
+ }
break;
case Key.Enter:
OnConfirmed();
@@ -170,9 +173,9 @@ namespace Avalonia.Controls
protected override void OnConfirmed()
{
- var hr = _hourSelector.SelectedValue;
- var min = _minuteSelector.SelectedValue;
- var per = _periodSelector.SelectedValue;
+ var hr = _hourSelector!.SelectedValue;
+ var min = _minuteSelector!.SelectedValue;
+ var per = _periodSelector!.SelectedValue;
if (ClockIdentifier == "12HourClock")
{
@@ -190,20 +193,20 @@ namespace Avalonia.Controls
return;
bool clock12 = ClockIdentifier == "12HourClock";
- _hourSelector.MaximumValue = clock12 ? 12 : 23;
+ _hourSelector!.MaximumValue = clock12 ? 12 : 23;
_hourSelector.MinimumValue = clock12 ? 1 : 0;
_hourSelector.ItemFormat = "%h";
var hr = Time.Hours;
_hourSelector.SelectedValue = !clock12 ? hr :
hr > 12 ? hr - 12 : hr == 0 ? 12 : hr;
- _minuteSelector.MaximumValue = 59;
+ _minuteSelector!.MaximumValue = 59;
_minuteSelector.MinimumValue = 0;
_minuteSelector.Increment = MinuteIncrement;
_minuteSelector.SelectedValue = Time.Minutes;
_minuteSelector.ItemFormat = "mm";
- _periodSelector.MaximumValue = 1;
+ _periodSelector!.MaximumValue = 1;
_periodSelector.MinimumValue = 0;
_periodSelector.SelectedValue = hr >= 12 ? 1 : 0;
@@ -216,45 +219,45 @@ namespace Avalonia.Controls
bool use24HourClock = ClockIdentifier == "24HourClock";
var columnsD = use24HourClock ? "*, Auto, *" : "*, Auto, *, Auto, *";
- _pickerContainer.ColumnDefinitions = new ColumnDefinitions(columnsD);
+ _pickerContainer!.ColumnDefinitions = new ColumnDefinitions(columnsD);
- _spacer2.IsVisible = !use24HourClock;
- _periodHost.IsVisible = !use24HourClock;
+ _spacer2!.IsVisible = !use24HourClock;
+ _periodHost!.IsVisible = !use24HourClock;
Grid.SetColumn(_spacer2, use24HourClock ? 0 : 3);
Grid.SetColumn(_periodHost, use24HourClock ? 0 : 4);
}
- private void OnDismissButtonClicked(object sender, RoutedEventArgs e)
+ private void OnDismissButtonClicked(object? sender, RoutedEventArgs e)
{
OnDismiss();
}
- private void OnAcceptButtonClicked(object sender, RoutedEventArgs e)
+ private void OnAcceptButtonClicked(object? sender, RoutedEventArgs e)
{
OnConfirmed();
}
- private void OnSelectorButtonClick(object sender, RoutedEventArgs e)
+ private void OnSelectorButtonClick(object? sender, RoutedEventArgs e)
{
if (sender == _hourUpButton)
- _hourSelector.ScrollUp();
+ _hourSelector!.ScrollUp();
else if (sender == _hourDownButton)
- _hourSelector.ScrollDown();
+ _hourSelector!.ScrollDown();
else if (sender == _minuteUpButton)
- _minuteSelector.ScrollUp();
+ _minuteSelector!.ScrollUp();
else if (sender == _minuteDownButton)
- _minuteSelector.ScrollDown();
+ _minuteSelector!.ScrollDown();
else if (sender == _periodUpButton)
- _periodSelector.ScrollUp();
+ _periodSelector!.ScrollUp();
else if (sender == _periodDownButton)
- _periodSelector.ScrollDown();
+ _periodSelector!.ScrollDown();
}
internal double GetOffsetForPopup()
{
var acceptDismissButtonHeight = _acceptButton != null ? _acceptButton.Bounds.Height : 41;
- return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_hourSelector.ItemHeight / 2);
+ return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_hourSelector!.ItemHeight / 2);
}
}
}
diff --git a/src/Avalonia.Controls/Decorator.cs b/src/Avalonia.Controls/Decorator.cs
index 8959f0e306..bd866ee8d8 100644
--- a/src/Avalonia.Controls/Decorator.cs
+++ b/src/Avalonia.Controls/Decorator.cs
@@ -11,8 +11,8 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty ChildProperty =
- AvaloniaProperty.Register(nameof(Child));
+ public static readonly StyledProperty ChildProperty =
+ AvaloniaProperty.Register(nameof(Child));
///
/// Defines the property.
@@ -33,7 +33,7 @@ namespace Avalonia.Controls
/// Gets or sets the decorated control.
///
[Content]
- public IControl Child
+ public IControl? Child
{
get { return GetValue(ChildProperty); }
set { SetValue(ChildProperty, value); }
@@ -66,8 +66,8 @@ namespace Avalonia.Controls
/// The event args.
private void ChildChanged(AvaloniaPropertyChangedEventArgs e)
{
- var oldChild = (Control)e.OldValue;
- var newChild = (Control)e.NewValue;
+ var oldChild = (Control?)e.OldValue;
+ var newChild = (Control?)e.NewValue;
if (oldChild != null)
{
diff --git a/src/Avalonia.Controls/DefinitionBase.cs b/src/Avalonia.Controls/DefinitionBase.cs
index 37b8691ce9..eb09ff397a 100644
--- a/src/Avalonia.Controls/DefinitionBase.cs
+++ b/src/Avalonia.Controls/DefinitionBase.cs
@@ -39,7 +39,7 @@ namespace Avalonia.Controls
string sharedSizeGroupId = SharedSizeGroup;
if (sharedSizeGroupId != null)
{
- SharedSizeScope privateSharedSizeScope = PrivateSharedSizeScope;
+ SharedSizeScope? privateSharedSizeScope = PrivateSharedSizeScope;
if (privateSharedSizeScope != null)
{
_sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId);
@@ -104,7 +104,7 @@ namespace Avalonia.Controls
///
internal static void OnIsSharedSizeScopePropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
{
- if ((bool)e.NewValue)
+ if ((bool)e.NewValue!)
{
SharedSizeScope sharedStatesCollection = new SharedSizeScope();
d.SetValue(PrivateSharedSizeScopeProperty, sharedStatesCollection);
@@ -131,8 +131,8 @@ namespace Avalonia.Controls
}
else
{
- GridUnitType oldUnitType = ((GridLength)e.OldValue).GridUnitType;
- GridUnitType newUnitType = ((GridLength)e.NewValue).GridUnitType;
+ GridUnitType oldUnitType = ((GridLength)e.OldValue!).GridUnitType;
+ GridUnitType newUnitType = ((GridLength)e.NewValue!).GridUnitType;
if (oldUnitType != newUnitType)
{
@@ -300,7 +300,7 @@ namespace Avalonia.Controls
///
internal abstract double UserMaxSizeValueCache { get; }
- internal Grid Parent { get; set; }
+ internal Grid? Parent { get; set; }
///
/// SetFlags is used to set or unset one or multiple
@@ -326,7 +326,7 @@ namespace Avalonia.Controls
if (definition.Parent != null)
{
- string sharedSizeGroupId = (string)e.NewValue;
+ string sharedSizeGroupId = (string)e.NewValue!;
if (definition._sharedState != null)
{
@@ -338,7 +338,7 @@ namespace Avalonia.Controls
if ((definition._sharedState == null) && (sharedSizeGroupId != null))
{
- SharedSizeScope privateSharedSizeScope = definition.PrivateSharedSizeScope;
+ SharedSizeScope? privateSharedSizeScope = definition.PrivateSharedSizeScope;
if (privateSharedSizeScope != null)
{
// if definition is not registered and both: shared size group id AND private shared scope
@@ -402,7 +402,7 @@ namespace Avalonia.Controls
if (definition.Parent != null)
{
- SharedSizeScope privateSharedSizeScope = (SharedSizeScope)e.NewValue;
+ SharedSizeScope privateSharedSizeScope = (SharedSizeScope)e.NewValue!;
if (definition._sharedState != null)
{
@@ -429,9 +429,9 @@ namespace Avalonia.Controls
///
/// Private getter of shared state collection dynamic property.
///
- private SharedSizeScope PrivateSharedSizeScope
+ private SharedSizeScope? PrivateSharedSizeScope
{
- get { return (SharedSizeScope)GetValue(PrivateSharedSizeScopeProperty); }
+ get { return (SharedSizeScope?)GetValue(PrivateSharedSizeScopeProperty); }
}
///
@@ -462,7 +462,7 @@ namespace Avalonia.Controls
private double _sizeCache; // cache used for various purposes (sorting, caching, etc) during calculations
private double _offset; // offset of the DefinitionBase from left / top corner (assuming LTR case)
- private SharedSizeState _sharedState; // reference to shared state object this instance is registered with
+ private SharedSizeState? _sharedState; // reference to shared state object this instance is registered with
[System.Flags]
private enum Flags : byte
@@ -488,7 +488,7 @@ namespace Avalonia.Controls
// check that sharedSizeGroup is not default
Debug.Assert(sharedSizeGroup != null);
- SharedSizeState sharedState = _registry[sharedSizeGroup] as SharedSizeState;
+ SharedSizeState? sharedState = _registry[sharedSizeGroup] as SharedSizeState;
if (sharedState == null)
{
sharedState = new SharedSizeState(this, sharedSizeGroup);
@@ -567,7 +567,7 @@ namespace Avalonia.Controls
{
for (int i = 0, count = _registry.Count; i < count; ++i)
{
- Grid parentGrid = (Grid)(_registry[i].Parent);
+ Grid parentGrid = (Grid)(_registry[i].Parent!);
parentGrid.Invalidate();
}
_broadcastInvalidation = false;
@@ -645,7 +645,7 @@ namespace Avalonia.Controls
/// OnLayoutUpdated handler. Validates that all participating definitions
/// have updated min size value. Forces another layout update cycle if needed.
///
- private void OnLayoutUpdated(object sender, EventArgs e)
+ private void OnLayoutUpdated(object? sender, EventArgs e)
{
double sharedMinSize = 0;
@@ -707,14 +707,14 @@ namespace Avalonia.Controls
if(!measureIsValid)
{
- definitionBase.Parent.InvalidateMeasure();
+ definitionBase.Parent!.InvalidateMeasure();
}
else if (!MathUtilities.AreClose(sharedMinSize, definitionBase.SizeCache))
{
// if measure is valid then also need to check arrange.
// Note: definitionBase.SizeCache is volatile but at this point
// it contains up-to-date final size
- definitionBase.Parent.InvalidateArrange();
+ definitionBase.Parent!.InvalidateArrange();
}
// now we can restore the invariant, and clear the layout flag
@@ -724,7 +724,7 @@ namespace Avalonia.Controls
_minSize = sharedMinSize;
- _layoutUpdatedHost.LayoutUpdated -= _layoutUpdated;
+ _layoutUpdatedHost!.LayoutUpdated -= _layoutUpdated;
_layoutUpdatedHost = null;
_broadcastInvalidation = true;
@@ -743,7 +743,7 @@ namespace Avalonia.Controls
private readonly EventHandler _layoutUpdated;
// Control for which layout updated event handler is registered
- private Control _layoutUpdatedHost;
+ private Control? _layoutUpdatedHost;
// "true" when broadcasting of invalidation is needed
private bool _broadcastInvalidation;
@@ -762,8 +762,8 @@ namespace Avalonia.Controls
/// Private shared size scope property holds a collection of shared state objects for the a given shared size scope.
///
///
- internal static readonly AttachedProperty PrivateSharedSizeScopeProperty =
- AvaloniaProperty.RegisterAttached(
+ internal static readonly AttachedProperty PrivateSharedSizeScopeProperty =
+ AvaloniaProperty.RegisterAttached(
"PrivateSharedSizeScope",
defaultValue: null,
inherits: true);
diff --git a/src/Avalonia.Controls/DefinitionList.cs b/src/Avalonia.Controls/DefinitionList.cs
index ad0e2513c4..c850647bf4 100644
--- a/src/Avalonia.Controls/DefinitionList.cs
+++ b/src/Avalonia.Controls/DefinitionList.cs
@@ -2,8 +2,6 @@ using System.Collections;
using System.Collections.Specialized;
using Avalonia.Collections;
-#nullable enable
-
namespace Avalonia.Controls
{
public abstract class DefinitionList : AvaloniaList where T : DefinitionBase
@@ -36,7 +34,7 @@ namespace Avalonia.Controls
}
}
- internal void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ internal void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
var idx = 0;
@@ -62,7 +60,7 @@ namespace Avalonia.Controls
for (var i = 0; i < count; i++)
{
- var definition = (DefinitionBase) items[i];
+ var definition = (DefinitionBase) items[i]!;
if (wasRemoved)
{
diff --git a/src/Avalonia.Controls/Diagnostics/IPopupHostProvider.cs b/src/Avalonia.Controls/Diagnostics/IPopupHostProvider.cs
index 11d3b1792a..45cd1d727e 100644
--- a/src/Avalonia.Controls/Diagnostics/IPopupHostProvider.cs
+++ b/src/Avalonia.Controls/Diagnostics/IPopupHostProvider.cs
@@ -1,8 +1,6 @@
using System;
using Avalonia.Controls.Primitives;
-#nullable enable
-
namespace Avalonia.Controls.Diagnostics
{
///
diff --git a/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs b/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs
index 4acf2a217f..9fddb91231 100644
--- a/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs
+++ b/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs
@@ -1,6 +1,4 @@
-#nullable enable
-
-namespace Avalonia.Controls.Diagnostics
+namespace Avalonia.Controls.Diagnostics
{
///
/// Helper class to provide diagnostics information for .
diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
index e2afbd3bdc..08d559a5c1 100644
--- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
+++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
@@ -12,7 +12,7 @@ namespace Avalonia.Controls.Embedding.Offscreen
private double _scaling = 1;
private Size _clientSize;
- public IInputRoot InputRoot { get; private set; }
+ public IInputRoot? InputRoot { get; private set; }
public bool IsDisposed { get; private set; }
public virtual void Dispose()
@@ -47,12 +47,12 @@ namespace Avalonia.Controls.Embedding.Offscreen
}
}
- public Action Input { get; set; }
- public Action Paint { get; set; }
- public Action Resized { get; set; }
- public Action ScalingChanged { get; set; }
+ public Action? Input { get; set; }
+ public Action? Paint { get; set; }
+ public Action? Resized { get; set; }
+ public Action? ScalingChanged { get; set; }
- public Action TransparencyLevelChanged { get; set; }
+ public Action? TransparencyLevelChanged { get; set; }
///
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1);
@@ -63,18 +63,18 @@ namespace Avalonia.Controls.Embedding.Offscreen
public virtual PixelPoint PointToScreen(Point point) => PixelPoint.FromPoint(point, 1);
- public virtual void SetCursor(ICursorImpl cursor)
+ public virtual void SetCursor(ICursorImpl? cursor)
{
}
- public Action Closed { get; set; }
- public Action LostFocus { get; set; }
+ public Action? Closed { get; set; }
+ public Action? LostFocus { get; set; }
public abstract IMouseDevice MouseDevice { get; }
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { }
public WindowTransparencyLevel TransparencyLevel { get; private set; }
- public IPopupImpl CreatePopup() => null;
+ public IPopupImpl? CreatePopup() => null;
}
}
diff --git a/src/Avalonia.Controls/Expander.cs b/src/Avalonia.Controls/Expander.cs
index b9c79e5749..020b162864 100644
--- a/src/Avalonia.Controls/Expander.cs
+++ b/src/Avalonia.Controls/Expander.cs
@@ -1,11 +1,8 @@
using System.Threading;
-
using Avalonia.Animation;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs b/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs
index 57861163d6..30bdb4c60e 100644
--- a/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs
+++ b/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs
@@ -17,7 +17,7 @@ namespace Avalonia.Controls
private readonly BorderRenderHelper _borderRenderHelper = new BorderRenderHelper();
- private IDisposable _subscription;
+ private IDisposable? _subscription;
static ExperimentalAcrylicBorder()
{
@@ -46,11 +46,14 @@ namespace Avalonia.Controls
{
base.OnAttachedToVisualTree(e);
- var tl = (e.Root as TopLevel);
+ var tl = (TopLevel)e.Root;
_subscription = tl.GetObservable(TopLevel.ActualTransparencyLevelProperty)
.Subscribe(x =>
{
+ if (tl.PlatformImpl is null)
+ return;
+
switch (x)
{
case WindowTransparencyLevel.Transparent:
diff --git a/src/Avalonia.Controls/Flyouts/Flyout.cs b/src/Avalonia.Controls/Flyouts/Flyout.cs
index 974f1418b2..df3fe28a29 100644
--- a/src/Avalonia.Controls/Flyouts/Flyout.cs
+++ b/src/Avalonia.Controls/Flyouts/Flyout.cs
@@ -1,8 +1,6 @@
using Avalonia.Controls.Primitives;
using Avalonia.Metadata;
-#nullable enable
-
namespace Avalonia.Controls
{
public class Flyout : FlyoutBase
diff --git a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs
index a08b82f512..d024f86b32 100644
--- a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs
+++ b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs
@@ -8,8 +8,6 @@ using Avalonia.Input.Raw;
using Avalonia.Layout;
using Avalonia.Logging;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
public abstract class FlyoutBase : AvaloniaObject, IPopupHostProvider
@@ -267,7 +265,7 @@ namespace Avalonia.Controls.Primitives
return true;
}
- private void PlacementTarget_DetachedFromVisualTree(object sender, VisualTreeAttachmentEventArgs e)
+ private void PlacementTarget_DetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
_ = HideCore(false);
}
@@ -335,7 +333,7 @@ namespace Avalonia.Controls.Primitives
protected virtual void OnOpened()
{
- Opened?.Invoke(this, null);
+ Opened?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnClosing(CancelEventArgs args)
@@ -345,7 +343,7 @@ namespace Avalonia.Controls.Primitives
protected virtual void OnClosed()
{
- Closed?.Invoke(this, null);
+ Closed?.Invoke(this, EventArgs.Empty);
}
///
@@ -368,14 +366,14 @@ namespace Avalonia.Controls.Primitives
return popup;
}
- private void OnPopupOpened(object sender, EventArgs e)
+ private void OnPopupOpened(object? sender, EventArgs e)
{
IsOpen = true;
_popupHostChangedHandler?.Invoke(Popup!.Host);
}
- private void OnPopupClosing(object sender, CancelEventArgs e)
+ private void OnPopupClosing(object? sender, CancelEventArgs e)
{
if (IsOpen)
{
@@ -383,7 +381,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void OnPopupClosed(object sender, EventArgs e)
+ private void OnPopupClosed(object? sender, EventArgs e)
{
HideCore(false);
@@ -391,7 +389,7 @@ namespace Avalonia.Controls.Primitives
}
// This method is handling both popup logical tree and target logical tree.
- private void OnPlacementTargetOrPopupKeyUp(object sender, KeyEventArgs e)
+ private void OnPlacementTargetOrPopupKeyUp(object? sender, KeyEventArgs e)
{
if (!e.Handled
&& IsOpen
@@ -530,10 +528,10 @@ namespace Avalonia.Controls.Primitives
}
}
- private static void OnControlContextRequested(object sender, ContextRequestedEventArgs e)
+ private static void OnControlContextRequested(object? sender, ContextRequestedEventArgs e)
{
- var control = (Control)sender;
if (!e.Handled
+ && sender is Control control
&& control.ContextFlyout is FlyoutBase flyout)
{
if (control.ContextMenu != null)
diff --git a/src/Avalonia.Controls/Flyouts/MenuFlyout.cs b/src/Avalonia.Controls/Flyouts/MenuFlyout.cs
index 5b2e323f4f..97fda68051 100644
--- a/src/Avalonia.Controls/Flyouts/MenuFlyout.cs
+++ b/src/Avalonia.Controls/Flyouts/MenuFlyout.cs
@@ -4,8 +4,6 @@ using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Metadata;
-#nullable enable
-
namespace Avalonia.Controls
{
public class MenuFlyout : FlyoutBase
@@ -18,7 +16,7 @@ namespace Avalonia.Controls
///
/// Defines the property
///
- public static readonly DirectProperty ItemsProperty =
+ public static readonly DirectProperty ItemsProperty =
ItemsControl.ItemsProperty.AddOwner(x => x.Items,
(x, v) => x.Items = v);
@@ -35,7 +33,7 @@ namespace Avalonia.Controls
/// Gets or sets the items of the MenuFlyout
///
[Content]
- public IEnumerable Items
+ public IEnumerable? Items
{
get => _items;
set => SetAndRaise(ItemsProperty, ref _items, value);
@@ -51,7 +49,7 @@ namespace Avalonia.Controls
}
private Classes? _classes;
- private IEnumerable _items;
+ private IEnumerable? _items;
private IDataTemplate? _itemTemplate;
protected override Control CreatePresenter()
diff --git a/src/Avalonia.Controls/Flyouts/MenuFlyoutPresenter.cs b/src/Avalonia.Controls/Flyouts/MenuFlyoutPresenter.cs
index 3a45c85c70..bcd859100a 100644
--- a/src/Avalonia.Controls/Flyouts/MenuFlyoutPresenter.cs
+++ b/src/Avalonia.Controls/Flyouts/MenuFlyoutPresenter.cs
@@ -43,5 +43,18 @@ namespace Avalonia.Controls
{
return new MenuItemContainerGenerator(this);
}
+
+ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnDetachedFromVisualTree(e);
+
+ foreach (var i in LogicalChildren)
+ {
+ if (i is MenuItem menuItem)
+ {
+ menuItem.IsSubMenuOpen = false;
+ }
+ }
+ }
}
}
diff --git a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
index 6220a20a82..dd4c6561c2 100644
--- a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
@@ -17,27 +17,27 @@ namespace Avalonia.Controls.Generators
///
/// Gets or sets the data template used to display the items in the control.
///
- IDataTemplate ItemTemplate { get; set; }
+ IDataTemplate? ItemTemplate { get; set; }
///
/// Gets the ContainerType, or null if its an untyped ContainerGenerator.
///
- Type ContainerType { get; }
+ Type? ContainerType { get; }
///
/// Signaled whenever new containers are materialized.
///
- event EventHandler Materialized;
+ event EventHandler? Materialized;
///
/// Event raised whenever containers are dematerialized.
///
- event EventHandler Dematerialized;
+ event EventHandler? Dematerialized;
///
/// Event raised whenever containers are recycled.
///
- event EventHandler Recycled;
+ event EventHandler? Recycled;
///
/// Creates a container control for an item.
@@ -90,7 +90,7 @@ namespace Avalonia.Controls.Generators
///
/// The index.
/// The container, or null if no container created.
- IControl ContainerFromIndex(int index);
+ IControl? ContainerFromIndex(int index);
///
/// Gets the index of the specified container control.
diff --git a/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs
index 335e0df5f7..f15987fe79 100644
--- a/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs
@@ -8,7 +8,7 @@ namespace Avalonia.Controls.Generators
///
/// Gets the container index for the tree.
///
- TreeContainerIndex Index { get; }
+ TreeContainerIndex? Index { get; }
///
/// Updates the index based on the parent .
diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
index f16834f6e1..d02eaffeb2 100644
--- a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
@@ -20,27 +20,25 @@ namespace Avalonia.Controls.Generators
/// The owner control.
public ItemContainerGenerator(IControl owner)
{
- Contract.Requires(owner != null);
-
- Owner = owner;
+ Owner = owner ?? throw new ArgumentNullException(nameof(owner));
}
///
public IEnumerable Containers => _containers.Values;
///
- public event EventHandler Materialized;
+ public event EventHandler? Materialized;
///
- public event EventHandler Dematerialized;
+ public event EventHandler? Dematerialized;
///
- public event EventHandler Recycled;
+ public event EventHandler? Recycled;
///
/// Gets or sets the data template used to display the items in the control.
///
- public IDataTemplate ItemTemplate { get; set; }
+ public IDataTemplate? ItemTemplate { get; set; }
///
/// Gets the owner control.
@@ -48,12 +46,12 @@ namespace Avalonia.Controls.Generators
public IControl Owner { get; }
///
- public virtual Type ContainerType => null;
+ public virtual Type? ContainerType => null;
///
public ItemContainerInfo Materialize(int index, object item)
{
- var container = new ItemContainerInfo(CreateContainer(item), item, index);
+ var container = new ItemContainerInfo(CreateContainer(item)!, item, index);
_containers.Add(container.Index, container);
Materialized?.Invoke(this, new ItemContainerEventArgs(container));
@@ -104,9 +102,7 @@ namespace Avalonia.Controls.Generators
{
for (var i = startingIndex; i < startingIndex + count; ++i)
{
- ItemContainerInfo found;
-
- if (_containers.TryGetValue(i, out found))
+ if (_containers.TryGetValue(i, out var found))
{
result.Add(found);
}
@@ -154,9 +150,9 @@ namespace Avalonia.Controls.Generators
}
///
- public IControl ContainerFromIndex(int index)
+ public IControl? ContainerFromIndex(int index)
{
- ItemContainerInfo result;
+ ItemContainerInfo? result;
_containers.TryGetValue(index, out result);
return result?.ContainerControl;
}
@@ -180,7 +176,7 @@ namespace Avalonia.Controls.Generators
///
/// The item.
/// The created container control.
- protected virtual IControl CreateContainer(object item)
+ protected virtual IControl? CreateContainer(object item)
{
var result = item as IControl;
diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
index d1fbb25cb1..635f3a7d37 100644
--- a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
+++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
@@ -19,13 +19,10 @@ namespace Avalonia.Controls.Generators
public ItemContainerGenerator(
IControl owner,
AvaloniaProperty contentProperty,
- AvaloniaProperty contentTemplateProperty)
+ AvaloniaProperty? contentTemplateProperty)
: base(owner)
{
- Contract.Requires(owner != null);
- Contract.Requires(contentProperty != null);
-
- ContentProperty = contentProperty;
+ ContentProperty = contentProperty ?? throw new ArgumentNullException(nameof(contentProperty));
ContentTemplateProperty = contentTemplateProperty;
}
@@ -40,10 +37,10 @@ namespace Avalonia.Controls.Generators
///
/// Gets the container's ContentTemplate property.
///
- protected AvaloniaProperty ContentTemplateProperty { get; }
+ protected AvaloniaProperty? ContentTemplateProperty { get; }
///
- protected override IControl CreateContainer(object item)
+ protected override IControl? CreateContainer(object item)
{
var container = item as T;
diff --git a/src/Avalonia.Controls/Generators/MenuItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/MenuItemContainerGenerator.cs
index d3cf70e0f8..bfcb474515 100644
--- a/src/Avalonia.Controls/Generators/MenuItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/MenuItemContainerGenerator.cs
@@ -12,7 +12,7 @@
}
///
- protected override IControl CreateContainer(object item)
+ protected override IControl? CreateContainer(object item)
{
var separator = item as Separator;
return separator != null ? separator : base.CreateContainer(item);
diff --git a/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs
index 840a1f66f1..c6b0bda9af 100644
--- a/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs
@@ -20,7 +20,7 @@ namespace Avalonia.Controls.Generators
protected override IControl CreateContainer(object item)
{
- var tabItem = (TabItem)base.CreateContainer(item);
+ var tabItem = (TabItem)base.CreateContainer(item)!;
tabItem.Bind(TabItem.TabStripPlacementProperty, new OwnerBinding(
tabItem,
@@ -28,7 +28,7 @@ namespace Avalonia.Controls.Generators
if (tabItem.HeaderTemplate == null)
{
- tabItem.Bind(TabItem.HeaderTemplateProperty, new OwnerBinding(
+ tabItem.Bind(TabItem.HeaderTemplateProperty, new OwnerBinding(
tabItem,
TabControl.ItemTemplateProperty));
}
@@ -50,7 +50,7 @@ namespace Avalonia.Controls.Generators
if (!(tabItem.Content is IControl))
{
- tabItem.Bind(TabItem.ContentTemplateProperty, new OwnerBinding(
+ tabItem.Bind(TabItem.ContentTemplateProperty, new OwnerBinding(
tabItem,
TabControl.ContentTemplateProperty));
}
@@ -62,8 +62,8 @@ namespace Avalonia.Controls.Generators
{
private readonly TabItem _item;
private readonly StyledProperty _ownerProperty;
- private IDisposable _ownerSubscription;
- private IDisposable _propertySubscription;
+ private IDisposable? _ownerSubscription;
+ private IDisposable? _propertySubscription;
public OwnerBinding(TabItem item, StyledProperty ownerProperty)
{
@@ -82,7 +82,7 @@ namespace Avalonia.Controls.Generators
_ownerSubscription = null;
}
- private void OwnerChanged(ILogical c)
+ private void OwnerChanged(ILogical? c)
{
_propertySubscription?.Dispose();
_propertySubscription = null;
diff --git a/src/Avalonia.Controls/Generators/TreeContainerIndex.cs b/src/Avalonia.Controls/Generators/TreeContainerIndex.cs
index f0da370f73..da13416700 100644
--- a/src/Avalonia.Controls/Generators/TreeContainerIndex.cs
+++ b/src/Avalonia.Controls/Generators/TreeContainerIndex.cs
@@ -21,12 +21,12 @@ namespace Avalonia.Controls.Generators
///
/// Signaled whenever new containers are materialized.
///
- public event EventHandler Materialized;
+ public event EventHandler? Materialized;
///
/// Event raised whenever containers are dematerialized.
///
- public event EventHandler Dematerialized;
+ public event EventHandler? Dematerialized;
///
/// Gets the currently materialized containers.
@@ -92,7 +92,7 @@ namespace Avalonia.Controls.Generators
///
/// The item.
/// The container, or null of not found.
- public IControl ContainerFromItem(object item)
+ public IControl? ContainerFromItem(object item)
{
if (item != null)
{
@@ -108,7 +108,7 @@ namespace Avalonia.Controls.Generators
///
/// The container.
/// The item, or null of not found.
- public object ItemFromContainer(IControl container)
+ public object? ItemFromContainer(IControl? container)
{
if (container != null)
{
diff --git a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
index 9e65ef5f81..536a5fdd06 100644
--- a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Controls.Generators
public class TreeItemContainerGenerator : ItemContainerGenerator, ITreeItemContainerGenerator
where T : class, IControl, new()
{
- private TreeView _treeView;
+ private TreeView? _treeView;
///
/// Initializes a new instance of the class.
@@ -32,20 +32,15 @@ namespace Avalonia.Controls.Generators
AvaloniaProperty isExpandedProperty)
: base(owner, contentProperty, contentTemplateProperty)
{
- Contract.Requires(owner != null);
- Contract.Requires(contentProperty != null);
- Contract.Requires(itemsProperty != null);
- Contract.Requires(isExpandedProperty != null);
-
- ItemsProperty = itemsProperty;
- IsExpandedProperty = isExpandedProperty;
+ ItemsProperty = itemsProperty ?? throw new ArgumentNullException(nameof(itemsProperty));
+ IsExpandedProperty = isExpandedProperty ?? throw new ArgumentNullException(nameof(isExpandedProperty));
UpdateIndex();
}
///
/// Gets the container index for the tree.
///
- public TreeContainerIndex Index { get; private set; }
+ public TreeContainerIndex? Index { get; private set; }
///
/// Gets the item container's Items property.
@@ -58,7 +53,7 @@ namespace Avalonia.Controls.Generators
protected AvaloniaProperty IsExpandedProperty { get; }
///
- protected override IControl CreateContainer(object item)
+ protected override IControl? CreateContainer(object? item)
{
var container = item as T;
@@ -141,12 +136,12 @@ namespace Avalonia.Controls.Generators
{
private readonly IDataTemplate _inner;
public WrapperTreeDataTemplate(IDataTemplate inner) => _inner = inner;
- public IControl Build(object param) => _inner.Build(param);
- public bool Match(object data) => _inner.Match(data);
- public InstancedBinding ItemsSelector(object item) => null;
+ public IControl? Build(object? param) => _inner.Build(param);
+ public bool Match(object? data) => _inner.Match(data);
+ public InstancedBinding? ItemsSelector(object item) => null;
}
- private ITreeDataTemplate GetTreeDataTemplate(object item, IDataTemplate primary)
+ private ITreeDataTemplate GetTreeDataTemplate(object item, IDataTemplate? primary)
{
var template = Owner.FindDataTemplate(item, primary) ?? FuncDataTemplate.Default;
var treeTemplate = template as ITreeDataTemplate ?? new WrapperTreeDataTemplate(template);
diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs
index 74401c450a..8d246d35f4 100644
--- a/src/Avalonia.Controls/Grid.cs
+++ b/src/Avalonia.Controls/Grid.cs
@@ -8,6 +8,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Avalonia.Layout;
using Avalonia.Media;
@@ -48,7 +49,7 @@ namespace Avalonia.Controls
/// Column property value.
public static void SetColumn(Control element, int value)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(ColumnProperty, value);
}
@@ -59,7 +60,7 @@ namespace Avalonia.Controls
/// Column property value.
public static int GetColumn(Control element)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(ColumnProperty);
}
@@ -70,7 +71,7 @@ namespace Avalonia.Controls
/// Row property value.
public static void SetRow(Control element, int value)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(RowProperty, value);
}
@@ -81,7 +82,7 @@ namespace Avalonia.Controls
/// Row property value.
public static int GetRow(Control element)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(RowProperty);
}
@@ -92,7 +93,7 @@ namespace Avalonia.Controls
/// ColumnSpan property value.
public static void SetColumnSpan(Control element, int value)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(ColumnSpanProperty, value);
}
@@ -103,7 +104,7 @@ namespace Avalonia.Controls
/// ColumnSpan property value.
public static int GetColumnSpan(Control element)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(ColumnSpanProperty);
}
@@ -114,7 +115,7 @@ namespace Avalonia.Controls
/// RowSpan property value.
public static void SetRowSpan(Control element, int value)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(RowSpanProperty, value);
}
@@ -125,7 +126,7 @@ namespace Avalonia.Controls
/// RowSpan property value.
public static int GetRowSpan(Control element)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(RowSpanProperty);
}
@@ -136,7 +137,7 @@ namespace Avalonia.Controls
/// IsSharedSizeScope property value.
public static void SetIsSharedSizeScope(Control element, bool value)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(IsSharedSizeScopeProperty, value);
}
@@ -147,7 +148,7 @@ namespace Avalonia.Controls
/// IsSharedSizeScope property value.
public static bool GetIsSharedSizeScope(Control element)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(IsSharedSizeScopeProperty);
}
@@ -573,7 +574,7 @@ namespace Avalonia.Controls
///
///
///
- protected override void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ protected override void ChildrenChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
CellsStructureDirty = true;
base.ChildrenChanged(sender, e);
@@ -598,7 +599,7 @@ namespace Avalonia.Controls
{
double value = 0.0;
- Contract.Requires(_data != null);
+ Debug.Assert(_data != null);
// actual value calculations require structure to be up-to-date
if (!ColumnDefinitionsDirty)
@@ -620,7 +621,7 @@ namespace Avalonia.Controls
{
double value = 0.0;
- Contract.Requires(_data != null);
+ Debug.Assert(_data != null);
// actual value calculations require structure to be up-to-date
if (!RowDefinitionsDirty)
@@ -994,7 +995,7 @@ namespace Avalonia.Controls
}
var children = this.Children;
- Hashtable spanStore = null;
+ Hashtable? spanStore = null;
bool ignoreDesiredSizeV = forceInfinityV;
int i = cellsHead;
@@ -1048,7 +1049,7 @@ namespace Avalonia.Controls
foreach (DictionaryEntry e in spanStore)
{
SpanKey key = (SpanKey)e.Key;
- double requestedSize = (double)e.Value;
+ double requestedSize = (double)e.Value!;
EnsureMinSizeInDefinitionRange(
key.U ? DefinitionsU : DefinitionsV,
@@ -1069,7 +1070,7 @@ namespace Avalonia.Controls
/// true if this is a column span. false if this is a row span.
/// Value to store. If an entry already exists the biggest value is stored.
private static void RegisterSpan(
- ref Hashtable store,
+ ref Hashtable? store,
int start,
int count,
bool u,
@@ -1081,7 +1082,7 @@ namespace Avalonia.Controls
}
SpanKey key = new SpanKey(start, count, u);
- object o = store[key];
+ object? o = store[key];
if (o == null
|| value > (double)o)
@@ -1605,12 +1606,12 @@ namespace Avalonia.Controls
while (minCount > 0 && tempDefinitions[minCount - 1].MeasureSize < 0.0)
{
--minCount;
- tempDefinitions[minCount] = null;
+ tempDefinitions[minCount] = null!;
}
while (maxCount > 0 && tempDefinitions[defCount + maxCount - 1].MeasureSize < 0.0)
{
--maxCount;
- tempDefinitions[defCount + maxCount] = null;
+ tempDefinitions[defCount + maxCount] = null!;
}
}
@@ -2321,7 +2322,7 @@ namespace Avalonia.Controls
/// by adding / removing GridLinesRenderer visual.
/// Returns a reference to GridLinesRenderer visual or null.
///
- private GridLinesRenderer EnsureGridLinesRenderer()
+ private GridLinesRenderer? EnsureGridLinesRenderer()
{
//
// synchronize the state
@@ -2369,16 +2370,16 @@ namespace Avalonia.Controls
grid.InvalidateVisual();
}
- grid.SetFlags((bool)e.NewValue, Flags.ShowGridLinesPropertyValue);
+ grid.SetFlags((bool)e.NewValue!, Flags.ShowGridLinesPropertyValue);
}
private static void OnCellAttachedPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
{
- Visual child = d as Visual;
+ Visual? child = d as Visual;
if (child != null)
{
- Grid grid = child.GetVisualParent();
+ Grid? grid = child.GetVisualParent();
if (grid != null
&& grid.ExtData != null
&& grid.ListenToNotifications)
@@ -2395,7 +2396,7 @@ namespace Avalonia.Controls
/// true if one or both of x and y are null, in which case result holds
/// the relative sort order.
///
- private static bool CompareNullRefs(object x, object y, out int result)
+ private static bool CompareNullRefs([NotNullWhen(false)] object? x, [NotNullWhen(false)] object? y, out int result)
{
result = 2;
@@ -2426,7 +2427,7 @@ namespace Avalonia.Controls
///
private IReadOnlyList DefinitionsU
{
- get { return (ExtData.DefinitionsU); }
+ get { return (ExtData.DefinitionsU!); }
}
///
@@ -2434,7 +2435,7 @@ namespace Avalonia.Controls
///
private IReadOnlyList DefinitionsV
{
- get { return (ExtData.DefinitionsV); }
+ get { return (ExtData.DefinitionsV!); }
}
///
@@ -2450,7 +2451,7 @@ namespace Avalonia.Controls
if (extData.TempDefinitions == null
|| extData.TempDefinitions.Length < requiredLength)
{
- WeakReference tempDefinitionsWeakRef = (WeakReference)Thread.GetData(s_tempDefinitionsDataSlot);
+ WeakReference? tempDefinitionsWeakRef = (WeakReference?)Thread.GetData(s_tempDefinitionsDataSlot);
if (tempDefinitionsWeakRef == null)
{
extData.TempDefinitions = new DefinitionBase[requiredLength];
@@ -2458,7 +2459,7 @@ namespace Avalonia.Controls
}
else
{
- extData.TempDefinitions = (DefinitionBase[])tempDefinitionsWeakRef.Target;
+ extData.TempDefinitions = (DefinitionBase[]?)tempDefinitionsWeakRef.Target;
if (extData.TempDefinitions == null
|| extData.TempDefinitions.Length < requiredLength)
{
@@ -2515,7 +2516,7 @@ namespace Avalonia.Controls
///
private CellCache[] PrivateCells
{
- get { return (ExtData.CellCachesCollection); }
+ get { return (ExtData.CellCachesCollection!); }
}
///
@@ -2586,7 +2587,7 @@ namespace Avalonia.Controls
///
private ExtendedData ExtData
{
- get { return (_data); }
+ get { return (_data!); }
}
///
@@ -2608,17 +2609,17 @@ namespace Avalonia.Controls
}
// Extended data instantiated on demand, for non-trivial case handling only
- private ExtendedData _data;
+ private ExtendedData? _data;
// Grid validity / property caches dirtiness flags
private Flags _flags;
- private GridLinesRenderer _gridLinesRenderer;
+ private GridLinesRenderer? _gridLinesRenderer;
// Keeps track of definition indices.
- int[] _definitionIndices;
+ int[]? _definitionIndices;
// Stores unrounded values and rounding errors during layout rounding.
- double[] _roundingErrors;
+ double[]? _roundingErrors;
// 5 is an arbitrary constant chosen to end the measure loop
private const int c_layoutLoopMaxCount = 5;
@@ -2635,16 +2636,16 @@ namespace Avalonia.Controls
///
private class ExtendedData
{
- internal ColumnDefinitions ColumnDefinitions; // collection of column definitions (logical tree support)
- internal RowDefinitions RowDefinitions; // collection of row definitions (logical tree support)
- internal IReadOnlyList DefinitionsU; // collection of column definitions used during calc
- internal IReadOnlyList DefinitionsV; // collection of row definitions used during calc
- internal CellCache[] CellCachesCollection; // backing store for logical children
+ internal ColumnDefinitions? ColumnDefinitions; // collection of column definitions (logical tree support)
+ internal RowDefinitions? RowDefinitions; // collection of row definitions (logical tree support)
+ internal IReadOnlyList? DefinitionsU; // collection of column definitions used during calc
+ internal IReadOnlyList? DefinitionsV; // collection of row definitions used during calc
+ internal CellCache[]? CellCachesCollection; // backing store for logical children
internal int CellGroup1; // index of the first cell in first cell group
internal int CellGroup2; // index of the first cell in second cell group
internal int CellGroup3; // index of the first cell in third cell group
internal int CellGroup4; // index of the first cell in forth cell group
- internal DefinitionBase[] TempDefinitions; // temporary array used during layout for various purposes
+ internal DefinitionBase[]? TempDefinitions; // temporary array used during layout for various purposes
// TempDefinitions.Length == Max(definitionsU.Length, definitionsV.Length)
}
@@ -2831,9 +2832,9 @@ namespace Avalonia.Controls
///
///
///
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
- SpanKey sk = obj as SpanKey;
+ SpanKey? sk = obj as SpanKey;
return (sk != null
&& sk._start == _start
&& sk._count == _count
@@ -2866,10 +2867,10 @@ namespace Avalonia.Controls
///
private class SpanPreferredDistributionOrderComparer : IComparer
{
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
- DefinitionBase definitionX = x as DefinitionBase;
- DefinitionBase definitionY = y as DefinitionBase;
+ DefinitionBase? definitionX = x as DefinitionBase;
+ DefinitionBase? definitionY = y as DefinitionBase;
int result;
@@ -2908,10 +2909,10 @@ namespace Avalonia.Controls
///
private class SpanMaxDistributionOrderComparer : IComparer
{
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
- DefinitionBase definitionX = x as DefinitionBase;
- DefinitionBase definitionY = y as DefinitionBase;
+ DefinitionBase? definitionX = x as DefinitionBase;
+ DefinitionBase? definitionY = y as DefinitionBase;
int result;
@@ -2954,17 +2955,16 @@ namespace Avalonia.Controls
internal StarDistributionOrderIndexComparer(IReadOnlyList definitions)
{
- Contract.Requires(definitions != null);
- this.definitions = definitions;
+ this.definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
- DefinitionBase definitionX = null;
- DefinitionBase definitionY = null;
+ DefinitionBase? definitionX = null;
+ DefinitionBase? definitionY = null;
if (indexX != null)
{
@@ -2995,17 +2995,16 @@ namespace Avalonia.Controls
internal DistributionOrderIndexComparer(IReadOnlyList definitions)
{
- Contract.Requires(definitions != null);
- this.definitions = definitions;
+ this.definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
- DefinitionBase definitionX = null;
- DefinitionBase definitionY = null;
+ DefinitionBase? definitionX = null;
+ DefinitionBase? definitionY = null;
if (indexX != null)
{
@@ -3038,11 +3037,10 @@ namespace Avalonia.Controls
internal RoundingErrorIndexComparer(double[] errors)
{
- Contract.Requires(errors != null);
- this.errors = errors;
+ this.errors = errors ?? throw new ArgumentNullException(nameof(errors));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
@@ -3067,10 +3065,10 @@ namespace Avalonia.Controls
///
private class MinRatioComparer : IComparer
{
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
- DefinitionBase definitionX = x as DefinitionBase;
- DefinitionBase definitionY = y as DefinitionBase;
+ DefinitionBase? definitionX = x as DefinitionBase;
+ DefinitionBase? definitionY = y as DefinitionBase;
int result;
@@ -3090,10 +3088,10 @@ namespace Avalonia.Controls
///
private class MaxRatioComparer : IComparer
{
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
- DefinitionBase definitionX = x as DefinitionBase;
- DefinitionBase definitionY = y as DefinitionBase;
+ DefinitionBase? definitionX = x as DefinitionBase;
+ DefinitionBase? definitionY = y as DefinitionBase;
int result;
@@ -3112,10 +3110,10 @@ namespace Avalonia.Controls
///
private class StarWeightComparer : IComparer
{
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
- DefinitionBase definitionX = x as DefinitionBase;
- DefinitionBase definitionY = y as DefinitionBase;
+ DefinitionBase? definitionX = x as DefinitionBase;
+ DefinitionBase? definitionY = y as DefinitionBase;
int result;
@@ -3137,17 +3135,16 @@ namespace Avalonia.Controls
internal MinRatioIndexComparer(IReadOnlyList definitions)
{
- Contract.Requires(definitions != null);
- this.definitions = definitions;
+ this.definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
- DefinitionBase definitionX = null;
- DefinitionBase definitionY = null;
+ DefinitionBase? definitionX = null;
+ DefinitionBase? definitionY = null;
if (indexX != null)
{
@@ -3178,17 +3175,16 @@ namespace Avalonia.Controls
internal MaxRatioIndexComparer(IReadOnlyList definitions)
{
- Contract.Requires(definitions != null);
- this.definitions = definitions;
+ this.definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
- DefinitionBase definitionX = null;
- DefinitionBase definitionY = null;
+ DefinitionBase? definitionX = null;
+ DefinitionBase? definitionY = null;
if (indexX != null)
{
@@ -3219,17 +3215,16 @@ namespace Avalonia.Controls
internal StarWeightIndexComparer(IReadOnlyList definitions)
{
- Contract.Requires(definitions != null);
- this.definitions = definitions;
+ this.definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
- DefinitionBase definitionX = null;
- DefinitionBase definitionY = null;
+ DefinitionBase? definitionX = null;
+ DefinitionBase? definitionY = null;
if (indexX != null)
{
diff --git a/src/Avalonia.Controls/GridLength.cs b/src/Avalonia.Controls/GridLength.cs
index ee6a146d61..d7022b80ce 100644
--- a/src/Avalonia.Controls/GridLength.cs
+++ b/src/Avalonia.Controls/GridLength.cs
@@ -135,7 +135,7 @@ namespace Avalonia.Controls
///
/// The object with which to test equality.
/// True if the objects are equal, otherwise false.
- public override bool Equals(object o)
+ public override bool Equals(object? o)
{
if (o == null)
{
diff --git a/src/Avalonia.Controls/GridSplitter.cs b/src/Avalonia.Controls/GridSplitter.cs
index 26c8464576..216e43e1f0 100644
--- a/src/Avalonia.Controls/GridSplitter.cs
+++ b/src/Avalonia.Controls/GridSplitter.cs
@@ -59,7 +59,7 @@ namespace Avalonia.Controls
private static readonly Cursor s_columnSplitterCursor = new Cursor(StandardCursorType.SizeWestEast);
private static readonly Cursor s_rowSplitterCursor = new Cursor(StandardCursorType.SizeNorthSouth);
- private ResizeData _resizeData;
+ private ResizeData? _resizeData;
///
/// Indicates whether the Splitter resizes the Columns, Rows, or Both.
@@ -197,9 +197,9 @@ namespace Avalonia.Controls
///
private void RemovePreviewAdorner()
{
- if (_resizeData.Adorner != null)
+ if (_resizeData?.Adorner != null)
{
- AdornerLayer layer = AdornerLayer.GetAdornerLayer(this);
+ AdornerLayer layer = AdornerLayer.GetAdornerLayer(this)!;
layer.Children.Remove(_resizeData.Adorner);
}
}
@@ -242,7 +242,7 @@ namespace Avalonia.Controls
///
private bool SetupDefinitionsToResize()
{
- int gridSpan = GetValue(_resizeData.ResizeDirection == GridResizeDirection.Columns ?
+ int gridSpan = GetValue(_resizeData!.ResizeDirection == GridResizeDirection.Columns ?
Grid.ColumnSpanProperty :
Grid.RowSpanProperty);
@@ -276,8 +276,8 @@ namespace Avalonia.Controls
// Get count of rows/columns in the resize direction.
int count = _resizeData.ResizeDirection == GridResizeDirection.Columns ?
- _resizeData.Grid.ColumnDefinitions.Count :
- _resizeData.Grid.RowDefinitions.Count;
+ _resizeData.Grid!.ColumnDefinitions.Count :
+ _resizeData.Grid!.RowDefinitions.Count;
if (index1 >= 0 && index2 < count)
{
@@ -322,10 +322,10 @@ namespace Avalonia.Controls
///
private void SetupPreviewAdorner()
{
- if (_resizeData.ShowsPreview)
+ if (_resizeData!.ShowsPreview)
{
// Get the adorner layer and add an adorner to it.
- var adornerLayer = AdornerLayer.GetAdornerLayer(_resizeData.Grid);
+ var adornerLayer = AdornerLayer.GetAdornerLayer(_resizeData.Grid!);
var previewContent = PreviewContent;
@@ -335,7 +335,7 @@ namespace Avalonia.Controls
return;
}
- IControl builtPreviewContent = previewContent?.Build();
+ IControl? builtPreviewContent = previewContent?.Build();
_resizeData.Adorner = new PreviewAdorner(builtPreviewContent);
@@ -409,13 +409,13 @@ namespace Avalonia.Controls
// Set the Translation of the Adorner to the distance from the thumb.
if (_resizeData.ResizeDirection == GridResizeDirection.Columns)
{
- _resizeData.Adorner.OffsetX = Math.Min(
+ _resizeData.Adorner!.OffsetX = Math.Min(
Math.Max(horizontalChange, _resizeData.MinChange),
_resizeData.MaxChange);
}
else
{
- _resizeData.Adorner.OffsetY = Math.Min(
+ _resizeData.Adorner!.OffsetY = Math.Min(
Math.Max(verticalChange, _resizeData.MinChange),
_resizeData.MaxChange);
}
@@ -437,7 +437,7 @@ namespace Avalonia.Controls
if (_resizeData.ShowsPreview)
{
// Update the grid.
- MoveSplitter(_resizeData.Adorner.OffsetX, _resizeData.Adorner.OffsetY);
+ MoveSplitter(_resizeData.Adorner!.OffsetX, _resizeData.Adorner.OffsetY);
RemovePreviewAdorner();
}
@@ -481,14 +481,14 @@ namespace Avalonia.Controls
private void CancelResize()
{
// Restore original column/row lengths.
- if (_resizeData.ShowsPreview)
+ if (_resizeData!.ShowsPreview)
{
RemovePreviewAdorner();
}
else // Reset the columns/rows lengths to the saved values.
{
- SetDefinitionLength(_resizeData.Definition1, _resizeData.OriginalDefinition1Length);
- SetDefinitionLength(_resizeData.Definition2, _resizeData.OriginalDefinition2Length);
+ SetDefinitionLength(_resizeData.Definition1!, _resizeData.OriginalDefinition1Length);
+ SetDefinitionLength(_resizeData.Definition2!, _resizeData.OriginalDefinition2Length);
}
_resizeData = null;
@@ -536,12 +536,12 @@ namespace Avalonia.Controls
///
private void GetDeltaConstraints(out double minDelta, out double maxDelta)
{
- double definition1Len = GetActualLength(_resizeData.Definition1);
- double definition1Min = _resizeData.Definition1.UserMinSizeValueCache;
+ double definition1Len = GetActualLength(_resizeData!.Definition1!);
+ double definition1Min = _resizeData.Definition1!.UserMinSizeValueCache;
double definition1Max = _resizeData.Definition1.UserMaxSizeValueCache;
- double definition2Len = GetActualLength(_resizeData.Definition2);
- double definition2Min = _resizeData.Definition2.UserMinSizeValueCache;
+ double definition2Len = GetActualLength(_resizeData.Definition2!);
+ double definition2Min = _resizeData.Definition2!.UserMinSizeValueCache;
double definition2Max = _resizeData.Definition2.UserMaxSizeValueCache;
// Set MinWidths to be greater than width of splitter.
@@ -565,11 +565,11 @@ namespace Avalonia.Controls
private void SetLengths(double definition1Pixels, double definition2Pixels)
{
// For the case where both definition1 and 2 are stars, update all star values to match their current pixel values.
- if (_resizeData.SplitBehavior == SplitBehavior.Split)
+ if (_resizeData!.SplitBehavior == SplitBehavior.Split)
{
var definitions = _resizeData.ResizeDirection == GridResizeDirection.Columns ?
- (IAvaloniaReadOnlyList)_resizeData.Grid.ColumnDefinitions :
- (IAvaloniaReadOnlyList)_resizeData.Grid.RowDefinitions;
+ (IAvaloniaReadOnlyList)_resizeData.Grid!.ColumnDefinitions :
+ (IAvaloniaReadOnlyList)_resizeData.Grid!.RowDefinitions;
var definitionsCount = definitions.Count;
@@ -595,11 +595,11 @@ namespace Avalonia.Controls
}
else if (_resizeData.SplitBehavior == SplitBehavior.Resize1)
{
- SetDefinitionLength(_resizeData.Definition1, new GridLength(definition1Pixels));
+ SetDefinitionLength(_resizeData.Definition1!, new GridLength(definition1Pixels));
}
else
{
- SetDefinitionLength(_resizeData.Definition2, new GridLength(definition2Pixels));
+ SetDefinitionLength(_resizeData.Definition2!, new GridLength(definition2Pixels));
}
}
@@ -623,8 +623,8 @@ namespace Avalonia.Controls
delta = LayoutHelper.RoundLayoutValue(delta, LayoutHelper.GetLayoutScale(this));
}
- DefinitionBase definition1 = _resizeData.Definition1;
- DefinitionBase definition2 = _resizeData.Definition2;
+ DefinitionBase? definition1 = _resizeData.Definition1;
+ DefinitionBase? definition2 = _resizeData.Definition2;
if (definition1 != null && definition2 != null)
{
@@ -691,7 +691,7 @@ namespace Avalonia.Controls
private readonly TranslateTransform _translation;
private readonly Decorator _decorator;
- public PreviewAdorner(IControl previewControl)
+ public PreviewAdorner(IControl? previewControl)
{
// Add a decorator to perform translations.
_translation = new TranslateTransform();
@@ -762,22 +762,22 @@ namespace Avalonia.Controls
private class ResizeData
{
public bool ShowsPreview;
- public PreviewAdorner Adorner;
+ public PreviewAdorner? Adorner;
// The constraints to keep the Preview within valid ranges.
public double MinChange;
public double MaxChange;
// The grid to Resize.
- public Grid Grid;
+ public Grid? Grid;
// Cache of Resize Direction and Behavior.
public GridResizeDirection ResizeDirection;
public GridResizeBehavior ResizeBehavior;
// The columns/rows to resize.
- public DefinitionBase Definition1;
- public DefinitionBase Definition2;
+ public DefinitionBase? Definition1;
+ public DefinitionBase? Definition2;
// Are the columns/rows star lengths.
public SplitBehavior SplitBehavior;
diff --git a/src/Avalonia.Controls/HotkeyManager.cs b/src/Avalonia.Controls/HotkeyManager.cs
index e89bb177dd..d83b996aa0 100644
--- a/src/Avalonia.Controls/HotkeyManager.cs
+++ b/src/Avalonia.Controls/HotkeyManager.cs
@@ -7,29 +7,29 @@ namespace Avalonia.Controls
{
public class HotKeyManager
{
- public static readonly AttachedProperty HotKeyProperty
- = AvaloniaProperty.RegisterAttached("HotKey", typeof(HotKeyManager));
+ public static readonly AttachedProperty HotKeyProperty
+ = AvaloniaProperty.RegisterAttached("HotKey", typeof(HotKeyManager));
class HotkeyCommandWrapper : ICommand
{
- public HotkeyCommandWrapper(ICommandSource control)
+ public HotkeyCommandWrapper(ICommandSource? control)
{
CommandSource = control;
}
- public readonly ICommandSource CommandSource;
+ public readonly ICommandSource? CommandSource;
- private ICommand GetCommand() => CommandSource.Command;
+ private ICommand? GetCommand() => CommandSource?.Command;
- public bool CanExecute(object parameter) =>
- CommandSource.Command?.CanExecute(CommandSource.CommandParameter) == true
+ public bool CanExecute(object? parameter) =>
+ CommandSource?.Command?.CanExecute(CommandSource.CommandParameter) == true
&& CommandSource.IsEffectivelyEnabled;
- public void Execute(object parameter) =>
- GetCommand()?.Execute(CommandSource.CommandParameter);
+ public void Execute(object? parameter) =>
+ GetCommand()?.Execute(CommandSource?.CommandParameter);
#pragma warning disable 67 // Event not used
- public event EventHandler CanExecuteChanged;
+ public event EventHandler? CanExecuteChanged;
#pragma warning restore 67
}
@@ -37,12 +37,12 @@ namespace Avalonia.Controls
class Manager
{
private readonly IControl _control;
- private TopLevel _root;
- private IDisposable _parentSub;
- private IDisposable _hotkeySub;
- private KeyGesture _hotkey;
+ private TopLevel? _root;
+ private IDisposable? _parentSub;
+ private IDisposable? _hotkeySub;
+ private KeyGesture? _hotkey;
private readonly HotkeyCommandWrapper _wrapper;
- private KeyBinding _binding;
+ private KeyBinding? _binding;
public Manager(IControl control)
{
@@ -56,14 +56,14 @@ namespace Avalonia.Controls
_parentSub = AncestorFinder.Create(_control).Subscribe(OnParentChanged);
}
- private void OnParentChanged(TopLevel control)
+ private void OnParentChanged(TopLevel? control)
{
Unregister();
_root = control;
Register();
}
- private void OnHotkeyChanged(KeyGesture hotkey)
+ private void OnHotkeyChanged(KeyGesture? hotkey)
{
if (hotkey == null)
//Subscription will be recreated by static property watcher
@@ -95,8 +95,8 @@ namespace Avalonia.Controls
void Stop()
{
Unregister();
- _parentSub.Dispose();
- _hotkeySub.Dispose();
+ _parentSub?.Dispose();
+ _hotkeySub?.Dispose();
}
}
@@ -118,6 +118,6 @@ namespace Avalonia.Controls
});
}
public static void SetHotKey(AvaloniaObject target, KeyGesture value) => target.SetValue(HotKeyProperty, value);
- public static KeyGesture GetHotKey(AvaloniaObject target) => target.GetValue(HotKeyProperty);
+ public static KeyGesture? GetHotKey(AvaloniaObject target) => target.GetValue(HotKeyProperty);
}
}
diff --git a/src/Avalonia.Controls/IContentControl.cs b/src/Avalonia.Controls/IContentControl.cs
index 889771b355..d28b0afb25 100644
--- a/src/Avalonia.Controls/IContentControl.cs
+++ b/src/Avalonia.Controls/IContentControl.cs
@@ -12,12 +12,12 @@ namespace Avalonia.Controls
///
/// Gets or sets the content to display.
///
- object Content { get; set; }
+ object? Content { get; set; }
///
/// Gets or sets the data template used to display the content of the control.
///
- IDataTemplate ContentTemplate { get; set; }
+ IDataTemplate? ContentTemplate { get; set; }
///
/// Gets or sets the horizontal alignment of the content within the control.
@@ -29,4 +29,4 @@ namespace Avalonia.Controls
///
VerticalAlignment VerticalContentAlignment { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Controls/IControl.cs b/src/Avalonia.Controls/IControl.cs
index 598e6b6f4e..b501bc15a7 100644
--- a/src/Avalonia.Controls/IControl.cs
+++ b/src/Avalonia.Controls/IControl.cs
@@ -3,8 +3,6 @@ using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/IHeadered.cs b/src/Avalonia.Controls/IHeadered.cs
index c208e21c97..8c1b5cfb1b 100644
--- a/src/Avalonia.Controls/IHeadered.cs
+++ b/src/Avalonia.Controls/IHeadered.cs
@@ -8,6 +8,6 @@ namespace Avalonia.Controls
///
/// Gets or set the header.
///
- object Header { get; set; }
+ object? Header { get; set; }
}
}
diff --git a/src/Avalonia.Controls/IMenuElement.cs b/src/Avalonia.Controls/IMenuElement.cs
index 426f265084..a3200d2b1b 100644
--- a/src/Avalonia.Controls/IMenuElement.cs
+++ b/src/Avalonia.Controls/IMenuElement.cs
@@ -1,8 +1,6 @@
using System.Collections.Generic;
using Avalonia.Input;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/IMenuItem.cs b/src/Avalonia.Controls/IMenuItem.cs
index d92625218a..35e36eb0f4 100644
--- a/src/Avalonia.Controls/IMenuItem.cs
+++ b/src/Avalonia.Controls/IMenuItem.cs
@@ -1,6 +1,4 @@
-#nullable enable
-
-namespace Avalonia.Controls
+namespace Avalonia.Controls
{
///
/// Represents a .
diff --git a/src/Avalonia.Controls/IScrollAnchorProvider.cs b/src/Avalonia.Controls/IScrollAnchorProvider.cs
index 7ba02e99ea..b3ce7ef9e8 100644
--- a/src/Avalonia.Controls/IScrollAnchorProvider.cs
+++ b/src/Avalonia.Controls/IScrollAnchorProvider.cs
@@ -1,6 +1,4 @@
-#nullable enable
-
-namespace Avalonia.Controls
+namespace Avalonia.Controls
{
///
/// Specifies a contract for a scrolling control that supports scroll anchoring.
diff --git a/src/Avalonia.Controls/IVirtualizingPanel.cs b/src/Avalonia.Controls/IVirtualizingPanel.cs
index 8c4dc80934..604a62dcb9 100644
--- a/src/Avalonia.Controls/IVirtualizingPanel.cs
+++ b/src/Avalonia.Controls/IVirtualizingPanel.cs
@@ -16,7 +16,7 @@ namespace Avalonia.Controls
/// Note that this property may remain null if the panel is added to a control that does
/// not act as a virtualizing controller.
///
- IVirtualizingController Controller { get; set; }
+ IVirtualizingController? Controller { get; set; }
///
/// Gets a value indicating whether the panel is full.
diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs
index 1ff49326b6..70f771ca00 100644
--- a/src/Avalonia.Controls/ItemsControl.cs
+++ b/src/Avalonia.Controls/ItemsControl.cs
@@ -32,8 +32,8 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly DirectProperty ItemsProperty =
- AvaloniaProperty.RegisterDirect(nameof(Items), o => o.Items, (o, v) => o.Items = v);
+ public static readonly DirectProperty ItemsProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Items), o => o.Items, (o, v) => o.Items = v);
///
/// Defines the property.
@@ -50,13 +50,13 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty ItemTemplateProperty =
- AvaloniaProperty.Register(nameof(ItemTemplate));
+ public static readonly StyledProperty ItemTemplateProperty =
+ AvaloniaProperty.Register(nameof(ItemTemplate));
- private IEnumerable _items = new AvaloniaList();
+ private IEnumerable? _items = new AvaloniaList();
private int _itemCount;
- private IItemContainerGenerator _itemContainerGenerator;
- private EventHandler _childIndexChanged;
+ private IItemContainerGenerator? _itemContainerGenerator;
+ private EventHandler? _childIndexChanged;
///
/// Initializes static members of the class.
@@ -79,7 +79,7 @@ namespace Avalonia.Controls
///
/// Gets the for the control.
///
- public IItemContainerGenerator ItemContainerGenerator
+ public IItemContainerGenerator? ItemContainerGenerator
{
get
{
@@ -104,7 +104,7 @@ namespace Avalonia.Controls
/// Gets or sets the items to display.
///
[Content]
- public IEnumerable Items
+ public IEnumerable? Items
{
get { return _items; }
set { SetAndRaise(ItemsProperty, ref _items, value); }
@@ -131,7 +131,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the data template used to display the items in the control.
///
- public IDataTemplate ItemTemplate
+ public IDataTemplate? ItemTemplate
{
get { return GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
@@ -140,13 +140,13 @@ namespace Avalonia.Controls
///
/// Gets the items presenter control.
///
- public IItemsPresenter Presenter
+ public IItemsPresenter? Presenter
{
get;
protected set;
}
- event EventHandler IChildIndexProvider.ChildIndexChanged
+ event EventHandler? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
@@ -161,7 +161,7 @@ namespace Avalonia.Controls
}
Presenter = presenter;
- ItemContainerGenerator.Clear();
+ ItemContainerGenerator?.Clear();
if (Presenter is IChildIndexProvider innerProvider)
{
@@ -189,11 +189,11 @@ namespace Avalonia.Controls
/// The collection.
/// The index.
/// The item at the given index or null if the index is out of bounds.
- protected static object ElementAt(IEnumerable items, int index)
+ protected static object? ElementAt(IEnumerable? items, int index)
{
if (index != -1 && index < items.Count())
{
- return items.ElementAt(index) ?? null;
+ return items!.ElementAt(index) ?? null;
}
else
{
@@ -207,7 +207,7 @@ namespace Avalonia.Controls
/// The collection.
/// The item.
/// The index of the item or -1 if the item was not found.
- protected static int IndexOf(IEnumerable items, object item)
+ protected static int IndexOf(IEnumerable? items, object item)
{
if (items != null && item != null)
{
@@ -282,7 +282,7 @@ namespace Avalonia.Controls
{
// If the item is its own container, then it will be removed from the logical tree
// when it is removed from the Items collection.
- if (container?.ContainerControl != container?.Item)
+ if (container.ContainerControl != container.Item)
{
LogicalChildren.Remove(container.ContainerControl);
}
@@ -311,20 +311,20 @@ namespace Avalonia.Controls
var container = Presenter?.Panel as INavigableContainer;
if (container == null ||
- focus.Current == null ||
+ focus?.Current == null ||
direction == null ||
direction.Value.IsTab())
{
return;
}
- IVisual current = focus.Current;
+ IVisual? current = focus.Current;
while (current != null)
{
if (current.VisualParent == container && current is IInputElement inputElement)
{
- IInputElement next = GetNextControl(container, direction.Value, inputElement, false);
+ var next = GetNextControl(container, direction.Value, inputElement, false);
if (next != null)
{
@@ -406,7 +406,7 @@ namespace Avalonia.Controls
/// Given a collection of items, adds those that are controls to the logical children.
///
/// The items.
- private void AddControlItemsToLogicalChildren(IEnumerable items)
+ private void AddControlItemsToLogicalChildren(IEnumerable? items)
{
var toAdd = new List();
@@ -430,7 +430,7 @@ namespace Avalonia.Controls
/// Given a collection of items, removes those that are controls to from logical children.
///
/// The items.
- private void RemoveControlItemsFromLogicalChildren(IEnumerable items)
+ private void RemoveControlItemsFromLogicalChildren(IEnumerable? items)
{
var toRemove = new List();
@@ -454,7 +454,7 @@ namespace Avalonia.Controls
/// Subscribes to an collection.
///
/// The items collection.
- private void SubscribeToItems(IEnumerable items)
+ private void SubscribeToItems(IEnumerable? items)
{
if (items is INotifyCollectionChanged incc)
{
@@ -470,7 +470,7 @@ namespace Avalonia.Controls
{
if (_itemContainerGenerator != null)
{
- _itemContainerGenerator.ItemTemplate = (IDataTemplate)e.NewValue;
+ _itemContainerGenerator.ItemTemplate = (IDataTemplate?)e.NewValue;
// TODO: Rebuild the item containers.
}
}
@@ -497,13 +497,13 @@ namespace Avalonia.Controls
PseudoClasses.Set(":singleitem", itemCount == 1);
}
- protected static IInputElement GetNextControl(
+ protected static IInputElement? GetNextControl(
INavigableContainer container,
NavigationDirection direction,
- IInputElement from,
+ IInputElement? from,
bool wrap)
{
- IInputElement result;
+ IInputElement? result;
var c = from;
do
@@ -525,7 +525,7 @@ namespace Avalonia.Controls
return null;
}
- private void PresenterChildIndexChanged(object sender, ChildIndexChangedEventArgs e)
+ private void PresenterChildIndexChanged(object? sender, ChildIndexChangedEventArgs e)
{
_childIndexChanged?.Invoke(this, e);
}
diff --git a/src/Avalonia.Controls/ItemsSourceView.cs b/src/Avalonia.Controls/ItemsSourceView.cs
index c2d20495ef..945035ab5e 100644
--- a/src/Avalonia.Controls/ItemsSourceView.cs
+++ b/src/Avalonia.Controls/ItemsSourceView.cs
@@ -7,12 +7,9 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Avalonia.Controls.Utils;
-#nullable enable
-
namespace Avalonia.Controls
{
///
@@ -196,7 +193,7 @@ namespace Avalonia.Controls
_collectionChanged?.Invoke(this, args);
}
- private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
OnItemsSourceChanged(e);
}
@@ -239,8 +236,7 @@ namespace Avalonia.Controls
///
/// The index.
/// The item.
- [return: MaybeNull]
- public new T GetAt(int index) => (T)Inner[index];
+ public new T GetAt(int index) => (T)Inner[index]!;
public IEnumerator GetEnumerator() => Inner.Cast().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => Inner.GetEnumerator();
diff --git a/src/Avalonia.Controls/Label.cs b/src/Avalonia.Controls/Label.cs
index 9d5eda464f..5c8a6e0a5b 100644
--- a/src/Avalonia.Controls/Label.cs
+++ b/src/Avalonia.Controls/Label.cs
@@ -18,19 +18,19 @@ namespace Avalonia.Controls
///
/// Defines the Direct property
///
- public static readonly DirectProperty
public class LayoutTransformControl : Decorator
{
- public static readonly StyledProperty LayoutTransformProperty =
- AvaloniaProperty.Register(nameof(LayoutTransform));
+ public static readonly StyledProperty LayoutTransformProperty =
+ AvaloniaProperty.Register(nameof(LayoutTransform));
public static readonly StyledProperty UseRenderTransformProperty =
AvaloniaProperty.Register(nameof(UseRenderTransform));
@@ -37,7 +37,7 @@ namespace Avalonia.Controls
///
/// Gets or sets a graphics transformation that should apply to this element when layout is performed.
///
- public ITransform LayoutTransform
+ public ITransform? LayoutTransform
{
get { return GetValue(LayoutTransformProperty); }
set { SetValue(LayoutTransformProperty, value); }
@@ -52,7 +52,7 @@ namespace Avalonia.Controls
set { SetValue(UseRenderTransformProperty, value); }
}
- public IControl TransformRoot => Child;
+ public IControl? TransformRoot => Child;
///
/// Provides the behavior for the "Arrange" pass of layout.
@@ -146,7 +146,7 @@ namespace Avalonia.Controls
return transformedDesiredSize;
}
- IDisposable _renderTransformChangedEvent;
+ IDisposable? _renderTransformChangedEvent;
private void OnUseRenderTransformPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
@@ -158,7 +158,7 @@ namespace Avalonia.Controls
// workaround.
var target = e.Sender as LayoutTransformControl;
- var shouldUseRenderTransform = (bool)e.NewValue;
+ var shouldUseRenderTransform = (bool)e.NewValue!;
if (target != null)
{
if (shouldUseRenderTransform)
@@ -217,7 +217,7 @@ namespace Avalonia.Controls
/// Transformation matrix corresponding to _matrixTransform.
///
private Matrix _transformation;
- private IDisposable _transformChangedEvent = null;
+ private IDisposable? _transformChangedEvent = null;
///
/// Returns true if Size a is smaller than Size b in either dimension.
diff --git a/src/Avalonia.Controls/ListBox.cs b/src/Avalonia.Controls/ListBox.cs
index 43b4908482..9b7ae0d324 100644
--- a/src/Avalonia.Controls/ListBox.cs
+++ b/src/Avalonia.Controls/ListBox.cs
@@ -23,13 +23,13 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly DirectProperty ScrollProperty =
- AvaloniaProperty.RegisterDirect(nameof(Scroll), o => o.Scroll);
+ public static readonly DirectProperty ScrollProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Scroll), o => o.Scroll);
///
/// Defines the property.
///
- public static readonly new DirectProperty SelectedItemsProperty =
+ public static readonly new DirectProperty SelectedItemsProperty =
SelectingItemsControl.SelectedItemsProperty;
///
@@ -50,7 +50,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty VirtualizationModeProperty =
ItemsPresenter.VirtualizationModeProperty.AddOwner();
- private IScrollable _scroll;
+ private IScrollable? _scroll;
///
/// Initializes static members of the class.
@@ -64,14 +64,14 @@ namespace Avalonia.Controls
///
/// Gets the scroll information for the .
///
- public IScrollable Scroll
+ public IScrollable? Scroll
{
get { return _scroll; }
private set { SetAndRaise(ScrollProperty, ref _scroll, value); }
}
///
- public new IList SelectedItems
+ public new IList? SelectedItems
{
get => base.SelectedItems;
set => base.SelectedItems = value;
diff --git a/src/Avalonia.Controls/MaskedTextBox.cs b/src/Avalonia.Controls/MaskedTextBox.cs
index f59cef8223..ad64c61ebe 100644
--- a/src/Avalonia.Controls/MaskedTextBox.cs
+++ b/src/Avalonia.Controls/MaskedTextBox.cs
@@ -8,8 +8,6 @@ using Avalonia.Input.Platform;
using Avalonia.Interactivity;
using Avalonia.Styling;
-#nullable enable
-
namespace Avalonia.Controls
{
public class MaskedTextBox : TextBox, IStyleable
@@ -241,7 +239,7 @@ namespace Avalonia.Controls
switch (e.Key)
{
case Key.Delete:
- if (CaretIndex < Text.Length)
+ if (CaretIndex < Text?.Length)
{
if (MaskProvider.RemoveAt(CaretIndex))
{
@@ -286,7 +284,7 @@ namespace Avalonia.Controls
{
void UpdateMaskProvider()
{
- MaskProvider = new MaskedTextProvider(Mask, Culture, true, PromptChar, PasswordChar, AsciiOnly) { ResetOnSpace = ResetOnSpace, ResetOnPrompt = ResetOnPrompt };
+ MaskProvider = new MaskedTextProvider(Mask!, Culture, true, PromptChar, PasswordChar, AsciiOnly) { ResetOnSpace = ResetOnSpace, ResetOnPrompt = ResetOnPrompt };
if (Text != null)
{
MaskProvider.Set(Text);
@@ -383,11 +381,11 @@ namespace Avalonia.Controls
}
}
- if (CaretIndex < Text.Length)
+ if (CaretIndex < Text?.Length)
{
CaretIndex = GetNextCharacterPosition(CaretIndex);
- if (MaskProvider.InsertAt(e.Text, CaretIndex))
+ if (MaskProvider.InsertAt(e.Text!, CaretIndex))
{
CaretIndex++;
}
diff --git a/src/Avalonia.Controls/Menu.cs b/src/Avalonia.Controls/Menu.cs
index 706be376a9..cc89677f82 100644
--- a/src/Avalonia.Controls/Menu.cs
+++ b/src/Avalonia.Controls/Menu.cs
@@ -5,8 +5,6 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/MenuBase.cs b/src/Avalonia.Controls/MenuBase.cs
index 0434928280..c36fbcc51f 100644
--- a/src/Avalonia.Controls/MenuBase.cs
+++ b/src/Avalonia.Controls/MenuBase.cs
@@ -8,8 +8,6 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
-#nullable enable
-
namespace Avalonia.Controls
{
///
@@ -83,12 +81,13 @@ namespace Avalonia.Controls
{
var index = SelectedIndex;
return (index != -1) ?
- (IMenuItem)ItemContainerGenerator.ContainerFromIndex(index) :
+ (IMenuItem?)ItemContainerGenerator!.ContainerFromIndex(index) :
null;
}
set
{
- SelectedIndex = ItemContainerGenerator.IndexFromContainer(value);
+ SelectedIndex = value is not null ?
+ ItemContainerGenerator!.IndexFromContainer(value) : -1;
}
}
@@ -97,7 +96,7 @@ namespace Avalonia.Controls
{
get
{
- return ItemContainerGenerator.Containers
+ return ItemContainerGenerator!.Containers
.Select(x => x.ContainerControl)
.OfType();
}
@@ -111,7 +110,7 @@ namespace Avalonia.Controls
///
/// Occurs when a is opened.
///
- public event EventHandler MenuOpened
+ public event EventHandler? MenuOpened
{
add { AddHandler(MenuOpenedEvent, value); }
remove { RemoveHandler(MenuOpenedEvent, value); }
@@ -120,7 +119,7 @@ namespace Avalonia.Controls
///
/// Occurs when a is closed.
///
- public event EventHandler MenuClosed
+ public event EventHandler? MenuClosed
{
add { AddHandler(MenuClosedEvent, value); }
remove { RemoveHandler(MenuClosedEvent, value); }
diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs
index b843992f04..9540ab05f9 100644
--- a/src/Avalonia.Controls/MenuItem.cs
+++ b/src/Avalonia.Controls/MenuItem.cs
@@ -14,8 +14,6 @@ using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls
{
///
@@ -42,20 +40,20 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty CommandParameterProperty =
+ public static readonly StyledProperty CommandParameterProperty =
Button.CommandParameterProperty.AddOwner
/// The event sender.
/// The event args.
- private void CanExecuteChanged(object sender, EventArgs e)
+ private void CanExecuteChanged(object? sender, EventArgs e)
{
TryUpdateCanExecute();
}
@@ -655,7 +653,7 @@ namespace Avalonia.Controls
if (value)
{
- foreach (var item in Items.OfType())
+ foreach (var item in Items!.OfType())
{
item.TryUpdateCanExecute();
}
@@ -677,13 +675,13 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- private void PopupOpened(object sender, EventArgs e)
+ private void PopupOpened(object? sender, EventArgs e)
{
var selected = SelectedIndex;
if (selected != -1)
{
- var container = ItemContainerGenerator.ContainerFromIndex(selected);
+ var container = ItemContainerGenerator?.ContainerFromIndex(selected);
container?.Focus();
}
}
@@ -693,7 +691,7 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- private void PopupClosed(object sender, EventArgs e)
+ private void PopupClosed(object? sender, EventArgs e)
{
SelectedItem = null;
}
diff --git a/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs b/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
index 2c3dac8482..4cc6a20082 100644
--- a/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
+++ b/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
@@ -19,7 +19,7 @@ namespace Avalonia.Controls
///
/// The window to which the handler belongs.
///
- private IInputRoot _owner;
+ private IInputRoot? _owner;
///
/// Gets or sets the window's main menu.
@@ -27,7 +27,7 @@ namespace Avalonia.Controls
///
/// This property is ignored as a menu item cannot have a main menu.
///
- public IMainMenu MainMenu { get; set; }
+ public IMainMenu? MainMenu { get; set; }
///
/// Sets the owner of the access key handler.
@@ -38,7 +38,7 @@ namespace Avalonia.Controls
///
public void SetOwner(IInputRoot owner)
{
- Contract.Requires(owner != null);
+ _ = owner ?? throw new ArgumentNullException(nameof(owner));
if (_owner != null)
{
@@ -84,7 +84,7 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- protected virtual void OnTextInput(object sender, TextInputEventArgs e)
+ protected virtual void OnTextInput(object? sender, TextInputEventArgs e)
{
if (!string.IsNullOrWhiteSpace(e.Text))
{
diff --git a/src/Avalonia.Controls/Mixins/SelectableMixin.cs b/src/Avalonia.Controls/Mixins/SelectableMixin.cs
index c9e2b684cb..fa964c0056 100644
--- a/src/Avalonia.Controls/Mixins/SelectableMixin.cs
+++ b/src/Avalonia.Controls/Mixins/SelectableMixin.cs
@@ -40,7 +40,7 @@ namespace Avalonia.Controls.Mixins
public static void Attach(AvaloniaProperty isSelected)
where TControl : class, IControl
{
- Contract.Requires(isSelected != null);
+ _ = isSelected ?? throw new ArgumentNullException(nameof(isSelected));
isSelected.Changed.Subscribe(x =>
{
diff --git a/src/Avalonia.Controls/NativeControlHost.cs b/src/Avalonia.Controls/NativeControlHost.cs
index e18b7a5ba2..191b60f303 100644
--- a/src/Avalonia.Controls/NativeControlHost.cs
+++ b/src/Avalonia.Controls/NativeControlHost.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
using Avalonia.Threading;
@@ -9,10 +10,10 @@ namespace Avalonia.Controls
{
public class NativeControlHost : Control
{
- private TopLevel _currentRoot;
- private INativeControlHostImpl _currentHost;
- private INativeControlHostControlTopLevelAttachment _attachment;
- private IPlatformHandle _nativeControlHandle;
+ private TopLevel? _currentRoot;
+ private INativeControlHostImpl? _currentHost;
+ private INativeControlHostControlTopLevelAttachment? _attachment;
+ private IPlatformHandle? _nativeControlHandle;
private bool _queuedForDestruction;
private bool _queuedForMoveResize;
private readonly List _propertyChangedSubscriptions = new List();
@@ -35,7 +36,7 @@ namespace Avalonia.Controls
UpdateHost();
}
- private void PropertyChangedHandler(object sender, AvaloniaPropertyChangedEventArgs e)
+ private void PropertyChangedHandler(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.IsEffectiveValueChange && (e.Property == BoundsProperty || e.Property == IsVisibleProperty))
EnqueueForMoveResize();
@@ -58,9 +59,8 @@ namespace Avalonia.Controls
{
_queuedForMoveResize = false;
_currentHost = (_currentRoot?.PlatformImpl as ITopLevelImplWithNativeControlHost)?.NativeControlHost;
- var needsAttachment = _currentHost != null;
- if (needsAttachment)
+ if (_currentHost != null)
{
// If there is an existing attachment, ensure that we are attached to the proper host or destroy the attachment
if (_attachment != null && _attachment.AttachedTo != _currentHost)
@@ -119,6 +119,8 @@ namespace Avalonia.Controls
private Rect? GetAbsoluteBounds()
{
+ Debug.Assert(_currentRoot is not null);
+
var bounds = Bounds;
var position = this.TranslatePoint(default, _currentRoot);
if (position == null)
@@ -140,9 +142,8 @@ namespace Avalonia.Controls
return false;
var bounds = GetAbsoluteBounds();
- var needsShow = IsEffectivelyVisible && bounds.HasValue;
- if (needsShow)
+ if (IsEffectivelyVisible && bounds.HasValue)
{
if (bounds.Value.IsEmpty)
return false;
diff --git a/src/Avalonia.Controls/NativeMenu.Export.cs b/src/Avalonia.Controls/NativeMenu.Export.cs
index 6bfe5ebc82..fe650ab41e 100644
--- a/src/Avalonia.Controls/NativeMenu.Export.cs
+++ b/src/Avalonia.Controls/NativeMenu.Export.cs
@@ -18,7 +18,7 @@ namespace Avalonia.Controls
class NativeMenuInfo
{
public bool ChangingIsExported { get; set; }
- public ITopLevelNativeMenuExporter Exporter { get; }
+ public ITopLevelNativeMenuExporter? Exporter { get; }
public NativeMenuInfo(TopLevel target)
{
diff --git a/src/Avalonia.Controls/NativeMenu.cs b/src/Avalonia.Controls/NativeMenu.cs
index 58ee99722f..5ff4148e5a 100644
--- a/src/Avalonia.Controls/NativeMenu.cs
+++ b/src/Avalonia.Controls/NativeMenu.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Controls
{
private readonly AvaloniaList _items =
new AvaloniaList { ResetBehavior = ResetBehavior.Remove };
- private NativeMenuItem _parent;
+ private NativeMenuItem? _parent;
[Content]
public IList Items => _items;
@@ -23,7 +23,7 @@ namespace Avalonia.Controls
/// Use this event to add, remove or modify menu items before a menu is
/// shown or a hotkey is pressed.
///
- public event EventHandler NeedsUpdate;
+ public event EventHandler? NeedsUpdate;
///
/// Raised before the menu is opened.
@@ -31,7 +31,7 @@ namespace Avalonia.Controls
///
/// Do not update the menu in this event; use .
///
- public event EventHandler Opening;
+ public event EventHandler? Opening;
///
/// Raised after the menu is closed.
@@ -39,7 +39,7 @@ namespace Avalonia.Controls
///
/// Do not update the menu in this event; use .
///
- public event EventHandler Closed;
+ public event EventHandler? Closed;
public NativeMenu()
{
@@ -68,7 +68,7 @@ namespace Avalonia.Controls
throw new InvalidOperationException("NativeMenuItem already has a parent");
}
- private void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void ItemsChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null)
foreach (NativeMenuItemBase i in e.OldItems)
@@ -78,10 +78,10 @@ namespace Avalonia.Controls
i.Parent = this;
}
- public static readonly DirectProperty ParentProperty =
- AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v);
+ public static readonly DirectProperty ParentProperty =
+ AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v);
- public NativeMenuItem Parent
+ public NativeMenuItem? Parent
{
get => _parent;
set => SetAndRaise(ParentProperty, ref _parent, value);
diff --git a/src/Avalonia.Controls/NativeMenuBar.cs b/src/Avalonia.Controls/NativeMenuBar.cs
index 5d2e1087a7..ae473f8500 100644
--- a/src/Avalonia.Controls/NativeMenuBar.cs
+++ b/src/Avalonia.Controls/NativeMenuBar.cs
@@ -27,9 +27,9 @@ namespace Avalonia.Controls
menuItem.SetValue(EnableMenuItemClickForwardingProperty, enable);
}
- private static void OnMenuItemClick(object sender, RoutedEventArgs e)
+ private static void OnMenuItemClick(object? sender, RoutedEventArgs e)
{
- (((MenuItem)sender).DataContext as INativeMenuItemExporterEventsImplBridge)?.RaiseClicked();
+ (((MenuItem)sender!).DataContext as INativeMenuItemExporterEventsImplBridge)?.RaiseClicked();
}
}
}
diff --git a/src/Avalonia.Controls/NativeMenuItem.cs b/src/Avalonia.Controls/NativeMenuItem.cs
index 4d048f0fb0..265e7119eb 100644
--- a/src/Avalonia.Controls/NativeMenuItem.cs
+++ b/src/Avalonia.Controls/NativeMenuItem.cs
@@ -9,23 +9,23 @@ namespace Avalonia.Controls
{
public class NativeMenuItem : NativeMenuItemBase, INativeMenuItemExporterEventsImplBridge
{
- private string _header;
- private KeyGesture _gesture;
+ private string? _header;
+ private KeyGesture? _gesture;
private bool _isEnabled = true;
- private ICommand _command;
+ private ICommand? _command;
private bool _isChecked = false;
private NativeMenuItemToggleType _toggleType;
- private IBitmap _icon;
+ private IBitmap? _icon;
private readonly CanExecuteChangedSubscriber _canExecuteChangedSubscriber;
- private NativeMenu _menu;
+ private NativeMenu? _menu;
static NativeMenuItem()
{
MenuProperty.Changed.Subscribe(args =>
{
var item = (NativeMenuItem)args.Sender;
- var value = args.NewValue.GetValueOrDefault();
+ var value = args.NewValue.GetValueOrDefault()!;
if (value.Parent != null && value.Parent != item)
throw new InvalidOperationException("NativeMenu already has a parent");
value.Parent = item;
@@ -59,44 +59,44 @@ namespace Avalonia.Controls
Header = header;
}
- public static readonly DirectProperty MenuProperty =
- AvaloniaProperty.RegisterDirect(nameof(Menu), o => o.Menu, (o, v) => o.Menu = v);
+ public static readonly DirectProperty MenuProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Menu), o => o.Menu, (o, v) => o.Menu = v);
[Content]
- public NativeMenu Menu
+ public NativeMenu? Menu
{
get => _menu;
set
{
- if (value.Parent != null && value.Parent != this)
+ if (value != null && value.Parent != null && value.Parent != this)
throw new InvalidOperationException("NativeMenu already has a parent");
SetAndRaise(MenuProperty, ref _menu, value);
}
}
- public static readonly DirectProperty IconProperty =
- AvaloniaProperty.RegisterDirect(nameof(Icon), o => o.Icon, (o, v) => o.Icon = v);
+ public static readonly DirectProperty IconProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Icon), o => o.Icon, (o, v) => o.Icon = v);
- public IBitmap Icon
+ public IBitmap? Icon
{
get => _icon;
set => SetAndRaise(IconProperty, ref _icon, value);
}
- public static readonly DirectProperty HeaderProperty =
- AvaloniaProperty.RegisterDirect(nameof(Header), o => o.Header, (o, v) => o.Header = v);
+ public static readonly DirectProperty HeaderProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Header), o => o.Header, (o, v) => o.Header = v);
- public string Header
+ public string? Header
{
get => _header;
set => SetAndRaise(HeaderProperty, ref _header, value);
}
- public static readonly DirectProperty GestureProperty =
- AvaloniaProperty.RegisterDirect(nameof(Gesture), o => o.Gesture, (o, v) => o.Gesture = v);
+ public static readonly DirectProperty GestureProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Gesture), o => o.Gesture, (o, v) => o.Gesture = v);
- public KeyGesture Gesture
+ public KeyGesture? Gesture
{
get => _gesture;
set => SetAndRaise(GestureProperty, ref _gesture, value);
@@ -126,7 +126,7 @@ namespace Avalonia.Controls
set => SetAndRaise(ToggleTypeProperty, ref _toggleType, value);
}
- public static readonly DirectProperty CommandProperty =
+ public static readonly DirectProperty CommandProperty =
Button.CommandProperty.AddOwner(
menuItem => menuItem.Command,
(menuItem, command) => menuItem.Command = command,
@@ -135,7 +135,7 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty CommandParameterProperty =
+ public static readonly StyledProperty CommandParameterProperty =
Button.CommandParameterProperty.AddOwner();
public static readonly DirectProperty IsEnabledProperty =
@@ -154,7 +154,7 @@ namespace Avalonia.Controls
public bool HasClickHandlers => Click != null;
- public ICommand Command
+ public ICommand? Command
{
get => _command;
set
@@ -175,7 +175,7 @@ namespace Avalonia.Controls
/// Gets or sets the parameter to pass to the property of a
/// .
///
- public object CommandParameter
+ public object? CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
@@ -184,7 +184,7 @@ namespace Avalonia.Controls
///
/// Occurs when a is clicked.
///
- public event EventHandler Click;
+ public event EventHandler? Click;
[Obsolete("Use Click event.")]
public event EventHandler Clicked
diff --git a/src/Avalonia.Controls/NativeMenuItemBase.cs b/src/Avalonia.Controls/NativeMenuItemBase.cs
index 47eb86cdc3..a5e3308e3b 100644
--- a/src/Avalonia.Controls/NativeMenuItemBase.cs
+++ b/src/Avalonia.Controls/NativeMenuItemBase.cs
@@ -4,17 +4,17 @@ namespace Avalonia.Controls
{
public class NativeMenuItemBase : AvaloniaObject
{
- private NativeMenu _parent;
+ private NativeMenu? _parent;
internal NativeMenuItemBase()
{
}
- public static readonly DirectProperty ParentProperty =
- AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v);
+ public static readonly DirectProperty ParentProperty =
+ AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v);
- public NativeMenu Parent
+ public NativeMenu? Parent
{
get => _parent;
set => SetAndRaise(ParentProperty, ref _parent, value);
diff --git a/src/Avalonia.Controls/Notifications/INotification.cs b/src/Avalonia.Controls/Notifications/INotification.cs
index dc69a12887..fa08233097 100644
--- a/src/Avalonia.Controls/Notifications/INotification.cs
+++ b/src/Avalonia.Controls/Notifications/INotification.cs
@@ -10,12 +10,12 @@ namespace Avalonia.Controls.Notifications
///
/// Gets the Title of the notification.
///
- string Title { get; }
+ string? Title { get; }
///
/// Gets the notification message.
///
- string Message { get; }
+ string? Message { get; }
///
/// Gets the of the notification.
@@ -31,11 +31,11 @@ namespace Avalonia.Controls.Notifications
///
/// Gets an Action to be run when the notification is clicked.
///
- Action OnClick { get; }
+ Action? OnClick { get; }
///
/// Gets an Action to be run when the notification is closed.
///
- Action OnClose { get; }
+ Action? OnClose { get; }
}
}
diff --git a/src/Avalonia.Controls/Notifications/Notification.cs b/src/Avalonia.Controls/Notifications/Notification.cs
index 9bb514971b..376df175f3 100644
--- a/src/Avalonia.Controls/Notifications/Notification.cs
+++ b/src/Avalonia.Controls/Notifications/Notification.cs
@@ -21,12 +21,12 @@ namespace Avalonia.Controls.Notifications
/// Use for notifications that will remain open.
/// An Action to call when the notification is clicked.
/// An Action to call when the notification is closed.
- public Notification(string title,
- string message,
+ public Notification(string? title,
+ string? message,
NotificationType type = NotificationType.Information,
TimeSpan? expiration = null,
- Action onClick = null,
- Action onClose = null)
+ Action? onClick = null,
+ Action? onClose = null)
{
Title = title;
Message = message;
@@ -37,10 +37,10 @@ namespace Avalonia.Controls.Notifications
}
///
- public string Title { get; private set; }
+ public string? Title { get; private set; }
///
- public string Message { get; private set; }
+ public string? Message { get; private set; }
///
public NotificationType Type { get; private set; }
@@ -49,9 +49,9 @@ namespace Avalonia.Controls.Notifications
public TimeSpan Expiration { get; private set; }
///
- public Action OnClick { get; private set; }
+ public Action? OnClick { get; private set; }
///
- public Action OnClose { get; private set; }
+ public Action? OnClose { get; private set; }
}
}
diff --git a/src/Avalonia.Controls/Notifications/NotificationCard.cs b/src/Avalonia.Controls/Notifications/NotificationCard.cs
index ad883c8076..a103adf185 100644
--- a/src/Avalonia.Controls/Notifications/NotificationCard.cs
+++ b/src/Avalonia.Controls/Notifications/NotificationCard.cs
@@ -37,8 +37,11 @@ namespace Avalonia.Controls.Notifications
RaiseEvent(new RoutedEventArgs(NotificationClosedEvent));
});
+ // Disabling nullable checking because of https://github.com/dotnet/reactive/issues/1525
+#pragma warning disable CS8620
this.GetObservable(ContentProperty)
.OfType()
+#pragma warning restore CS8620
.Subscribe(x =>
{
switch (x.Type)
@@ -102,7 +105,7 @@ namespace Avalonia.Controls.Notifications
///
/// Raised when the has closed.
///
- public event EventHandler NotificationClosed
+ public event EventHandler? NotificationClosed
{
add { AddHandler(NotificationClosedEvent, value); }
remove { RemoveHandler(NotificationClosedEvent, value); }
@@ -110,13 +113,13 @@ namespace Avalonia.Controls.Notifications
public static bool GetCloseOnClick(Button obj)
{
- Contract.Requires(obj != null);
+ _ = obj ?? throw new ArgumentNullException(nameof(obj));
return (bool)obj.GetValue(CloseOnClickProperty);
}
public static void SetCloseOnClick(Button obj, bool value)
{
- Contract.Requires(obj != null);
+ _ = obj ?? throw new ArgumentNullException(nameof(obj));
obj.SetValue(CloseOnClickProperty, value);
}
@@ -129,7 +132,7 @@ namespace Avalonia.Controls.Notifications
private static void OnCloseOnClickPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
{
var button = (Button)d;
- var value = (bool)e.NewValue;
+ var value = (bool)e.NewValue!;
if (value)
{
button.Click += Button_Click;
@@ -143,10 +146,10 @@ namespace Avalonia.Controls.Notifications
///
/// Called when a button inside the Notification is clicked.
///
- private static void Button_Click(object sender, RoutedEventArgs e)
+ private static void Button_Click(object? sender, RoutedEventArgs e)
{
var btn = sender as ILogical;
- var notification = btn.GetLogicalAncestors().OfType().FirstOrDefault();
+ var notification = btn?.GetLogicalAncestors().OfType().FirstOrDefault();
notification?.Close();
}
diff --git a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
index 8f5c6faf40..9499995da3 100644
--- a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
+++ b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
@@ -17,7 +17,7 @@ namespace Avalonia.Controls.Notifications
[PseudoClasses(":topleft", ":topright", ":bottomleft", ":bottomright")]
public class WindowNotificationManager : TemplatedControl, IManagedNotificationManager, ICustomSimpleHitTest
{
- private IList _items;
+ private IList? _items;
///
/// Defines the property.
@@ -107,7 +107,7 @@ namespace Avalonia.Controls.Notifications
{
notification.OnClose?.Invoke();
- _items.Remove(sender);
+ _items?.Remove(sender);
};
}
@@ -121,9 +121,9 @@ namespace Avalonia.Controls.Notifications
(sender as NotificationCard)?.Close();
};
- _items.Add(notificationControl);
+ _items?.Add(notificationControl);
- if (_items.OfType().Count(i => !i.IsClosing) > MaxItems)
+ if (_items?.OfType().Count(i => !i.IsClosing) > MaxItems)
{
_items.OfType().First(i => !i.IsClosing).Close();
}
diff --git a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
index eba381e5fa..f67377b310 100644
--- a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
+++ b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
@@ -46,15 +46,15 @@ namespace Avalonia.Controls
/// Defines the property.
///
[Obsolete]
- public static readonly DirectProperty CultureInfoProperty =
- AvaloniaProperty.RegisterDirect(nameof(CultureInfo), o => o.CultureInfo,
+ public static readonly DirectProperty CultureInfoProperty =
+ AvaloniaProperty.RegisterDirect(nameof(CultureInfo), o => o.CultureInfo,
(o, v) => o.CultureInfo = v, CultureInfo.CurrentCulture);
///
/// Defines the property.
///
- public static readonly DirectProperty NumberFormatProperty =
- AvaloniaProperty.RegisterDirect(nameof(NumberFormat), o => o.NumberFormat,
+ public static readonly DirectProperty NumberFormatProperty =
+ AvaloniaProperty.RegisterDirect(nameof(NumberFormat), o => o.NumberFormat,
(o, v) => o.NumberFormat = v, NumberFormatInfo.CurrentInfo);
///
@@ -97,8 +97,8 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly DirectProperty TextProperty =
- AvaloniaProperty.RegisterDirect(nameof(Text), o => o.Text, (o, v) => o.Text = v,
+ public static readonly DirectProperty TextProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Text), o => o.Text, (o, v) => o.Text = v,
defaultBindingMode: BindingMode.TwoWay, enableDataValidation: true);
///
@@ -111,8 +111,8 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty WatermarkProperty =
- AvaloniaProperty.Register(nameof(Watermark));
+ public static readonly StyledProperty WatermarkProperty =
+ AvaloniaProperty.Register(nameof(Watermark));
///
/// Defines the property.
@@ -126,27 +126,27 @@ namespace Avalonia.Controls
public static readonly StyledProperty VerticalContentAlignmentProperty =
ContentControl.VerticalContentAlignmentProperty.AddOwner();
- private IDisposable _textBoxTextChangedSubscription;
+ private IDisposable? _textBoxTextChangedSubscription;
private decimal _value;
- private string _text;
+ private string? _text;
private bool _internalValueSet;
private bool _clipValueToMinMax;
private bool _isSyncingTextAndValueProperties;
private bool _isTextChangedFromUI;
- private CultureInfo _cultureInfo;
+ private CultureInfo? _cultureInfo;
private NumberStyles _parsingNumberStyle = NumberStyles.Any;
- private NumberFormatInfo _numberFormat;
+ private NumberFormatInfo? _numberFormat;
///
/// Gets the Spinner template part.
///
- private Spinner Spinner { get; set; }
+ private Spinner? Spinner { get; set; }
///
/// Gets the TextBox template part.
///
- private TextBox TextBox { get; set; }
+ private TextBox? TextBox { get; set; }
///
/// Gets or sets the ability to perform increment/decrement operations via the keyboard, button spinners, or mouse wheel.
@@ -188,7 +188,7 @@ namespace Avalonia.Controls
/// Gets or sets the current CultureInfo.
///
[Obsolete("CultureInfo is obsolete, please use NumberFormat instead.")]
- public CultureInfo CultureInfo
+ public CultureInfo? CultureInfo
{
get { return _cultureInfo; }
set
@@ -202,7 +202,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the current NumberFormatInfo
///
- public NumberFormatInfo NumberFormat
+ public NumberFormatInfo? NumberFormat
{
get { return _numberFormat; }
set { SetAndRaise(NumberFormatProperty, ref _numberFormat, value); }
@@ -265,7 +265,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the formatted string representation of the value.
///
- public string Text
+ public string? Text
{
get { return _text; }
set { SetAndRaise(TextProperty, ref _text, value); }
@@ -287,7 +287,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the object to use as a watermark if the is null.
///
- public string Watermark
+ public string? Watermark
{
get { return GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
@@ -414,7 +414,7 @@ namespace Avalonia.Controls
///
/// The old value.
/// The new value.
- protected virtual void OnCultureInfoChanged(CultureInfo oldValue, CultureInfo newValue)
+ protected virtual void OnCultureInfoChanged(CultureInfo? oldValue, CultureInfo? newValue)
{
if (IsInitialized)
{
@@ -427,7 +427,7 @@ namespace Avalonia.Controls
///
/// The old value.
/// The new value.
- protected virtual void OnNumberFormatChanged(NumberFormatInfo oldValue, NumberFormatInfo newValue)
+ protected virtual void OnNumberFormatChanged(NumberFormatInfo? oldValue, NumberFormatInfo? newValue)
{
if (IsInitialized)
{
@@ -440,7 +440,7 @@ namespace Avalonia.Controls
///
/// The old value.
/// The new value.
- protected virtual void OnFormatStringChanged(string oldValue, string newValue)
+ protected virtual void OnFormatStringChanged(string? oldValue, string? newValue)
{
if (IsInitialized)
{
@@ -510,7 +510,7 @@ namespace Avalonia.Controls
///
/// The old value.
/// The new value.
- protected virtual void OnTextChanged(string oldValue, string newValue)
+ protected virtual void OnTextChanged(string? oldValue, string? newValue)
{
if (IsInitialized)
{
@@ -706,8 +706,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (CultureInfo)e.OldValue;
- var newValue = (CultureInfo)e.NewValue;
+ var oldValue = (CultureInfo?)e.OldValue;
+ var newValue = (CultureInfo?)e.NewValue;
upDown.OnCultureInfoChanged(oldValue, newValue);
}
}
@@ -720,8 +720,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (NumberFormatInfo)e.OldValue;
- var newValue = (NumberFormatInfo)e.NewValue;
+ var oldValue = (NumberFormatInfo?)e.OldValue;
+ var newValue = (NumberFormatInfo?)e.NewValue;
upDown.OnNumberFormatChanged(oldValue, newValue);
}
}
@@ -734,8 +734,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (decimal)e.OldValue;
- var newValue = (decimal)e.NewValue;
+ var oldValue = (decimal)e.OldValue!;
+ var newValue = (decimal)e.NewValue!;
upDown.OnIncrementChanged(oldValue, newValue);
}
}
@@ -748,8 +748,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (string)e.OldValue;
- var newValue = (string)e.NewValue;
+ var oldValue = (string?)e.OldValue;
+ var newValue = (string?)e.NewValue;
upDown.OnFormatStringChanged(oldValue, newValue);
}
}
@@ -762,8 +762,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (bool)e.OldValue;
- var newValue = (bool)e.NewValue;
+ var oldValue = (bool)e.OldValue!;
+ var newValue = (bool)e.NewValue!;
upDown.OnIsReadOnlyChanged(oldValue, newValue);
}
}
@@ -776,8 +776,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (decimal)e.OldValue;
- var newValue = (decimal)e.NewValue;
+ var oldValue = (decimal)e.OldValue!;
+ var newValue = (decimal)e.NewValue!;
upDown.OnMaximumChanged(oldValue, newValue);
}
}
@@ -790,8 +790,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (decimal)e.OldValue;
- var newValue = (decimal)e.NewValue;
+ var oldValue = (decimal)e.OldValue!;
+ var newValue = (decimal)e.NewValue!;
upDown.OnMinimumChanged(oldValue, newValue);
}
}
@@ -804,8 +804,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (string)e.OldValue;
- var newValue = (string)e.NewValue;
+ var oldValue = (string?)e.OldValue;
+ var newValue = (string?)e.NewValue;
upDown.OnTextChanged(oldValue, newValue);
}
}
@@ -818,8 +818,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (decimal)e.OldValue;
- var newValue = (decimal)e.NewValue;
+ var oldValue = (decimal)e.OldValue!;
+ var newValue = (decimal)e.NewValue!;
upDown.OnValueChanged(oldValue, newValue);
}
}
@@ -883,7 +883,7 @@ namespace Avalonia.Controls
}
}
- private void OnSpinnerSpin(object sender, SpinEventArgs e)
+ private void OnSpinnerSpin(object? sender, SpinEventArgs e)
{
if (AllowSpin && !IsReadOnly)
{
@@ -914,9 +914,9 @@ namespace Avalonia.Controls
}
}
- public event EventHandler Spinned;
+ public event EventHandler? Spinned;
- private void TextBoxOnPointerPressed(object sender, PointerPressedEventArgs e)
+ private void TextBoxOnPointerPressed(object? sender, PointerPressedEventArgs e)
{
if (e.Pointer.Captured != Spinner)
{
@@ -933,7 +933,7 @@ namespace Avalonia.Controls
///
/// Raised when the changes.
///
- public event EventHandler ValueChanged
+ public event EventHandler? ValueChanged
{
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
@@ -949,7 +949,7 @@ namespace Avalonia.Controls
///
/// If value should be updated from text.
/// The text.
- private bool SyncTextAndValueProperties(bool updateValueFromText, string text)
+ private bool SyncTextAndValueProperties(bool updateValueFromText, string? text)
{
return SyncTextAndValueProperties(updateValueFromText, text, false);
}
@@ -960,7 +960,7 @@ namespace Avalonia.Controls
/// If value should be updated from text.
/// The text.
/// Force text update.
- private bool SyncTextAndValueProperties(bool updateValueFromText, string text, bool forceTextUpdate)
+ private bool SyncTextAndValueProperties(bool updateValueFromText, string? text, bool forceTextUpdate)
{
if (_isSyncingTextAndValueProperties)
return true;
@@ -1092,7 +1092,7 @@ namespace Avalonia.Controls
///
/// Text to parse.
/// The culture info.
- private static decimal ParsePercent(string text, IFormatProvider cultureInfo)
+ private static decimal ParsePercent(string text, IFormatProvider? cultureInfo)
{
var info = NumberFormatInfo.GetInstance(cultureInfo);
text = text.Replace(info.PercentSymbol, null);
diff --git a/src/Avalonia.Controls/Panel.cs b/src/Avalonia.Controls/Panel.cs
index b182f9d261..482a7fab84 100644
--- a/src/Avalonia.Controls/Panel.cs
+++ b/src/Avalonia.Controls/Panel.cs
@@ -21,7 +21,7 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty BackgroundProperty =
+ public static readonly StyledProperty BackgroundProperty =
Border.BackgroundProperty.AddOwner();
///
@@ -32,7 +32,7 @@ namespace Avalonia.Controls
AffectsRender(BackgroundProperty);
}
- private EventHandler _childIndexChanged;
+ private EventHandler? _childIndexChanged;
///
/// Initializes a new instance of the class.
@@ -51,13 +51,13 @@ namespace Avalonia.Controls
///
/// Gets or Sets Panel background brush.
///
- public IBrush Background
+ public IBrush? Background
{
get { return GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}
- event EventHandler IChildIndexProvider.ChildIndexChanged
+ event EventHandler? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
@@ -110,34 +110,34 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- protected virtual void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ protected virtual void ChildrenChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
List controls;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
- controls = e.NewItems.OfType().ToList();
+ controls = e.NewItems!.OfType().ToList();
LogicalChildren.InsertRange(e.NewStartingIndex, controls);
- VisualChildren.InsertRange(e.NewStartingIndex, e.NewItems.OfType());
+ VisualChildren.InsertRange(e.NewStartingIndex, e.NewItems!.OfType());
break;
case NotifyCollectionChangedAction.Move:
- LogicalChildren.MoveRange(e.OldStartingIndex, e.OldItems.Count, e.NewStartingIndex);
+ LogicalChildren.MoveRange(e.OldStartingIndex, e.OldItems!.Count, e.NewStartingIndex);
VisualChildren.MoveRange(e.OldStartingIndex, e.OldItems.Count, e.NewStartingIndex);
break;
case NotifyCollectionChangedAction.Remove:
- controls = e.OldItems.OfType().ToList();
+ controls = e.OldItems!.OfType().ToList();
LogicalChildren.RemoveAll(controls);
- VisualChildren.RemoveAll(e.OldItems.OfType());
+ VisualChildren.RemoveAll(e.OldItems!.OfType());
break;
case NotifyCollectionChangedAction.Replace:
- for (var i = 0; i < e.OldItems.Count; ++i)
+ for (var i = 0; i < e.OldItems!.Count; ++i)
{
var index = i + e.OldStartingIndex;
- var child = (IControl)e.NewItems[i];
+ var child = (IControl)e.NewItems![i]!;
LogicalChildren[index] = child;
VisualChildren[index] = child;
}
diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
index 18348571bf..23ecdb2e7b 100644
--- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
+++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
@@ -4,12 +4,11 @@ using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
+using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Threading;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Platform
{
///
@@ -68,8 +67,8 @@ namespace Avalonia.Controls.Platform
window.Deactivated += WindowDeactivated;
}
- if (_root is TopLevel tl)
- tl.PlatformImpl.LostFocus += TopLevelLostPlatformFocus;
+ if (_root is TopLevel tl && tl.PlatformImpl is ITopLevelImpl pimpl)
+ pimpl.LostFocus += TopLevelLostPlatformFocus;
_inputManagerSubscription = InputManager?.Process.Subscribe(RawInput);
}
@@ -118,7 +117,7 @@ namespace Avalonia.Controls.Platform
protected static TimeSpan MenuShowDelay { get; } = TimeSpan.FromMilliseconds(400);
- protected internal virtual void GotFocus(object sender, GotFocusEventArgs e)
+ protected internal virtual void GotFocus(object? sender, GotFocusEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -128,7 +127,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void LostFocus(object sender, RoutedEventArgs e)
+ protected internal virtual void LostFocus(object? sender, RoutedEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -138,7 +137,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void KeyDown(object sender, KeyEventArgs e)
+ protected internal virtual void KeyDown(object? sender, KeyEventArgs e)
{
KeyDown(GetMenuItem(e.Source as IControl), e);
}
@@ -267,7 +266,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void AccessKeyPressed(object sender, RoutedEventArgs e)
+ protected internal virtual void AccessKeyPressed(object? sender, RoutedEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -288,7 +287,7 @@ namespace Avalonia.Controls.Platform
e.Handled = true;
}
- protected internal virtual void PointerEnter(object sender, PointerEventArgs e)
+ protected internal virtual void PointerEnter(object? sender, PointerEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -333,7 +332,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void PointerLeave(object sender, PointerEventArgs e)
+ protected internal virtual void PointerLeave(object? sender, PointerEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -368,12 +367,12 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void PointerPressed(object sender, PointerPressedEventArgs e)
+ protected internal virtual void PointerPressed(object? sender, PointerPressedEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
- var visual = (IVisual)sender;
- if (e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed && item?.HasSubMenu == true)
+ if (sender is IVisual visual &&
+ e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed && item?.HasSubMenu == true)
{
if (item.IsSubMenuOpen)
{
@@ -399,7 +398,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void PointerReleased(object sender, PointerReleasedEventArgs e)
+ protected internal virtual void PointerReleased(object? sender, PointerReleasedEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -410,7 +409,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void MenuOpened(object sender, RoutedEventArgs e)
+ protected internal virtual void MenuOpened(object? sender, RoutedEventArgs e)
{
if (e.Source == Menu)
{
@@ -428,20 +427,18 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void RootPointerPressed(object sender, PointerPressedEventArgs e)
+ protected internal virtual void RootPointerPressed(object? sender, PointerPressedEventArgs e)
{
if (Menu?.IsOpen == true)
{
- var control = e.Source as ILogical;
-
- if (!Menu.IsLogicalAncestorOf(control))
+ if (e.Source is ILogical control && !Menu.IsLogicalAncestorOf(control))
{
Menu.Close();
}
}
}
- protected internal virtual void WindowDeactivated(object sender, EventArgs e)
+ protected internal virtual void WindowDeactivated(object? sender, EventArgs e)
{
Menu?.Close();
}
diff --git a/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs b/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs
index e958b7aa15..2a401ad912 100644
--- a/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs
+++ b/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs
@@ -6,7 +6,7 @@ namespace Avalonia.Platform
public class ExportWindowingSubsystemAttribute : Attribute
{
public ExportWindowingSubsystemAttribute(OperatingSystemType requiredRuntimePlatform, int priority, string name, Type initializationType,
- string initializationMethod, Type environmentChecker = null)
+ string initializationMethod, Type? environmentChecker = null)
{
Name = name;
InitializationType = initializationType;
@@ -17,7 +17,7 @@ namespace Avalonia.Platform
}
public string InitializationMethod { get; private set; }
- public Type EnvironmentChecker { get; }
+ public Type? EnvironmentChecker { get; }
public Type InitializationType { get; private set; }
public string Name { get; private set; }
public int Priority { get; private set; }
diff --git a/src/Avalonia.Controls/Platform/INativeControlHostImpl.cs b/src/Avalonia.Controls/Platform/INativeControlHostImpl.cs
index c6b1d09849..df13613848 100644
--- a/src/Avalonia.Controls/Platform/INativeControlHostImpl.cs
+++ b/src/Avalonia.Controls/Platform/INativeControlHostImpl.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using Avalonia.Platform;
using Avalonia.VisualTree;
@@ -19,7 +20,8 @@ namespace Avalonia.Controls.Platform
public interface INativeControlHostControlTopLevelAttachment : IDisposable
{
- INativeControlHostImpl AttachedTo { get; set; }
+ INativeControlHostImpl? AttachedTo { get; set; }
+
bool IsCompatibleWith(INativeControlHostImpl host);
void HideWithSize(Size size);
void ShowInBounds(Rect rect);
@@ -27,6 +29,6 @@ namespace Avalonia.Controls.Platform
public interface ITopLevelImplWithNativeControlHost
{
- INativeControlHostImpl NativeControlHost { get; }
+ INativeControlHostImpl? NativeControlHost { get; }
}
}
diff --git a/src/Avalonia.Controls/Platform/ISystemDialogImpl.cs b/src/Avalonia.Controls/Platform/ISystemDialogImpl.cs
index 7bd13ecdb1..1685a6a38c 100644
--- a/src/Avalonia.Controls/Platform/ISystemDialogImpl.cs
+++ b/src/Avalonia.Controls/Platform/ISystemDialogImpl.cs
@@ -1,7 +1,5 @@
using System.Threading.Tasks;
-#nullable enable
-
namespace Avalonia.Controls.Platform
{
///
diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs
index f4f4d29168..80434882f7 100644
--- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs
+++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs
@@ -82,27 +82,27 @@ namespace Avalonia.Platform
///
/// Gets or sets a method called when the toplevel receives input.
///
- Action Input { get; set; }
+ Action? Input { get; set; }
///
/// Gets or sets a method called when the toplevel requires painting.
///
- Action Paint { get; set; }
+ Action? Paint { get; set; }
///
/// Gets or sets a method called when the toplevel is resized.
///
- Action Resized { get; set; }
+ Action? Resized { get; set; }
///
/// Gets or sets a method called when the toplevel's scaling changes.
///
- Action ScalingChanged { get; set; }
+ Action? ScalingChanged { get; set; }
///
/// Gets or sets a method called when the toplevel's TransparencyLevel changes.
///
- Action TransparencyLevelChanged { get; set; }
+ Action? TransparencyLevelChanged { get; set; }
///
/// Creates a new renderer for the toplevel.
@@ -138,17 +138,17 @@ namespace Avalonia.Platform
/// Sets the cursor associated with the toplevel.
///
/// The cursor. Use null for default cursor
- void SetCursor(ICursorImpl cursor);
+ void SetCursor(ICursorImpl? cursor);
///
/// Gets or sets a method called when the underlying implementation is destroyed.
///
- Action Closed { get; set; }
+ Action? Closed { get; set; }
///
/// Gets or sets a method called when the input focus is lost.
///
- Action LostFocus { get; set; }
+ Action? LostFocus { get; set; }
///
/// Gets a mouse device associated with toplevel
@@ -156,7 +156,7 @@ namespace Avalonia.Platform
[CanBeNull]
IMouseDevice MouseDevice { get; }
- IPopupImpl CreatePopup();
+ IPopupImpl? CreatePopup();
///
/// Sets the hint of the TopLevel.
diff --git a/src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs b/src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs
index 9c29415a6a..bafb973765 100644
--- a/src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs
+++ b/src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs
@@ -6,6 +6,6 @@ namespace Avalonia.Controls.Platform
{
public interface ITopLevelImplWithTextInputMethod : ITopLevelImpl
{
- public ITextInputMethodImpl TextInputMethod { get; }
+ public ITextInputMethodImpl? TextInputMethod { get; }
}
}
diff --git a/src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs b/src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs
index 9b779054f3..9e72a40439 100644
--- a/src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs
+++ b/src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs
@@ -1,8 +1,6 @@
using System;
using Avalonia.Platform;
-#nullable enable
-
namespace Avalonia.Controls.Platform
{
public interface INativeMenuExporter
@@ -24,6 +22,6 @@ namespace Avalonia.Controls.Platform
public interface ITopLevelImplWithNativeMenuExporter : ITopLevelImpl
{
- ITopLevelNativeMenuExporter NativeMenuExporter { get; }
+ ITopLevelNativeMenuExporter? NativeMenuExporter { get; }
}
}
diff --git a/src/Avalonia.Controls/Platform/ITrayIconImpl.cs b/src/Avalonia.Controls/Platform/ITrayIconImpl.cs
index 9768d149f0..289b569645 100644
--- a/src/Avalonia.Controls/Platform/ITrayIconImpl.cs
+++ b/src/Avalonia.Controls/Platform/ITrayIconImpl.cs
@@ -1,8 +1,6 @@
using System;
using Avalonia.Controls.Platform;
-#nullable enable
-
namespace Avalonia.Platform
{
public interface ITrayIconImpl : IDisposable
diff --git a/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs b/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
index 5172569726..ff83e007b4 100644
--- a/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
+++ b/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
@@ -29,7 +29,7 @@ namespace Avalonia.Platform
///
/// Gets or sets a method called when the window's position changes.
///
- Action PositionChanged { get; set; }
+ Action? PositionChanged { get; set; }
///
/// Activates the window.
@@ -39,12 +39,12 @@ namespace Avalonia.Platform
///
/// Gets or sets a method called when the window is deactivated (loses focus).
///
- Action Deactivated { get; set; }
+ Action? Deactivated { get; set; }
///
/// Gets or sets a method called when the window is activated (receives focus).
///
- Action Activated { get; set; }
+ Action? Activated { get; set; }
///
/// Gets the platform window handle.
diff --git a/src/Avalonia.Controls/Platform/IWindowImpl.cs b/src/Avalonia.Controls/Platform/IWindowImpl.cs
index 17a90eddfe..d4be4f9f45 100644
--- a/src/Avalonia.Controls/Platform/IWindowImpl.cs
+++ b/src/Avalonia.Controls/Platform/IWindowImpl.cs
@@ -23,7 +23,7 @@ namespace Avalonia.Platform
/// Sets the title of the window.
///
/// The title.
- void SetTitle(string title);
+ void SetTitle(string? title);
///
/// Sets the parent of the window.
@@ -50,7 +50,7 @@ namespace Avalonia.Platform
///
/// Sets the icon of this window.
///
- void SetIcon(IWindowIconImpl icon);
+ void SetIcon(IWindowIconImpl? icon);
///
/// Enables or disables the taskbar icon
diff --git a/src/Avalonia.Controls/Platform/IWindowingPlatform.cs b/src/Avalonia.Controls/Platform/IWindowingPlatform.cs
index 21882b1271..fa26fe8fdd 100644
--- a/src/Avalonia.Controls/Platform/IWindowingPlatform.cs
+++ b/src/Avalonia.Controls/Platform/IWindowingPlatform.cs
@@ -1,5 +1,3 @@
-#nullable enable
-
namespace Avalonia.Platform
{
public interface IWindowingPlatform
diff --git a/src/Avalonia.Controls/Platform/InProcessDragSource.cs b/src/Avalonia.Controls/Platform/InProcessDragSource.cs
index 414c523e0d..209d5f03dc 100644
--- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs
+++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs
@@ -20,17 +20,17 @@ namespace Avalonia.Platform
private readonly Subject _result = new Subject();
private DragDropEffects _allowedEffects;
- private IDataObject _draggedData;
- private IInputRoot _lastRoot;
+ private IDataObject? _draggedData;
+ private IInputRoot? _lastRoot;
private Point _lastPosition;
private StandardCursorType _lastCursorType;
- private object _originalCursor;
+ private object? _originalCursor;
private RawInputModifiers? _initialInputModifiers;
public InProcessDragSource()
{
- _inputManager = AvaloniaLocator.Current.GetService();
- _dragDrop = AvaloniaLocator.Current.GetService();
+ _inputManager = AvaloniaLocator.Current.GetRequiredService();
+ _dragDrop = AvaloniaLocator.Current.GetRequiredService();
}
public async Task DoDragDrop(PointerEventArgs triggerEvent, IDataObject data, DragDropEffects allowedEffects)
@@ -60,9 +60,9 @@ namespace Avalonia.Platform
{
_lastPosition = pt;
- RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects, modifiers);
+ RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData!, _allowedEffects, modifiers);
var tl = root.GetSelfAndVisualAncestors().OfType().FirstOrDefault();
- tl.PlatformImpl?.Input(rawEvent);
+ tl?.PlatformImpl?.Input?.Invoke(rawEvent);
var effect = GetPreferredEffect(rawEvent.Effects & _allowedEffects, modifiers);
UpdateCursor(root, effect);
@@ -91,7 +91,7 @@ namespace Avalonia.Platform
return StandardCursorType.No;
}
- private void UpdateCursor(IInputRoot root, DragDropEffects effect)
+ private void UpdateCursor(IInputRoot? root, DragDropEffects effect)
{
if (_lastRoot != root)
{
diff --git a/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs b/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs
index 6a95c2e047..4e5908456e 100644
--- a/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs
+++ b/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs
@@ -36,7 +36,7 @@ namespace Avalonia.Controls.Platform
private readonly DispatcherPriority _priority;
private readonly TimeSpan _interval;
private readonly Action _tick;
- private Timer _timer;
+ private Timer? _timer;
private GCHandle _handle;
public TimerImpl(DispatcherPriority priority, TimeSpan interval, Action tick)
@@ -48,7 +48,7 @@ namespace Avalonia.Controls.Platform
_handle = GCHandle.Alloc(_timer);
}
- private void OnTimer(object state)
+ private void OnTimer(object? state)
{
if (_timer == null)
return;
@@ -66,7 +66,7 @@ namespace Avalonia.Controls.Platform
public void Dispose()
{
_handle.Free();
- _timer.Dispose();
+ _timer?.Dispose();
_timer = null;
}
}
@@ -84,9 +84,9 @@ namespace Avalonia.Controls.Platform
[ThreadStatic] private static bool TlsCurrentThreadIsLoopThread;
public bool CurrentThreadIsLoopThread => TlsCurrentThreadIsLoopThread;
- public event Action Signaled;
+ public event Action? Signaled;
#pragma warning disable CS0067
- public event Action Tick;
+ public event Action? Tick;
#pragma warning restore CS0067
}
diff --git a/src/Avalonia.Controls/Platform/MountedDriveInfo.cs b/src/Avalonia.Controls/Platform/MountedDriveInfo.cs
index 9448f16c38..f3104e4360 100644
--- a/src/Avalonia.Controls/Platform/MountedDriveInfo.cs
+++ b/src/Avalonia.Controls/Platform/MountedDriveInfo.cs
@@ -7,14 +7,14 @@ namespace Avalonia.Controls.Platform
///
public class MountedVolumeInfo : IEquatable
{
- public string VolumeLabel { get; set; }
- public string VolumePath { get; set; }
+ public string? VolumeLabel { get; set; }
+ public string? VolumePath { get; set; }
public ulong VolumeSizeBytes { get; set; }
- public bool Equals(MountedVolumeInfo other)
+ public bool Equals(MountedVolumeInfo? other)
{
- return this.VolumeSizeBytes.Equals(other.VolumeSizeBytes) &&
- this.VolumePath.Equals(other.VolumePath) &&
+ return this.VolumeSizeBytes.Equals(other?.VolumeSizeBytes) &&
+ Equals(this.VolumePath, other.VolumePath) &&
(this.VolumeLabel ?? string.Empty).Equals(other.VolumeLabel ?? string.Empty);
}
}
diff --git a/src/Avalonia.Controls/Platform/PlatformManager.cs b/src/Avalonia.Controls/Platform/PlatformManager.cs
index 8e9f64b3ad..ee62316922 100644
--- a/src/Avalonia.Controls/Platform/PlatformManager.cs
+++ b/src/Avalonia.Controls/Platform/PlatformManager.cs
@@ -2,8 +2,6 @@ using System;
using System.Reactive.Disposables;
using Avalonia.Platform;
-#nullable enable
-
namespace Avalonia.Controls.Platform
{
public static partial class PlatformManager
diff --git a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
index 81f43865a7..8883c9e8ce 100644
--- a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
@@ -35,7 +35,7 @@ namespace Avalonia.Controls.Presenters
Carousel.PageTransitionProperty.AddOwner();
private int _selectedIndex = -1;
- private Task _currentTransition;
+ private Task? _currentTransition;
private int _queuedTransitionIndex = -1;
///
@@ -126,7 +126,7 @@ namespace Avalonia.Controls.Presenters
break;
case NotifyCollectionChangedAction.Replace:
if (e.OldStartingIndex > SelectedIndex ||
- e.OldStartingIndex + e.OldItems.Count - 1 < SelectedIndex)
+ e.OldStartingIndex + e.OldItems!.Count - 1 < SelectedIndex)
{
return;
}
@@ -170,13 +170,13 @@ namespace Avalonia.Controls.Presenters
{
if (fromIndex != toIndex)
{
- var generator = ItemContainerGenerator;
- IControl from = null;
- IControl to = null;
+ var generator = ItemContainerGenerator!;
+ IControl? from = null;
+ IControl? to = null;
if (fromIndex != -1)
{
- from = ItemContainerGenerator.ContainerFromIndex(fromIndex);
+ from = generator.ContainerFromIndex(fromIndex);
}
if (toIndex != -1)
@@ -186,7 +186,7 @@ namespace Avalonia.Controls.Presenters
if (PageTransition != null && (from != null || to != null))
{
- await PageTransition.Start((Visual)from, (Visual)to, fromIndex < toIndex, default);
+ await PageTransition.Start((Visual?)from, (Visual?)to, fromIndex < toIndex, default);
}
else if (to != null)
{
@@ -197,7 +197,7 @@ namespace Avalonia.Controls.Presenters
{
if (IsVirtualized)
{
- Panel.Children.Remove(from);
+ Panel!.Children.Remove(from);
generator.Dematerialize(fromIndex, 1);
}
else
@@ -208,15 +208,15 @@ namespace Avalonia.Controls.Presenters
}
}
- private IControl GetOrCreateContainer(int index)
+ private IControl? GetOrCreateContainer(int index)
{
var container = ItemContainerGenerator.ContainerFromIndex(index);
if (container == null && IsVirtualized)
{
- var item = Items.Cast().ElementAt(index);
+ var item = Items!.Cast().ElementAt(index);
var materialized = ItemContainerGenerator.Materialize(index, item);
- Panel.Children.Add(materialized.ContainerControl);
+ Panel!.Children.Add(materialized.ContainerControl);
container = materialized.ContainerControl;
}
@@ -245,8 +245,8 @@ namespace Avalonia.Controls.Presenters
{
if (_currentTransition == null)
{
- int fromIndex = (int)e.OldValue;
- int toIndex = (int)e.NewValue;
+ int fromIndex = (int)e.OldValue!;
+ int toIndex = (int)e.NewValue!;
for (;;)
{
@@ -268,7 +268,7 @@ namespace Avalonia.Controls.Presenters
}
else
{
- _queuedTransitionIndex = (int)e.NewValue;
+ _queuedTransitionIndex = (int)e.NewValue!;
}
}
}
diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs
index 1a46d84558..9886dd913a 100644
--- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs
@@ -20,13 +20,13 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly StyledProperty BackgroundProperty =
+ public static readonly StyledProperty BackgroundProperty =
Border.BackgroundProperty.AddOwner();
///
/// Defines the property.
///
- public static readonly StyledProperty BorderBrushProperty =
+ public static readonly StyledProperty BorderBrushProperty =
Border.BorderBrushProperty.AddOwner();
///
@@ -50,21 +50,21 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly DirectProperty ChildProperty =
- AvaloniaProperty.RegisterDirect(
+ public static readonly DirectProperty ChildProperty =
+ AvaloniaProperty.RegisterDirect(
nameof(Child),
o => o.Child);
///
/// Defines the property.
///
- public static readonly StyledProperty ContentProperty =
+ public static readonly StyledProperty ContentProperty =
ContentControl.ContentProperty.AddOwner();
///
/// Defines the property.
///
- public static readonly StyledProperty ContentTemplateProperty =
+ public static readonly StyledProperty ContentTemplateProperty =
ContentControl.ContentTemplateProperty.AddOwner();
///
@@ -93,9 +93,9 @@ namespace Avalonia.Controls.Presenters
nameof(RecognizesAccessKey),
cp => cp.RecognizesAccessKey, (cp, value) => cp.RecognizesAccessKey = value);
- private IControl _child;
+ private IControl? _child;
private bool _createdChild;
- private IRecyclingDataTemplate _recyclingDataTemplate;
+ private IRecyclingDataTemplate? _recyclingDataTemplate;
private readonly BorderRenderHelper _borderRenderer = new BorderRenderHelper();
private bool _recognizesAccessKey;
@@ -120,7 +120,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets a brush with which to paint the background.
///
- public IBrush Background
+ public IBrush? Background
{
get { return GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
@@ -129,7 +129,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets a brush with which to paint the border.
///
- public IBrush BorderBrush
+ public IBrush? BorderBrush
{
get { return GetValue(BorderBrushProperty); }
set { SetValue(BorderBrushProperty, value); }
@@ -165,7 +165,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets the control displayed by the presenter.
///
- public IControl Child
+ public IControl? Child
{
get { return _child; }
private set { SetAndRaise(ChildProperty, ref _child, value); }
@@ -175,7 +175,7 @@ namespace Avalonia.Controls.Presenters
/// Gets or sets the content to be displayed by the presenter.
///
[DependsOn(nameof(ContentTemplate))]
- public object Content
+ public object? Content
{
get { return GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
@@ -184,7 +184,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets the data template used to display the content of the control.
///
- public IDataTemplate ContentTemplate
+ public IDataTemplate? ContentTemplate
{
get { return GetValue(ContentTemplateProperty); }
set { SetValue(ContentTemplateProperty, value); }
@@ -229,7 +229,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets the host content control.
///
- internal IContentPresenterHost Host { get; private set; }
+ internal IContentPresenterHost? Host { get; private set; }
///
public sealed override void ApplyTemplate()
@@ -321,7 +321,7 @@ namespace Avalonia.Controls.Presenters
/// Creates the child control.
///
/// The child control or null.
- protected virtual IControl CreateChild()
+ protected virtual IControl? CreateChild()
{
var content = Content;
var oldChild = Child;
diff --git a/src/Avalonia.Controls/Presenters/IContentPresenter.cs b/src/Avalonia.Controls/Presenters/IContentPresenter.cs
index b1e64c2f25..ab4d61e3bd 100644
--- a/src/Avalonia.Controls/Presenters/IContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/IContentPresenter.cs
@@ -11,11 +11,11 @@ namespace Avalonia.Controls.Presenters
///
/// Gets the control displayed by the presenter.
///
- IControl Child { get; }
+ IControl? Child { get; }
///
/// Gets or sets the content to be displayed by the presenter.
///
- object Content { get; set; }
+ object? Content { get; set; }
}
}
diff --git a/src/Avalonia.Controls/Presenters/IItemsPresenter.cs b/src/Avalonia.Controls/Presenters/IItemsPresenter.cs
index 873f0d756f..e7da3d4618 100644
--- a/src/Avalonia.Controls/Presenters/IItemsPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/IItemsPresenter.cs
@@ -5,9 +5,9 @@ namespace Avalonia.Controls.Presenters
{
public interface IItemsPresenter : IPresenter
{
- IEnumerable Items { get; set; }
+ IEnumerable? Items { get; set; }
- IPanel Panel { get; }
+ IPanel? Panel { get; }
void ItemsChanged(NotifyCollectionChangedEventArgs e);
diff --git a/src/Avalonia.Controls/Presenters/ItemContainerSync.cs b/src/Avalonia.Controls/Presenters/ItemContainerSync.cs
index 6e72908e6b..81184f719e 100644
--- a/src/Avalonia.Controls/Presenters/ItemContainerSync.cs
+++ b/src/Avalonia.Controls/Presenters/ItemContainerSync.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Controls.Presenters
{
public static void ItemsChanged(
ItemsPresenterBase owner,
- IEnumerable items,
+ IEnumerable? items,
NotifyCollectionChangedEventArgs e)
{
var generator = owner.ItemContainerGenerator;
@@ -24,7 +24,7 @@ namespace Avalonia.Controls.Presenters
void Add()
{
- if (e.NewStartingIndex + e.NewItems.Count < items.Count())
+ if (e.NewStartingIndex + e.NewItems!.Count < items!.Count())
{
generator.InsertSpace(e.NewStartingIndex, e.NewItems.Count);
}
@@ -34,7 +34,7 @@ namespace Avalonia.Controls.Presenters
void Remove()
{
- RemoveContainers(panel, generator.RemoveRange(e.OldStartingIndex, e.OldItems.Count));
+ RemoveContainers(panel, generator.RemoveRange(e.OldStartingIndex, e.OldItems!.Count));
}
switch (e.Action)
@@ -48,8 +48,8 @@ namespace Avalonia.Controls.Presenters
break;
case NotifyCollectionChangedAction.Replace:
- RemoveContainers(panel, generator.Dematerialize(e.OldStartingIndex, e.OldItems.Count));
- var containers = AddContainers(owner, e.NewStartingIndex, e.NewItems);
+ RemoveContainers(panel, generator.Dematerialize(e.OldStartingIndex, e.OldItems!.Count));
+ var containers = AddContainers(owner, e.NewStartingIndex, e.NewItems!);
var i = e.NewStartingIndex;
@@ -92,7 +92,7 @@ namespace Avalonia.Controls.Presenters
if (i.ContainerControl != null)
{
- if (i.Index < panel.Children.Count)
+ if (i.Index < panel!.Children.Count)
{
// TODO: This will insert at the wrong place when there are null items.
panel.Children.Insert(i.Index, i.ContainerControl);
diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
index be2b1e86f0..343c72f742 100644
--- a/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
+++ b/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
@@ -16,7 +16,7 @@ namespace Avalonia.Controls.Presenters
internal abstract class ItemVirtualizer : IVirtualizingController, IDisposable
{
private double _crossAxisOffset;
- private IDisposable _subscriptions;
+ private IDisposable? _subscriptions;
///
/// Initializes a new instance of the class.
@@ -46,12 +46,12 @@ namespace Avalonia.Controls.Presenters
///
/// Gets the which will host the items.
///
- public IVirtualizingPanel VirtualizingPanel => Owner.Panel as IVirtualizingPanel;
+ public IVirtualizingPanel? VirtualizingPanel => Owner.Panel as IVirtualizingPanel;
///
/// Gets the items to display.
///
- public IEnumerable Items { get; private set; }
+ public IEnumerable? Items { get; private set; }
///
/// Gets the number of items in .
@@ -100,11 +100,11 @@ namespace Avalonia.Controls.Presenters
{
get
{
- if (IsLogicalScrollEnabled)
+ if (IsLogicalScrollEnabled && Owner.Panel is Panel panel)
{
return Vertical ?
- new Size(Owner.Panel.DesiredSize.Width, ExtentValue) :
- new Size(ExtentValue, Owner.Panel.DesiredSize.Height);
+ new Size(panel.DesiredSize.Width, ExtentValue) :
+ new Size(ExtentValue, panel.DesiredSize.Height);
}
return default;
@@ -118,11 +118,11 @@ namespace Avalonia.Controls.Presenters
{
get
{
- if (IsLogicalScrollEnabled)
+ if (IsLogicalScrollEnabled && Owner.Panel is Panel panel)
{
return Vertical ?
- new Size(Owner.Panel.Bounds.Width, ViewportValue) :
- new Size(ViewportValue, Owner.Panel.Bounds.Height);
+ new Size(panel.Bounds.Width, ViewportValue) :
+ new Size(ViewportValue, panel.Bounds.Height);
}
return default;
@@ -177,7 +177,7 @@ namespace Avalonia.Controls.Presenters
///
/// The items presenter.
/// An .
- public static ItemVirtualizer Create(ItemsPresenter owner)
+ public static ItemVirtualizer? Create(ItemsPresenter owner)
{
if (owner.Panel == null)
{
@@ -186,7 +186,7 @@ namespace Avalonia.Controls.Presenters
var virtualizingPanel = owner.Panel as IVirtualizingPanel;
var scrollContentPresenter = owner.Parent as IScrollable;
- ItemVirtualizer result = null;
+ ItemVirtualizer? result = null;
if (virtualizingPanel != null && scrollContentPresenter is object)
{
@@ -218,7 +218,7 @@ namespace Avalonia.Controls.Presenters
/// The desired size for the control.
public virtual Size MeasureOverride(Size availableSize)
{
- Owner.Panel.Measure(availableSize);
+ Owner.Panel!.Measure(availableSize);
return Owner.Panel.DesiredSize;
}
@@ -232,12 +232,12 @@ namespace Avalonia.Controls.Presenters
if (VirtualizingPanel != null)
{
VirtualizingPanel.CrossAxisOffset = _crossAxisOffset;
- Owner.Panel.Arrange(new Rect(finalSize));
+ Owner.Panel!.Arrange(new Rect(finalSize));
}
else
{
var origin = Vertical ? new Point(-_crossAxisOffset, 0) : new Point(0, _crossAxisOffset);
- Owner.Panel.Arrange(new Rect(origin, finalSize));
+ Owner.Panel!.Arrange(new Rect(origin, finalSize));
}
return finalSize;
@@ -254,7 +254,7 @@ namespace Avalonia.Controls.Presenters
/// The movement direction.
/// The control from which movement begins.
/// The control.
- public virtual IControl GetControlInDirection(NavigationDirection direction, IControl from)
+ public virtual IControl? GetControlInDirection(NavigationDirection direction, IControl from)
{
return null;
}
@@ -266,10 +266,10 @@ namespace Avalonia.Controls.Presenters
///
/// The items.
/// A description of the change.
- public virtual void ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
+ public virtual void ItemsChanged(IEnumerable? items, NotifyCollectionChangedEventArgs e)
{
Items = items;
- ItemCount = items.Count();
+ ItemCount = items?.Count() ?? 0;
}
///
diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs
index 275f4d418e..c1b6842b88 100644
--- a/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs
+++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs
@@ -54,7 +54,7 @@ namespace Avalonia.Controls.Presenters
}
///
- public override void ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
+ public override void ItemsChanged(IEnumerable? items, NotifyCollectionChangedEventArgs e)
{
base.ItemsChanged(items, e);
ItemContainerSync.ItemsChanged(Owner, items, e);
@@ -86,7 +86,7 @@ namespace Avalonia.Controls.Presenters
if (i.ContainerControl != null)
{
- if (i.Index < panel.Children.Count)
+ if (i.Index < panel!.Children.Count)
{
// TODO: This will insert at the wrong place when there are null items.
panel.Children.Insert(i.Index, i.ContainerControl);
@@ -102,18 +102,5 @@ namespace Avalonia.Controls.Presenters
return result;
}
-
- private void RemoveContainers(IEnumerable items)
- {
- var panel = Owner.Panel;
-
- foreach (var i in items)
- {
- if (i.ContainerControl != null)
- {
- panel.Children.Remove(i.ContainerControl);
- }
- }
- }
}
}
diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
index 7d50ef7d33..a34e5d6438 100644
--- a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
+++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
@@ -108,6 +108,8 @@ namespace Avalonia.Controls.Presenters
}
}
+ public new IVirtualizingPanel VirtualizingPanel => base.VirtualizingPanel!;
+
///
public override Size MeasureOverride(Size availableSize)
{
@@ -151,7 +153,7 @@ namespace Avalonia.Controls.Presenters
}
}
- Owner.Panel.Measure(availableSize);
+ Owner.Panel!.Measure(availableSize);
return Owner.Panel.DesiredSize;
}
@@ -163,7 +165,7 @@ namespace Avalonia.Controls.Presenters
}
///
- public override void ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
+ public override void ItemsChanged(IEnumerable? items, NotifyCollectionChangedEventArgs e)
{
base.ItemsChanged(items, e);
@@ -224,7 +226,7 @@ namespace Avalonia.Controls.Presenters
InvalidateScroll();
}
- public override IControl GetControlInDirection(NavigationDirection direction, IControl from)
+ public override IControl? GetControlInDirection(NavigationDirection direction, IControl from)
{
var generator = Owner.ItemContainerGenerator;
var panel = VirtualizingPanel;
@@ -331,7 +333,7 @@ namespace Avalonia.Controls.Presenters
}
}
- var materialized = generator.Materialize(index, Items.ElementAt(index));
+ var materialized = generator.Materialize(index, Items.ElementAt(index)!);
if (step == 1)
{
@@ -382,7 +384,7 @@ namespace Avalonia.Controls.Presenters
foreach (var container in containers)
{
- var item = Items.ElementAt(itemIndex);
+ var item = Items!.ElementAt(itemIndex)!;
if (!object.Equals(container.Item, item))
{
@@ -427,7 +429,7 @@ namespace Avalonia.Controls.Presenters
var oldItemIndex = FirstIndex + first + i;
var newItemIndex = oldItemIndex + delta + ((panel.Children.Count - count) * sign);
- var item = Items.ElementAt(newItemIndex);
+ var item = Items!.ElementAt(newItemIndex)!;
if (!generator.TryRecycle(oldItemIndex, newItemIndex, item))
{
@@ -506,7 +508,7 @@ namespace Avalonia.Controls.Presenters
///
/// The item index.
/// The container that was brought into view.
- private IControl ScrollIntoViewCore(int index)
+ private IControl? ScrollIntoViewCore(int index)
{
var panel = VirtualizingPanel;
var generator = Owner.ItemContainerGenerator;
diff --git a/src/Avalonia.Controls/Presenters/ItemsPresenter.cs b/src/Avalonia.Controls/Presenters/ItemsPresenter.cs
index 80c9e972d5..2c04b03faf 100644
--- a/src/Avalonia.Controls/Presenters/ItemsPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ItemsPresenter.cs
@@ -21,7 +21,7 @@ namespace Avalonia.Controls.Presenters
private bool _canHorizontallyScroll;
private bool _canVerticallyScroll;
- private EventHandler _scrollInvalidated;
+ private EventHandler? _scrollInvalidated;
///
/// Initializes static members of the class.
@@ -96,7 +96,7 @@ namespace Avalonia.Controls.Presenters
Size IScrollable.Viewport => Virtualizer?.Viewport ?? Bounds.Size;
///
- event EventHandler ILogicalScrollable.ScrollInvalidated
+ event EventHandler? ILogicalScrollable.ScrollInvalidated
{
add => _scrollInvalidated += value;
remove => _scrollInvalidated -= value;
@@ -108,7 +108,7 @@ namespace Avalonia.Controls.Presenters
///
Size ILogicalScrollable.PageScrollSize => Virtualizer?.Viewport ?? new Size(16, 16);
- internal ItemVirtualizer Virtualizer { get; private set; }
+ internal ItemVirtualizer? Virtualizer { get; private set; }
///
bool ILogicalScrollable.BringIntoView(IControl target, Rect targetRect)
@@ -117,7 +117,7 @@ namespace Avalonia.Controls.Presenters
}
///
- IControl ILogicalScrollable.GetControlInDirection(NavigationDirection direction, IControl from)
+ IControl? ILogicalScrollable.GetControlInDirection(NavigationDirection direction, IControl from)
{
return Virtualizer?.GetControlInDirection(direction, from);
}
@@ -152,7 +152,7 @@ namespace Avalonia.Controls.Presenters
_scrollInvalidated?.Invoke(this, EventArgs.Empty);
KeyboardNavigation.SetTabNavigation(
- (InputElement)Panel,
+ (InputElement)panel,
KeyboardNavigation.GetTabNavigation(this));
}
diff --git a/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs b/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs
index aeead7bfd0..f938c8d437 100644
--- a/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs
+++ b/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs
@@ -18,7 +18,7 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly DirectProperty ItemsProperty =
+ public static readonly DirectProperty ItemsProperty =
ItemsControl.ItemsProperty.AddOwner(o => o.Items, (o, v) => o.Items = v);
///
@@ -30,14 +30,14 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly StyledProperty ItemTemplateProperty =
+ public static readonly StyledProperty ItemTemplateProperty =
ItemsControl.ItemTemplateProperty.AddOwner();
- private IEnumerable _items;
- private IDisposable _itemsSubscription;
+ private IEnumerable? _items;
+ private IDisposable? _itemsSubscription;
private bool _createdPanel;
- private IItemContainerGenerator _generator;
- private EventHandler _childIndexChanged;
+ private IItemContainerGenerator? _generator;
+ private EventHandler? _childIndexChanged;
///
/// Initializes static members of the class.
@@ -50,7 +50,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets the items to be displayed.
///
- public IEnumerable Items
+ public IEnumerable? Items
{
get
{
@@ -114,7 +114,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets the data template used to display the items in the control.
///
- public IDataTemplate ItemTemplate
+ public IDataTemplate? ItemTemplate
{
get { return GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
@@ -123,7 +123,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets the panel used to display the items.
///
- public IPanel Panel
+ public IPanel? Panel
{
get;
private set;
@@ -131,7 +131,7 @@ namespace Avalonia.Controls.Presenters
protected bool IsHosted => TemplatedParent is IItemsPresenterHost;
- event EventHandler IChildIndexProvider.ChildIndexChanged
+ event EventHandler? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
@@ -186,7 +186,7 @@ namespace Avalonia.Controls.Presenters
return result;
}
- private void ContainerActionHandler(object sender, ItemContainerEventArgs e)
+ private void ContainerActionHandler(object? sender, ItemContainerEventArgs e)
{
for (var i = 0; i < e.Containers.Count; i++)
{
@@ -197,14 +197,14 @@ namespace Avalonia.Controls.Presenters
///
protected override Size MeasureOverride(Size availableSize)
{
- Panel.Measure(availableSize);
+ Panel!.Measure(availableSize);
return Panel.DesiredSize;
}
///
protected override Size ArrangeOverride(Size finalSize)
{
- Panel.Arrange(new Rect(finalSize));
+ Panel!.Arrange(new Rect(finalSize));
return finalSize;
}
@@ -258,7 +258,7 @@ namespace Avalonia.Controls.Presenters
///
/// The sender.
/// The event args.
- private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void ItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (_createdPanel)
{
diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
index a62ba306ab..97fb4c3f43 100644
--- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
@@ -7,8 +7,6 @@ using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Presenters
{
///
@@ -60,6 +58,12 @@ namespace Avalonia.Controls.Presenters
o => o.Viewport,
(o, v) => o.Viewport = v);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty IsScrollChainingEnabledProperty =
+ ScrollViewer.IsScrollChainingEnabledProperty.AddOwner();
+
private bool _canHorizontallyScroll;
private bool _canVerticallyScroll;
private bool _arranging;
@@ -138,6 +142,20 @@ namespace Avalonia.Controls.Presenters
private set { SetAndRaise(ViewportProperty, ref _viewport, value); }
}
+ ///
+ /// Gets or sets if scroll chaining is enabled. The default value is true.
+ ///
+ ///
+ /// After a user hits a scroll limit on an element that has been nested within another scrollable element,
+ /// you can specify whether that parent element should continue the scrolling operation begun in its child element.
+ /// This is called scroll chaining.
+ ///
+ public bool IsScrollChainingEnabled
+ {
+ get => GetValue(IsScrollChainingEnabledProperty);
+ set => SetValue(IsScrollChainingEnabledProperty, value);
+ }
+
///
IControl? IScrollAnchorProvider.CurrentAnchor
{
@@ -268,8 +286,8 @@ namespace Avalonia.Controls.Presenters
private Size ArrangeWithAnchoring(Size finalSize)
{
var size = new Size(
- CanHorizontallyScroll ? Math.Max(Child.DesiredSize.Width, finalSize.Width) : finalSize.Width,
- CanVerticallyScroll ? Math.Max(Child.DesiredSize.Height, finalSize.Height) : finalSize.Height);
+ CanHorizontallyScroll ? Math.Max(Child!.DesiredSize.Width, finalSize.Width) : finalSize.Width,
+ CanVerticallyScroll ? Math.Max(Child!.DesiredSize.Height, finalSize.Height) : finalSize.Height);
Vector TrackAnchor()
{
@@ -277,7 +295,7 @@ namespace Avalonia.Controls.Presenters
// arrange then that change wasn't just due to scrolling (as scrolling doesn't adjust
// relative positions within Child).
if (_anchorElement != null &&
- TranslateBounds(_anchorElement, Child, out var updatedBounds) &&
+ TranslateBounds(_anchorElement, Child!, out var updatedBounds) &&
updatedBounds.Position != _anchorElementBounds.Position)
{
var offset = updatedBounds.Position - _anchorElementBounds.Position;
@@ -337,13 +355,13 @@ namespace Avalonia.Controls.Presenters
}
Viewport = finalSize;
- Extent = Child.Bounds.Size.Inflate(Child.Margin);
+ Extent = Child!.Bounds.Size.Inflate(Child.Margin);
_isAnchorElementDirty = true;
return finalSize;
}
- private void OnScrollGesture(object sender, ScrollGestureEventArgs e)
+ private void OnScrollGesture(object? sender, ScrollGestureEventArgs e)
{
if (Extent.Height > Viewport.Height || Extent.Width > Viewport.Width)
{
@@ -405,12 +423,15 @@ namespace Avalonia.Controls.Presenters
_activeLogicalGestureScrolls[e.Id] = delta;
}
- Offset = new Vector(x, y);
- e.Handled = true;
+ Vector newOffset = new Vector(x, y);
+ bool offsetChanged = newOffset != Offset;
+ Offset = newOffset;
+
+ e.Handled = !IsScrollChainingEnabled || offsetChanged;
}
}
- private void OnScrollGestureEnded(object sender, ScrollGestureEndedEventArgs e)
+ private void OnScrollGestureEnded(object? sender, ScrollGestureEndedEventArgs e)
=> _activeLogicalGestureScrolls?.Remove(e.Id);
///
@@ -440,8 +461,11 @@ namespace Avalonia.Controls.Presenters
x = Math.Min(x, Extent.Width - Viewport.Width);
}
- Offset = new Vector(x, y);
- e.Handled = true;
+ Vector newOffset = new Vector(x, y);
+ bool offsetChanged = newOffset != Offset;
+ Offset = newOffset;
+
+ e.Handled = !IsScrollChainingEnabled || offsetChanged;
}
}
@@ -455,9 +479,10 @@ namespace Avalonia.Controls.Presenters
base.OnPropertyChanged(change);
}
- private void BringIntoViewRequested(object sender, RequestBringIntoViewEventArgs e)
+ private void BringIntoViewRequested(object? sender, RequestBringIntoViewEventArgs e)
{
- e.Handled = BringDescendantIntoView(e.TargetObject, e.TargetRect);
+ if (e.TargetObject is not null)
+ e.Handled = BringDescendantIntoView(e.TargetObject, e.TargetRect);
}
private void ChildChanged(AvaloniaPropertyChangedEventArgs e)
@@ -496,9 +521,9 @@ namespace Avalonia.Controls.Presenters
}
}
- private void ScrollInvalidated(object sender, EventArgs e)
+ private void ScrollInvalidated(object? sender, EventArgs e)
{
- UpdateFromScrollable((ILogicalScrollable)sender);
+ UpdateFromScrollable((ILogicalScrollable)sender!);
}
private void UpdateFromScrollable(ILogicalScrollable scrollable)
@@ -555,7 +580,7 @@ namespace Avalonia.Controls.Presenters
// We have a candidate, calculate its bounds relative to Child. Because these
// bounds aren't relative to the ScrollContentPresenter itself, if they change
// then we know it wasn't just due to scrolling.
- var unscrolledBounds = TranslateBounds(bestCandidate, Child);
+ var unscrolledBounds = TranslateBounds(bestCandidate, Child!);
_anchorElement = bestCandidate;
_anchorElementBounds = unscrolledBounds;
}
@@ -563,7 +588,7 @@ namespace Avalonia.Controls.Presenters
private bool GetViewportBounds(IControl element, out Rect bounds)
{
- if (TranslateBounds(element, Child, out var childBounds))
+ if (TranslateBounds(element, Child!, out var childBounds))
{
// We want the bounds relative to the new Offset, regardless of whether the child
// control has actually been arranged to this offset yet, so translate first to the
diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs
index ff63e5644f..1c60c0d906 100644
--- a/src/Avalonia.Controls/Presenters/TextPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs
@@ -1,9 +1,12 @@
using System;
+using System.Collections.Generic;
+using System.Diagnostics;
using System.Reactive.Linq;
-using Avalonia.Input.TextInput;
using Avalonia.Media;
+using Avalonia.Media.TextFormatting;
using Avalonia.Metadata;
using Avalonia.Threading;
+using Avalonia.Utilities;
using Avalonia.VisualTree;
using Avalonia.Layout;
using Avalonia.Media.Immutable;
@@ -66,7 +69,7 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly StyledProperty BackgroundProperty =
+ public static readonly StyledProperty BackgroundProperty =
Border.BackgroundProperty.AddOwner();
private readonly DispatcherTimer _caretTimer;
@@ -75,28 +78,18 @@ namespace Avalonia.Controls.Presenters
private int _selectionEnd;
private bool _caretBlink;
private string _text;
- private FormattedText _formattedText;
- private Size _constraint;
+ private TextLayout? _textLayout;
+ private Size _constraint = Size.Infinity;
- static TextPresenter()
- {
- AffectsRender(SelectionBrushProperty, TextBlock.ForegroundProperty,
- SelectionForegroundBrushProperty, CaretBrushProperty,
- SelectionStartProperty, SelectionEndProperty);
-
- AffectsMeasure(TextProperty, PasswordCharProperty, RevealPasswordProperty,
- TextAlignmentProperty, TextWrappingProperty, TextBlock.FontSizeProperty,
- TextBlock.FontStyleProperty, TextBlock.FontWeightProperty, TextBlock.FontFamilyProperty);
+ private CharacterHit _lastCharacterHit;
+ private Rect _caretBounds;
+ private Point _navigationPosition;
- Observable.Merge(TextProperty.Changed, TextBlock.ForegroundProperty.Changed,
- TextAlignmentProperty.Changed, TextWrappingProperty.Changed,
- TextBlock.FontSizeProperty.Changed, TextBlock.FontStyleProperty.Changed,
- TextBlock.FontWeightProperty.Changed, TextBlock.FontFamilyProperty.Changed,
- SelectionStartProperty.Changed, SelectionEndProperty.Changed,
- SelectionForegroundBrushProperty.Changed, PasswordCharProperty.Changed, RevealPasswordProperty.Changed
- ).AddClassHandler((x, _) => x.InvalidateFormattedText());
+ private ScrollViewer? _scrollViewer;
- CaretIndexProperty.Changed.AddClassHandler((x, e) => x.CaretIndexChanged((int)e.NewValue));
+ static TextPresenter()
+ {
+ AffectsRender(CaretBrushProperty, SelectionBrushProperty);
}
public TextPresenter()
@@ -106,10 +99,12 @@ namespace Avalonia.Controls.Presenters
_caretTimer.Tick += CaretTimerTick;
}
+ public event EventHandler? CaretBoundsChanged;
+
///
/// Gets or sets a brush used to paint the control's background.
///
- public IBrush Background
+ public IBrush? Background
{
get => GetValue(BackgroundProperty);
set => SetValue(BackgroundProperty, value);
@@ -164,7 +159,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets a brush used to paint the text.
///
- public IBrush Foreground
+ public IBrush? Foreground
{
get => TextBlock.GetForeground(this);
set => TextBlock.SetForeground(this, value);
@@ -189,13 +184,22 @@ namespace Avalonia.Controls.Presenters
}
///
- /// Gets the used to render the text.
+ /// Gets the used to render the text.
///
- public FormattedText FormattedText
+ public TextLayout? TextLayout
{
get
{
- return _formattedText ?? (_formattedText = CreateFormattedText());
+ if (_textLayout != null)
+ {
+ return _textLayout;
+ }
+
+ _textLayout = CreateTextLayout();
+
+ UpdateCaret(_lastCharacterHit);
+
+ return _textLayout;
}
}
@@ -205,11 +209,12 @@ namespace Avalonia.Controls.Presenters
{
return _caretIndex;
}
-
set
{
- value = CoerceCaretIndex(value);
- SetAndRaise(CaretIndexProperty, ref _caretIndex, value);
+ if (value != _caretIndex)
+ {
+ MoveCaretToTextPosition(value);
+ }
}
}
@@ -271,37 +276,32 @@ namespace Avalonia.Controls.Presenters
}
}
- public int GetCaretIndex(Point point)
- {
- var hit = FormattedText.HitTestPoint(point);
- return hit.TextPosition + (hit.IsTrailing ? 1 : 0);
- }
-
///
- /// Creates the used to render the text.
+ /// Creates the used to render the text.
///
/// The constraint of the text.
/// The text to format.
- /// A object.
- private FormattedText CreateFormattedTextInternal(Size constraint, string text)
+ ///
+ ///
+ /// A object.
+ private TextLayout? CreateTextLayoutInternal(Size constraint, string text, Typeface typeface,
+ IReadOnlyList>? textStyleOverrides)
{
- return new FormattedText
+ var foreground = Foreground;
+
+ if (foreground == null)
{
- Constraint = constraint,
- Typeface = new Typeface(FontFamily, FontStyle, FontWeight),
- FontSize = FontSize,
- Text = text ?? string.Empty,
- TextAlignment = TextAlignment,
- TextWrapping = TextWrapping,
- };
- }
+ return null;
+ }
- ///
- /// Invalidates .
- ///
- protected void InvalidateFormattedText()
- {
- _formattedText = null;
+ var maxWidth = MathUtilities.IsZero(constraint.Width) ? double.PositiveInfinity : constraint.Width;
+ var maxHeight = MathUtilities.IsZero(constraint.Height) ? double.PositiveInfinity : constraint.Height;
+
+ var textLayout = new TextLayout(text ?? string.Empty, typeface, FontSize, foreground, TextAlignment,
+ TextWrapping, maxWidth: maxWidth, maxHeight: maxHeight, textStyleOverrides: textStyleOverrides,
+ flowDirection: FlowDirection);
+
+ return textLayout;
}
///
@@ -317,41 +317,51 @@ namespace Avalonia.Controls.Presenters
context.FillRectangle(background, new Rect(Bounds.Size));
}
- double top = 0;
- var textSize = FormattedText.Bounds.Size;
+ if (TextLayout == null)
+ {
+ return;
+ }
+
+ var top = 0d;
+ var left = 0.0;
- if (Bounds.Height < textSize.Height)
+ var (_, textHeight) = TextLayout.Size;
+
+ if (Bounds.Height < textHeight)
{
switch (VerticalAlignment)
{
case VerticalAlignment.Center:
- top += (Bounds.Height - textSize.Height) / 2;
+ top += (Bounds.Height - textHeight) / 2;
break;
case VerticalAlignment.Bottom:
- top += (Bounds.Height - textSize.Height);
+ top += (Bounds.Height - textHeight);
break;
}
}
- context.DrawText(Foreground, new Point(0, top), FormattedText);
+ TextLayout.Draw(context, new Point(left, top));
}
public override void Render(DrawingContext context)
{
- FormattedText.Constraint = Bounds.Size;
-
- _constraint = Bounds.Size;
+ if (double.IsPositiveInfinity (_constraint.Width))
+ {
+ _constraint = _scrollViewer?.Viewport ?? Size.Infinity;
+
+ InvalidateTextLayout();
+ }
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
- if (selectionStart != selectionEnd)
+ if (selectionStart != selectionEnd && TextLayout != null)
{
var start = Math.Min(selectionStart, selectionEnd);
var length = Math.Max(selectionStart, selectionEnd) - start;
- var rects = FormattedText.HitTestTextRange(start, length);
+ var rects = TextLayout.HitTestTextRange(start, length);
foreach (var rect in rects)
{
@@ -361,40 +371,47 @@ namespace Avalonia.Controls.Presenters
RenderInternal(context);
- if (selectionStart == selectionEnd && _caretBlink)
+ if (selectionStart != selectionEnd || !_caretBlink)
{
- var caretBrush = CaretBrush?.ToImmutable();
+ return;
+ }
+
+ var caretBrush = CaretBrush?.ToImmutable();
- if (caretBrush is null)
+ if (caretBrush is null)
+ {
+ var backgroundColor = (Background as ISolidColorBrush)?.Color;
+
+ if (backgroundColor.HasValue)
{
- var backgroundColor = (Background as ISolidColorBrush)?.Color;
- if (backgroundColor.HasValue)
- {
- byte red = (byte)~(backgroundColor.Value.R);
- byte green = (byte)~(backgroundColor.Value.G);
- byte blue = (byte)~(backgroundColor.Value.B);
+ var red = (byte)~(backgroundColor.Value.R);
+ var green = (byte)~(backgroundColor.Value.G);
+ var blue = (byte)~(backgroundColor.Value.B);
- caretBrush = new ImmutableSolidColorBrush(Color.FromRgb(red, green, blue));
- }
- else
- {
- caretBrush = Brushes.Black;
- }
+ caretBrush = new ImmutableSolidColorBrush(Color.FromRgb(red, green, blue));
+ }
+ else
+ {
+ caretBrush = Brushes.Black;
}
-
- var (p1, p2) = GetCaretPoints();
- context.DrawLine(
- new ImmutablePen(caretBrush, 1),
- p1, p2);
}
- }
- (Point, Point) GetCaretPoints()
+ var (p1, p2) = GetCaretPoints();
+
+ context.DrawLine(new ImmutablePen(caretBrush), p1, p2);
+ }
+
+ private (Point, Point) GetCaretPoints()
{
- var charPos = FormattedText.HitTestTextPosition(CaretIndex);
- var x = Math.Floor(charPos.X) + 0.5;
- var y = Math.Floor(charPos.Y) + 0.5;
- var b = Math.Ceiling(charPos.Bottom) - 0.5;
+ var x = Math.Floor(_caretBounds.X) + 0.5;
+ var y = Math.Floor(_caretBounds.Y) + 0.5;
+ var b = Math.Ceiling(_caretBounds.Bottom) - 0.5;
+
+ if (x >= Bounds.Width)
+ {
+ x = Math.Floor(_caretBounds.X - 1) + 0.5;
+ }
+
return (new Point(x, y), new Point(x, b));
}
@@ -412,7 +429,7 @@ namespace Avalonia.Controls.Presenters
InvalidateVisual();
}
- internal void CaretIndexChanged(int caretIndex)
+ internal void CaretChanged()
{
if (this.GetVisualParent() != null)
{
@@ -432,8 +449,7 @@ namespace Avalonia.Controls.Presenters
if (IsMeasureValid)
{
- var rect = FormattedText.HitTestTextPosition(caretIndex);
- this.BringIntoView(rect);
+ this.BringIntoView(_caretBounds);
}
else
{
@@ -443,8 +459,7 @@ namespace Avalonia.Controls.Presenters
Dispatcher.UIThread.Post(
() =>
{
- var rect = FormattedText.HitTestTextPosition(caretIndex);
- this.BringIntoView(rect);
+ this.BringIntoView(_caretBounds);
},
DispatcherPriority.Render);
}
@@ -452,104 +467,335 @@ namespace Avalonia.Controls.Presenters
}
///
- /// Creates the used to render the text.
+ /// Creates the used to render the text.
///
- /// A object.
- protected virtual FormattedText CreateFormattedText()
+ /// A object.
+ protected virtual TextLayout? CreateTextLayout()
{
- FormattedText result = null;
+ TextLayout? result;
var text = Text;
- if (PasswordChar != default(char) && !RevealPassword)
- {
- result = CreateFormattedTextInternal(_constraint, new string(PasswordChar, text?.Length ?? 0));
- }
- else
- {
- result = CreateFormattedTextInternal(_constraint, text);
- }
+ var typeface = new Typeface(FontFamily, FontStyle, FontWeight);
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
var start = Math.Min(selectionStart, selectionEnd);
var length = Math.Max(selectionStart, selectionEnd) - start;
+ IReadOnlyList>? textStyleOverrides = null;
+
if (length > 0)
{
- result.Spans = new[]
+ textStyleOverrides = new[]
{
- new FormattedTextStyleSpan(start, length, SelectionForegroundBrush),
+ new ValueSpan(start, length,
+ new GenericTextRunProperties(typeface, FontSize,
+ foregroundBrush: SelectionForegroundBrush ?? Brushes.White))
};
}
+ if (PasswordChar != default(char) && !RevealPassword)
+ {
+ result = CreateTextLayoutInternal(_constraint, new string(PasswordChar, text?.Length ?? 0), typeface,
+ textStyleOverrides);
+ }
+ else
+ {
+ result = CreateTextLayoutInternal(_constraint, text, typeface, textStyleOverrides);
+ }
+
return result;
}
- ///
- /// Measures the control.
- ///
- /// The available size for the control.
- /// The desired size.
- private Size MeasureInternal(Size availableSize)
+ protected virtual void InvalidateTextLayout()
{
- if (!string.IsNullOrEmpty(Text))
+ _textLayout = null;
+
+ InvalidateMeasure();
+ }
+
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ if (!double.IsInfinity(availableSize.Width) && availableSize != _constraint)
{
- if (TextWrapping == TextWrapping.Wrap)
+ _constraint = availableSize;
+
+ InvalidateTextLayout();
+ }
+
+ return TextLayout?.Size ?? default;
+ }
+
+ private int CoerceCaretIndex(int value)
+ {
+ var text = Text;
+ var length = text?.Length ?? 0;
+ return Math.Max(0, Math.Min(length, value));
+ }
+
+ private void CaretTimerTick(object? sender, EventArgs e)
+ {
+ _caretBlink = !_caretBlink;
+ InvalidateVisual();
+ }
+
+ public void MoveCaretToTextPosition(int textPosition, bool trailingEdge = false)
+ {
+ if (TextLayout == null)
+ {
+ return;
+ }
+
+ var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(textPosition, trailingEdge);
+ var textLine = TextLayout.TextLines[lineIndex];
+
+ var characterHit = textLine.GetPreviousCaretCharacterHit(new CharacterHit(textPosition));
+
+ var nextCaretCharacterHit = textLine.GetNextCaretCharacterHit(characterHit);
+
+ if (nextCaretCharacterHit.FirstCharacterIndex <= textPosition)
+ {
+ characterHit = nextCaretCharacterHit;
+ }
+
+ if (textPosition == characterHit.FirstCharacterIndex + characterHit.TrailingLength)
+ {
+ UpdateCaret(characterHit);
+ }
+ else
+ {
+ UpdateCaret(trailingEdge ? characterHit : new CharacterHit(characterHit.FirstCharacterIndex));
+ }
+
+ _navigationPosition = _caretBounds.Position;
+ }
+
+ public void MoveCaretToPoint(Point point)
+ {
+ if (TextLayout == null)
+ {
+ return;
+ }
+
+ var hit = TextLayout.HitTestPoint(point);
+
+ UpdateCaret(hit.CharacterHit);
+
+ _navigationPosition = _caretBounds.Position;
+ }
+
+ public void MoveCaretVertical(LogicalDirection direction = LogicalDirection.Forward)
+ {
+ if (TextLayout == null)
+ {
+ return;
+ }
+
+ var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(CaretIndex, _lastCharacterHit.TrailingLength > 0);
+
+ if (lineIndex < 0)
+ {
+ return;
+ }
+
+ var (currentX, currentY) = _navigationPosition;
+
+ if (direction == LogicalDirection.Forward)
+ {
+ if (lineIndex + 1 > TextLayout.TextLines.Count - 1)
{
- _constraint = new Size(availableSize.Width, double.PositiveInfinity);
+ return;
}
- else
+
+ var textLine = TextLayout.TextLines[lineIndex];
+
+ currentY += textLine.Height;
+ }
+ else
+ {
+ if (lineIndex - 1 < 0)
{
- _constraint = Size.Infinity;
+ return;
}
- _formattedText = null;
+ var textLine = TextLayout.TextLines[--lineIndex];
- return FormattedText.Bounds.Size;
+ currentY -= textLine.Height;
}
- return new Size();
+ var navigationPosition = _navigationPosition;
+
+ MoveCaretToPoint(new Point(currentX, currentY));
+
+ _navigationPosition = navigationPosition.WithY(_caretBounds.Y);
}
- protected override Size MeasureOverride(Size availableSize)
+ public void MoveCaretHorizontal(LogicalDirection direction = LogicalDirection.Forward)
{
- var text = Text;
+ if (TextLayout == null)
+ {
+ return;
+ }
+
+ var characterHit = _lastCharacterHit;
+ var caretIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
+
+ var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(caretIndex, false);
- if (!string.IsNullOrEmpty(text))
+ if (lineIndex < 0)
{
- return MeasureInternal(availableSize);
+ return;
+ }
+
+ if (direction == LogicalDirection.Forward)
+ {
+ while (lineIndex < TextLayout.TextLines.Count)
+ {
+ var textLine = TextLayout.TextLines[lineIndex];
+
+ characterHit = textLine.GetNextCaretCharacterHit(characterHit);
+
+ caretIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
+
+ if (textLine.NewLineLength > 0 && caretIndex == textLine.TextRange.Start + textLine.TextRange.Length)
+ {
+ characterHit = new CharacterHit(caretIndex);
+ }
+
+ if (caretIndex >= Text.Length)
+ {
+ characterHit = new CharacterHit(Text.Length);
+
+ break;
+ }
+
+ if (caretIndex - textLine.NewLineLength == textLine.TextRange.Start + textLine.TextRange.Length)
+ {
+ break;
+ }
+
+ if (caretIndex <= CaretIndex)
+ {
+ lineIndex++;
+
+ continue;
+ }
+
+ break;
+ }
}
else
{
- return new FormattedText
+ while (lineIndex >= 0)
{
- Text = "X",
- Typeface = new Typeface(FontFamily, FontStyle, FontWeight),
- FontSize = FontSize,
- TextAlignment = TextAlignment,
- Constraint = availableSize,
- }.Bounds.Size;
+ var textLine = TextLayout.TextLines[lineIndex];
+
+ characterHit = textLine.GetPreviousCaretCharacterHit(characterHit);
+
+ caretIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
+
+ if (caretIndex >= CaretIndex)
+ {
+ lineIndex--;
+
+ continue;
+ }
+
+ break;
+ }
}
+
+ UpdateCaret(characterHit);
+
+ _navigationPosition = _caretBounds.Position;
}
- private int CoerceCaretIndex(int value)
+ private void UpdateCaret(CharacterHit characterHit)
{
- var text = Text;
- var length = text?.Length ?? 0;
- return Math.Max(0, Math.Min(length, value));
+ if (TextLayout == null)
+ {
+ return;
+ }
+
+ _lastCharacterHit = characterHit;
+
+ var caretIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
+
+ var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(caretIndex, characterHit.TrailingLength > 0);
+ var textLine = TextLayout.TextLines[lineIndex];
+ var distanceX = textLine.GetDistanceFromCharacterHit(characterHit);
+
+ var distanceY = 0d;
+
+ for (var i = 0; i < lineIndex; i++)
+ {
+ var currentLine = TextLayout.TextLines[i];
+
+ distanceY += currentLine.Height;
+ }
+
+ var caretBounds = new Rect(distanceX, distanceY, 0, textLine.Height);
+
+ if (caretBounds != _caretBounds)
+ {
+ _caretBounds = caretBounds;
+
+ CaretBoundsChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ CaretChanged();
+
+ SetAndRaise(CaretIndexProperty, ref _caretIndex, caretIndex);
}
- private void CaretTimerTick(object sender, EventArgs e)
+ internal Rect GetCursorRectangle()
{
- _caretBlink = !_caretBlink;
- InvalidateVisual();
+ return _caretBounds;
}
- internal Rect GetCursorRectangle()
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
- var (p1, p2) = GetCaretPoints();
- return new Rect(p1, p2);
+ base.OnAttachedToVisualTree(e);
+
+ _scrollViewer = this.FindAncestorOfType();
+ }
+
+ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnDetachedFromVisualTree(e);
+
+ _scrollViewer = null;
+
+ _caretTimer.Stop();
+
+ _caretTimer.Tick -= CaretTimerTick;
+ }
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ switch (change.Property.Name)
+ {
+ case nameof (TextBlock.Foreground):
+ case nameof (TextBlock.FontSize):
+ case nameof (TextBlock.FontStyle):
+ case nameof (TextBlock.FontWeight):
+ case nameof (TextBlock.FontFamily):
+ case nameof (Text):
+ case nameof (TextAlignment):
+ case nameof (TextWrapping):
+ case nameof (SelectionStart):
+ case nameof (SelectionEnd):
+ case nameof (SelectionForegroundBrush):
+ case nameof (PasswordChar):
+ case nameof (RevealPassword):
+ {
+ InvalidateTextLayout();
+ break;
+ }
+ }
}
}
}
diff --git a/src/Avalonia.Controls/Primitives/AccessText.cs b/src/Avalonia.Controls/Primitives/AccessText.cs
index 3c82386991..a6976721b1 100644
--- a/src/Avalonia.Controls/Primitives/AccessText.cs
+++ b/src/Avalonia.Controls/Primitives/AccessText.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using Avalonia.Input;
using Avalonia.Media;
using Avalonia.Media.TextFormatting;
@@ -19,7 +20,7 @@ namespace Avalonia.Controls.Primitives
///
/// The access key handler for the current window.
///
- private IAccessKeyHandler _accessKeys;
+ private IAccessKeyHandler? _accessKeys;
///
/// Initializes static members of the class.
@@ -67,7 +68,7 @@ namespace Avalonia.Controls.Primitives
if (underscore != -1 && ShowAccessKey)
{
- var rect = TextLayout.HitTestTextPosition(underscore);
+ var rect = TextLayout!.HitTestTextPosition(underscore);
var offset = new Vector(0, -1.5);
context.DrawLine(
new Pen(Foreground, 1),
@@ -77,7 +78,7 @@ namespace Avalonia.Controls.Primitives
}
///
- protected override TextLayout CreateTextLayout(Size constraint, string text)
+ protected override TextLayout? CreateTextLayout(Size constraint, string? text)
{
return base.CreateTextLayout(constraint, StripAccessKey(text));
}
@@ -111,8 +112,14 @@ namespace Avalonia.Controls.Primitives
///
/// The text.
/// The text with the first underscore stripped.
- private string StripAccessKey(string text)
+ [return: NotNullIfNotNull("text")]
+ private string? StripAccessKey(string? text)
{
+ if (text is null)
+ {
+ return null;
+ }
+
var position = text.IndexOf('_');
if (position == -1)
@@ -129,7 +136,7 @@ namespace Avalonia.Controls.Primitives
/// Called when the property changes.
///
/// The new text.
- private void TextChanged(string text)
+ private void TextChanged(string? text)
{
var key = (char)0;
diff --git a/src/Avalonia.Controls/Primitives/AdornerLayer.cs b/src/Avalonia.Controls/Primitives/AdornerLayer.cs
index 2ead82f95d..353f12118f 100644
--- a/src/Avalonia.Controls/Primitives/AdornerLayer.cs
+++ b/src/Avalonia.Controls/Primitives/AdornerLayer.cs
@@ -4,8 +4,6 @@ using Avalonia.Media;
using Avalonia.Rendering;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
@@ -142,12 +140,12 @@ namespace Avalonia.Controls.Primitives
clip.Rect = clipBounds;
}
- private void ChildrenCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void ChildrenCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
- foreach (Visual i in e.NewItems)
+ foreach (Visual i in e.NewItems!)
{
UpdateAdornedElement(i, i.GetValue(AdornedElementProperty));
}
diff --git a/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs b/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs
index 7171ecc302..a774368af6 100644
--- a/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs
+++ b/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs
@@ -2,8 +2,6 @@
using Avalonia.Rendering;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
public class ChromeOverlayLayer : Panel, ICustomSimpleHitTest
diff --git a/src/Avalonia.Controls/Primitives/HeaderedContentControl.cs b/src/Avalonia.Controls/Primitives/HeaderedContentControl.cs
index e55bdbb0eb..d44ef5666c 100644
--- a/src/Avalonia.Controls/Primitives/HeaderedContentControl.cs
+++ b/src/Avalonia.Controls/Primitives/HeaderedContentControl.cs
@@ -2,8 +2,6 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.LogicalTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
diff --git a/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs b/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs
index be3c100ecf..2f051c4fda 100644
--- a/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs
@@ -1,5 +1,4 @@
using Avalonia.Collections;
-using Avalonia.Controls.Mixins;
using Avalonia.Controls.Presenters;
using Avalonia.LogicalTree;
@@ -13,7 +12,7 @@ namespace Avalonia.Controls.Primitives
///
/// Defines the property.
///
- public static readonly StyledProperty HeaderProperty =
+ public static readonly StyledProperty HeaderProperty =
HeaderedContentControl.HeaderProperty.AddOwner();
///
@@ -27,7 +26,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets or sets the content of the control's header.
///
- public object Header
+ public object? Header
{
get { return GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
@@ -36,7 +35,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets the header presenter from the control's template.
///
- public IContentPresenter HeaderPresenter
+ public IContentPresenter? HeaderPresenter
{
get;
private set;
diff --git a/src/Avalonia.Controls/Primitives/HeaderedSelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/HeaderedSelectingItemsControl.cs
index 78b5771b80..49fc58c8f5 100644
--- a/src/Avalonia.Controls/Primitives/HeaderedSelectingItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/HeaderedSelectingItemsControl.cs
@@ -1,5 +1,4 @@
using Avalonia.Collections;
-using Avalonia.Controls.Mixins;
using Avalonia.Controls.Presenters;
using Avalonia.LogicalTree;
@@ -13,7 +12,7 @@ namespace Avalonia.Controls.Primitives
///
/// Defines the property.
///
- public static readonly StyledProperty HeaderProperty =
+ public static readonly StyledProperty HeaderProperty =
HeaderedContentControl.HeaderProperty.AddOwner();
///
@@ -27,7 +26,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets or sets the content of the control's header.
///
- public object Header
+ public object? Header
{
get { return GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
@@ -36,7 +35,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets the header presenter from the control's template.
///
- public IContentPresenter HeaderPresenter
+ public IContentPresenter? HeaderPresenter
{
get;
private set;
diff --git a/src/Avalonia.Controls/Primitives/ILogicalScrollable.cs b/src/Avalonia.Controls/Primitives/ILogicalScrollable.cs
index 5c29945735..2be91c046e 100644
--- a/src/Avalonia.Controls/Primitives/ILogicalScrollable.cs
+++ b/src/Avalonia.Controls/Primitives/ILogicalScrollable.cs
@@ -48,7 +48,7 @@ namespace Avalonia.Controls.Primitives
/// This event notifies an attached of a change in
/// one of the scroll properties.
///
- event EventHandler ScrollInvalidated;
+ event EventHandler? ScrollInvalidated;
///
/// Attempts to bring a portion of the target visual into view by scrolling the content.
@@ -64,7 +64,7 @@ namespace Avalonia.Controls.Primitives
/// The movement direction.
/// The control from which movement begins.
/// The control.
- IControl GetControlInDirection(NavigationDirection direction, IControl from);
+ IControl? GetControlInDirection(NavigationDirection direction, IControl from);
///
/// Raises the event.
diff --git a/src/Avalonia.Controls/Primitives/IPopupHost.cs b/src/Avalonia.Controls/Primitives/IPopupHost.cs
index ab81fe869e..36d2ae9230 100644
--- a/src/Avalonia.Controls/Primitives/IPopupHost.cs
+++ b/src/Avalonia.Controls/Primitives/IPopupHost.cs
@@ -20,23 +20,23 @@ namespace Avalonia.Controls.Primitives
/// Sets the control to display in the popup.
///
///
- void SetChild(IControl control);
+ void SetChild(IControl? control);
///
/// Gets the presenter from the control's template.
///
- IContentPresenter Presenter { get; }
+ IContentPresenter? Presenter { get; }
///
/// Gets the root of the visual tree in the case where the popup is presented using a
/// separate visual tree.
///
- IVisual HostedVisualTreeRoot { get; }
+ IVisual? HostedVisualTreeRoot { get; }
///
/// Raised when the control's template is applied.
///
- event EventHandler TemplateApplied;
+ event EventHandler? TemplateApplied;
///
/// Configures the position of the popup according to a target control and a set of
diff --git a/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs b/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs
index 74d804f2bf..04c30b0f33 100644
--- a/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs
+++ b/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs
@@ -7,8 +7,6 @@ using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
@@ -52,7 +50,7 @@ namespace Avalonia.Controls.Primitives
{
if (InputPassThroughElement is object)
{
- var hit = VisualRoot.GetVisualAt(point, x => x != this);
+ var hit = VisualRoot?.GetVisualAt(point, x => x != this);
if (hit is object)
{
diff --git a/src/Avalonia.Controls/Primitives/OverlayLayer.cs b/src/Avalonia.Controls/Primitives/OverlayLayer.cs
index 5150033a53..6a0408d6d1 100644
--- a/src/Avalonia.Controls/Primitives/OverlayLayer.cs
+++ b/src/Avalonia.Controls/Primitives/OverlayLayer.cs
@@ -7,7 +7,7 @@ namespace Avalonia.Controls.Primitives
public class OverlayLayer : Canvas, ICustomSimpleHitTest
{
public Size AvailableSize { get; private set; }
- public static OverlayLayer GetOverlayLayer(IVisual visual)
+ public static OverlayLayer? GetOverlayLayer(IVisual visual)
{
foreach(var v in visual.GetVisualAncestors())
if(v is VisualLayerManager vlm)
diff --git a/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs b/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs
index 403902f676..6251d5cda7 100644
--- a/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs
+++ b/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs
@@ -23,15 +23,15 @@ namespace Avalonia.Controls.Primitives
_positioner = new ManagedPopupPositioner(this);
}
- public void SetChild(IControl control)
+ public void SetChild(IControl? control)
{
Content = control;
}
- public IVisual HostedVisualTreeRoot => null;
+ public IVisual? HostedVisualTreeRoot => null;
///
- IInteractive IInteractive.InteractiveParent => Parent;
+ IInteractive? IInteractive.InteractiveParent => Parent;
public void Dispose() => Hide();
@@ -75,7 +75,7 @@ namespace Avalonia.Controls.Primitives
PopupPositionerConstraintAdjustment constraintAdjustment = PopupPositionerConstraintAdjustment.All,
Rect? rect = null)
{
- _positionerParameters.ConfigurePosition((TopLevel)_overlayLayer.GetVisualRoot(), target, placement, offset, anchor,
+ _positionerParameters.ConfigurePosition((TopLevel)_overlayLayer.GetVisualRoot()!, target, placement, offset, anchor,
gravity, constraintAdjustment, rect);
UpdatePosition();
}
@@ -126,11 +126,11 @@ namespace Avalonia.Controls.Primitives
double IManagedPopupPositionerPopup.Scaling => 1;
- public static IPopupHost CreatePopupHost(IVisual target, IAvaloniaDependencyResolver dependencyResolver)
+ public static IPopupHost CreatePopupHost(IVisual target, IAvaloniaDependencyResolver? dependencyResolver)
{
var platform = (target.GetVisualRoot() as TopLevel)?.PlatformImpl?.CreatePopup();
if (platform != null)
- return new PopupRoot((TopLevel)target.GetVisualRoot(), platform, dependencyResolver);
+ return new PopupRoot((TopLevel)target.GetVisualRoot()!, platform, dependencyResolver);
var overlayLayer = OverlayLayer.GetOverlayLayer(target);
if (overlayLayer == null)
diff --git a/src/Avalonia.Controls/Primitives/Popup.cs b/src/Avalonia.Controls/Primitives/Popup.cs
index ffab7f86d1..f3fec95bcc 100644
--- a/src/Avalonia.Controls/Primitives/Popup.cs
+++ b/src/Avalonia.Controls/Primitives/Popup.cs
@@ -14,8 +14,6 @@ using Avalonia.Metadata;
using Avalonia.Platform;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
@@ -419,7 +417,7 @@ namespace Avalonia.Controls.Primitives
(x, handler) => x.TemplateApplied += handler,
(x, handler) => x.TemplateApplied -= handler).DisposeWith(handlerCleanup);
- if (topLevel is Window window)
+ if (topLevel is Window window && window.PlatformImpl != null)
{
SubscribeToEventHandler(window, WindowDeactivated,
(x, handler) => x.Deactivated += handler,
@@ -429,16 +427,20 @@ namespace Avalonia.Controls.Primitives
(x, handler) => x.LostFocus += handler,
(x, handler) => x.LostFocus -= handler).DisposeWith(handlerCleanup);
- SubscribeToEventHandler>(window.PlatformImpl, WindowPositionChanged,
- (x, handler) => x.PositionChanged += handler,
- (x, handler) => x.PositionChanged -= handler).DisposeWith(handlerCleanup);
-
- if (placementTarget is Layoutable layoutTarget)
+ // Recalculate popup position on parent moved/resized, but not if placement was on pointer
+ if (PlacementMode != PlacementMode.Pointer)
{
- // If the placement target is moved, update the popup position
- SubscribeToEventHandler(layoutTarget, PlacementTargetLayoutUpdated,
- (x, handler) => x.LayoutUpdated += handler,
- (x, handler) => x.LayoutUpdated -= handler).DisposeWith(handlerCleanup);
+ SubscribeToEventHandler>(window.PlatformImpl, WindowPositionChanged,
+ (x, handler) => x.PositionChanged += handler,
+ (x, handler) => x.PositionChanged -= handler).DisposeWith(handlerCleanup);
+
+ if (placementTarget is Layoutable layoutTarget)
+ {
+ // If the placement target is moved, update the popup position
+ SubscribeToEventHandler(layoutTarget, PlacementTargetLayoutUpdated,
+ (x, handler) => x.LayoutUpdated += handler,
+ (x, handler) => x.LayoutUpdated -= handler).DisposeWith(handlerCleanup);
+ }
}
}
else if (topLevel is PopupRoot parentPopupRoot)
@@ -567,7 +569,7 @@ namespace Avalonia.Controls.Primitives
private void WindowManagerAddShadowHintChanged(IPopupHost host, bool hint)
{
- if(host is PopupRoot pr)
+ if(host is PopupRoot pr && pr.PlatformImpl is not null)
{
pr.PlatformImpl.SetWindowManagerAddShadowHint(hint);
}
@@ -672,7 +674,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void PointerPressedDismissOverlay(object sender, PointerPressedEventArgs e)
+ private void PointerPressedDismissOverlay(object? sender, PointerPressedEventArgs e)
{
if (IsLightDismissEnabled && e.Source is IVisual v && !IsChildOrThis(v))
{
@@ -702,7 +704,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void RootTemplateApplied(object sender, TemplateAppliedEventArgs e)
+ private void RootTemplateApplied(object? sender, TemplateAppliedEventArgs e)
{
if (_openState is null)
{
@@ -729,7 +731,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void SetTemplatedParentAndApplyChildTemplates(IControl control)
+ private void SetTemplatedParentAndApplyChildTemplates(IControl? control)
{
if (control != null)
{
@@ -790,7 +792,7 @@ namespace Avalonia.Controls.Primitives
public bool IsPointerOverPopup => ((IInputElement?)_openState?.PopupHost)?.IsPointerOver ?? false;
- private void WindowDeactivated(object sender, EventArgs e)
+ private void WindowDeactivated(object? sender, EventArgs e)
{
if (IsLightDismissEnabled)
{
@@ -798,7 +800,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void ParentClosed(object sender, EventArgs e)
+ private void ParentClosed(object? sender, EventArgs e)
{
if (IsLightDismissEnabled)
{
@@ -814,9 +816,9 @@ namespace Avalonia.Controls.Primitives
private void WindowPositionChanged(PixelPoint pp) => HandlePositionChange();
- private void PlacementTargetLayoutUpdated(object src, EventArgs e) => HandlePositionChange();
+ private void PlacementTargetLayoutUpdated(object? src, EventArgs e) => HandlePositionChange();
- private void ParentPopupPositionChanged(object src, PixelPointEventArgs e) => HandlePositionChange();
+ private void ParentPopupPositionChanged(object? src, PixelPointEventArgs e) => HandlePositionChange();
private IgnoreIsOpenScope BeginIgnoringIsOpen()
{
diff --git a/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs b/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
index 844069965b..340076a407 100644
--- a/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
+++ b/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
@@ -448,7 +448,7 @@ namespace Avalonia.Controls.Primitives.PopupPositioning
{
// We need a better way for tracking the last pointer position
#pragma warning disable CS0618 // Type or member is obsolete
- var pointer = topLevel.PointToClient(topLevel.PlatformImpl.MouseDevice.Position);
+ var pointer = topLevel.PointToClient(topLevel.PlatformImpl?.MouseDevice.Position ?? default);
#pragma warning restore CS0618 // Type or member is obsolete
positionerParameters.Offset = offset;
diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs
index c59c7c11d9..be447ea512 100644
--- a/src/Avalonia.Controls/Primitives/PopupRoot.cs
+++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs
@@ -43,7 +43,7 @@ namespace Avalonia.Controls.Primitives
///
/// The dependency resolver to use. If null the default dependency resolver will be used.
///
- public PopupRoot(TopLevel parent, IPopupImpl impl, IAvaloniaDependencyResolver dependencyResolver)
+ public PopupRoot(TopLevel parent, IPopupImpl impl, IAvaloniaDependencyResolver? dependencyResolver)
: base(ValidatingPopupImpl.Wrap(impl), dependencyResolver)
{
_parent = parent;
@@ -52,8 +52,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets the platform-specific window implementation.
///
- [CanBeNull]
- public new IPopupImpl PlatformImpl => (IPopupImpl)base.PlatformImpl;
+ public new IPopupImpl? PlatformImpl => (IPopupImpl?)base.PlatformImpl;
///
/// Gets the parent control in the event route.
@@ -61,20 +60,24 @@ namespace Avalonia.Controls.Primitives
///
/// Popup events are passed to their parent window. This facilitates this.
///
- IInteractive IInteractive.InteractiveParent => Parent;
+ IInteractive? IInteractive.InteractiveParent => Parent;
///
/// Gets the control that is hosting the popup root.
///
- IVisual IHostedVisualTreeRoot.Host => Parent;
+ IVisual? IHostedVisualTreeRoot.Host => Parent;
///
/// Gets the styling parent of the popup root.
///
- IStyleHost IStyleHost.StylingParent => Parent;
+ IStyleHost? IStyleHost.StylingParent => Parent;
///
- public void Dispose() => PlatformImpl?.Dispose();
+ public void Dispose()
+ {
+ PlatformImpl?.Dispose();
+ HandleClosed();
+ }
private void UpdatePosition()
{
@@ -94,7 +97,7 @@ namespace Avalonia.Controls.Primitives
UpdatePosition();
}
- public void SetChild(IControl control) => Content = control;
+ public void SetChild(IControl? control) => Content = control;
IVisual IPopupHost.HostedVisualTreeRoot => this;
diff --git a/src/Avalonia.Controls/Primitives/ScrollBar.cs b/src/Avalonia.Controls/Primitives/ScrollBar.cs
index d5d6af8bfa..8460fe3017 100644
--- a/src/Avalonia.Controls/Primitives/ScrollBar.cs
+++ b/src/Avalonia.Controls/Primitives/ScrollBar.cs
@@ -69,11 +69,11 @@ namespace Avalonia.Controls.Primitives
public static readonly StyledProperty ShowDelayProperty =
AvaloniaProperty.Register(nameof(ShowDelay), TimeSpan.FromSeconds(0.5));
- private Button _lineUpButton;
- private Button _lineDownButton;
- private Button _pageUpButton;
- private Button _pageDownButton;
- private DispatcherTimer _timer;
+ private Button? _lineUpButton;
+ private Button? _lineDownButton;
+ private Button? _pageUpButton;
+ private Button? _pageDownButton;
+ private DispatcherTimer? _timer;
private bool _isExpanded;
///
@@ -157,7 +157,7 @@ namespace Avalonia.Controls.Primitives
set => SetValue(ShowDelayProperty, value);
}
- public event EventHandler Scroll;
+ public event EventHandler? Scroll;
///
/// Calculates and updates whether the scrollbar should be visible.
@@ -293,7 +293,7 @@ namespace Avalonia.Controls.Primitives
_timer = new DispatcherTimer(DispatcherPriority.Normal);
_timer.Tick += (sender, args) =>
{
- var senderTimer = (DispatcherTimer)sender;
+ var senderTimer = (DispatcherTimer)sender!;
if (senderTimer.Tag is Action action)
{
@@ -344,22 +344,22 @@ namespace Avalonia.Controls.Primitives
IsExpanded = true;
}
- private void LineUpClick(object sender, RoutedEventArgs e)
+ private void LineUpClick(object? sender, RoutedEventArgs e)
{
SmallDecrement();
}
- private void LineDownClick(object sender, RoutedEventArgs e)
+ private void LineDownClick(object? sender, RoutedEventArgs e)
{
SmallIncrement();
}
- private void PageUpClick(object sender, RoutedEventArgs e)
+ private void PageUpClick(object? sender, RoutedEventArgs e)
{
LargeDecrement();
}
- private void PageDownClick(object sender, RoutedEventArgs e)
+ private void PageDownClick(object? sender, RoutedEventArgs e)
{
LargeIncrement();
}
diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
index 80f3d345a6..31de6f6398 100644
--- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
@@ -13,8 +13,6 @@ using Avalonia.Interactivity;
using Avalonia.Threading;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
@@ -138,7 +136,7 @@ namespace Avalonia.Controls.Primitives
///
/// Occurs when the control's selection changes.
///
- public event EventHandler SelectionChanged
+ public event EventHandler? SelectionChanged
{
add { AddHandler(SelectionChangedEvent, value); }
remove { RemoveHandler(SelectionChangedEvent, value); }
@@ -386,9 +384,9 @@ namespace Avalonia.Controls.Primitives
return null;
}
- protected override void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ protected override void ItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
- base.ItemsCollectionChanged(sender, e);
+ base.ItemsCollectionChanged(sender!, e);
if (AlwaysSelected && SelectedIndex == -1 && ItemCount > 0)
{
@@ -406,7 +404,7 @@ namespace Avalonia.Controls.Primitives
{
base.OnApplyTemplate(e);
- void ExecuteScrollWhenLayoutUpdated(object sender, EventArgs e)
+ void ExecuteScrollWhenLayoutUpdated(object? sender, EventArgs e)
{
LayoutUpdated -= ExecuteScrollWhenLayoutUpdated;
AutoScrollToSelectedItemIfNecessary();
@@ -443,9 +441,7 @@ namespace Avalonia.Controls.Primitives
{
base.OnContainersDematerialized(e);
- var panel = (InputElement)Presenter.Panel;
-
- if (panel != null)
+ if (Presenter?.Panel is InputElement panel)
{
foreach (var container in e.Containers)
{
@@ -523,7 +519,7 @@ namespace Avalonia.Controls.Primitives
info.ContainerControl is IContentControl control &&
control.Content?.ToString()?.StartsWith(_textSearchTerm, StringComparison.OrdinalIgnoreCase) == true;
- var info = ItemContainerGenerator.Containers.FirstOrDefault(match);
+ var info = ItemContainerGenerator?.Containers.FirstOrDefault(match);
if (info != null)
{
@@ -594,7 +590,7 @@ namespace Avalonia.Controls.Primitives
/// True if the selection was moved; otherwise false.
protected bool MoveSelection(NavigationDirection direction, bool wrap)
{
- var from = SelectedIndex != -1 ? ItemContainerGenerator.ContainerFromIndex(SelectedIndex) : null;
+ var from = SelectedIndex != -1 ? ItemContainerGenerator?.ContainerFromIndex(SelectedIndex) : null;
return MoveSelection(from, direction, wrap);
}
@@ -610,7 +606,7 @@ namespace Avalonia.Controls.Primitives
if (Presenter?.Panel is INavigableContainer container &&
GetNextControl(container, direction, from, wrap) is IControl next)
{
- var index = ItemContainerGenerator.IndexFromContainer(next);
+ var index = ItemContainerGenerator?.IndexFromContainer(next) ?? -1;
if (index != -1)
{
@@ -688,7 +684,7 @@ namespace Avalonia.Controls.Primitives
if (Presenter?.Panel != null)
{
- var container = ItemContainerGenerator.ContainerFromIndex(index);
+ var container = ItemContainerGenerator?.ContainerFromIndex(index);
KeyboardNavigation.SetTabOnceActiveElement(
(InputElement)Presenter.Panel,
container);
@@ -755,7 +751,7 @@ namespace Avalonia.Controls.Primitives
///
/// The sender.
/// The event args.
- private void OnSelectionModelPropertyChanged(object sender, PropertyChangedEventArgs e)
+ private void OnSelectionModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ISelectionModel.AnchorIndex))
{
@@ -789,11 +785,11 @@ namespace Avalonia.Controls.Primitives
///
/// The sender.
/// The event args.
- private void OnSelectionModelSelectionChanged(object sender, SelectionModelSelectionChangedEventArgs e)
+ private void OnSelectionModelSelectionChanged(object? sender, SelectionModelSelectionChangedEventArgs e)
{
void Mark(int index, bool selected)
{
- var container = ItemContainerGenerator.ContainerFromIndex(index);
+ var container = ItemContainerGenerator?.ContainerFromIndex(index);
if (container != null)
{
@@ -829,7 +825,7 @@ namespace Avalonia.Controls.Primitives
///
/// The sender.
/// The event args.
- private void OnSelectionModelLostSelection(object sender, EventArgs e)
+ private void OnSelectionModelLostSelection(object? sender, EventArgs e)
{
if (AlwaysSelected && Items is object)
{
@@ -912,7 +908,7 @@ namespace Avalonia.Controls.Primitives
{
MarkContainerSelected(
container,
- Selection.IsSelected(ItemContainerGenerator.IndexFromContainer(container)));
+ Selection.IsSelected(ItemContainerGenerator!.IndexFromContainer(container)));
}
}
}
@@ -1034,7 +1030,7 @@ namespace Avalonia.Controls.Primitives
_textSearchTimer = null;
}
- private void TextSearchTimer_Tick(object sender, EventArgs e)
+ private void TextSearchTimer_Tick(object? sender, EventArgs e)
{
_textSearchTerm = string.Empty;
StopTextSearchTimer();
diff --git a/src/Avalonia.Controls/Primitives/TemplatedControl.cs b/src/Avalonia.Controls/Primitives/TemplatedControl.cs
index 59975b072d..af681d6930 100644
--- a/src/Avalonia.Controls/Primitives/TemplatedControl.cs
+++ b/src/Avalonia.Controls/Primitives/TemplatedControl.cs
@@ -6,8 +6,6 @@ using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Styling;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
@@ -109,7 +107,7 @@ namespace Avalonia.Controls.Primitives
///
/// Raised when the control's template is applied.
///
- public event EventHandler TemplateApplied
+ public event EventHandler? TemplateApplied
{
add { AddHandler(TemplateAppliedEvent, value); }
remove { RemoveHandler(TemplateAppliedEvent, value); }
diff --git a/src/Avalonia.Controls/Primitives/Thumb.cs b/src/Avalonia.Controls/Primitives/Thumb.cs
index 91141058e4..cb3195cf52 100644
--- a/src/Avalonia.Controls/Primitives/Thumb.cs
+++ b/src/Avalonia.Controls/Primitives/Thumb.cs
@@ -26,19 +26,19 @@ namespace Avalonia.Controls.Primitives
DragCompletedEvent.AddClassHandler((x, e) => x.OnDragCompleted(e), RoutingStrategies.Bubble);
}
- public event EventHandler DragStarted
+ public event EventHandler? DragStarted
{
add { AddHandler(DragStartedEvent, value); }
remove { RemoveHandler(DragStartedEvent, value); }
}
- public event EventHandler DragDelta
+ public event EventHandler? DragDelta
{
add { AddHandler(DragDeltaEvent, value); }
remove { RemoveHandler(DragDeltaEvent, value); }
}
- public event EventHandler DragCompleted
+ public event EventHandler? DragCompleted
{
add { AddHandler(DragCompletedEvent, value); }
remove { RemoveHandler(DragCompletedEvent, value); }
diff --git a/src/Avalonia.Controls/Primitives/ToggleButton.cs b/src/Avalonia.Controls/Primitives/ToggleButton.cs
index 6b2c566422..4bdf6db2fc 100644
--- a/src/Avalonia.Controls/Primitives/ToggleButton.cs
+++ b/src/Avalonia.Controls/Primitives/ToggleButton.cs
@@ -61,7 +61,7 @@ namespace Avalonia.Controls.Primitives
///
/// Raised when a is checked.
///
- public event EventHandler Checked
+ public event EventHandler? Checked
{
add => AddHandler(CheckedEvent, value);
remove => RemoveHandler(CheckedEvent, value);
@@ -70,7 +70,7 @@ namespace Avalonia.Controls.Primitives
///
/// Raised when a is unchecked.
///
- public event EventHandler Unchecked
+ public event EventHandler? Unchecked
{
add => AddHandler(UncheckedEvent, value);
remove => RemoveHandler(UncheckedEvent, value);
@@ -79,7 +79,7 @@ namespace Avalonia.Controls.Primitives
///
/// Raised when a is neither checked nor unchecked.
///
- public event EventHandler Indeterminate
+ public event EventHandler? Indeterminate
{
add => AddHandler(IndeterminateEvent, value);
remove => RemoveHandler(IndeterminateEvent, value);
diff --git a/src/Avalonia.Controls/Primitives/Track.cs b/src/Avalonia.Controls/Primitives/Track.cs
index 9399f5fb31..f8d6046101 100644
--- a/src/Avalonia.Controls/Primitives/Track.cs
+++ b/src/Avalonia.Controls/Primitives/Track.cs
@@ -403,8 +403,8 @@ namespace Avalonia.Controls.Primitives
private void ThumbChanged(AvaloniaPropertyChangedEventArgs e)
{
- var oldThumb = (Thumb)e.OldValue;
- var newThumb = (Thumb)e.NewValue;
+ var oldThumb = (Thumb?)e.OldValue;
+ var newThumb = (Thumb?)e.NewValue;
if (oldThumb != null)
{
@@ -424,8 +424,8 @@ namespace Avalonia.Controls.Primitives
private void ButtonChanged(AvaloniaPropertyChangedEventArgs e)
{
- var oldButton = (Button)e.OldValue;
- var newButton = (Button)e.NewValue;
+ var oldButton = (Button?)e.OldValue;
+ var newButton = (Button?)e.NewValue;
if (oldButton != null)
{
@@ -440,7 +440,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void ThumbDragged(object sender, VectorEventArgs e)
+ private void ThumbDragged(object? sender, VectorEventArgs e)
{
if (IsThumbDragHandled)
return;
diff --git a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
index 03a84e26f2..df4edbd252 100644
--- a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
+++ b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Controls.Primitives
private const int LightDismissOverlayZIndex = int.MaxValue - 98;
private const int OverlayZIndex = int.MaxValue - 97;
- private ILogicalRoot _logicalRoot;
+ private ILogicalRoot? _logicalRoot;
private readonly List _layers = new List();
public static readonly StyledProperty ChromeOverlayLayerProperty =
@@ -50,7 +50,7 @@ namespace Avalonia.Controls.Primitives
}
}
- public OverlayLayer OverlayLayer
+ public OverlayLayer? OverlayLayer
{
get
{
@@ -81,7 +81,7 @@ namespace Avalonia.Controls.Primitives
}
}
- T FindLayer() where T : class
+ T? FindLayer() where T : class
{
foreach (var layer in _layers)
if (layer is T match)
@@ -97,7 +97,7 @@ namespace Avalonia.Controls.Primitives
VisualChildren.Add(layer);
if (((ILogical)this).IsAttachedToLogicalTree)
((ILogical)layer).NotifyAttachedToLogicalTree(
- new LogicalTreeAttachmentEventArgs(_logicalRoot, layer, this));
+ new LogicalTreeAttachmentEventArgs(_logicalRoot!, layer, this));
InvalidateArrange();
}
diff --git a/src/Avalonia.Controls/ProgressBar.cs b/src/Avalonia.Controls/ProgressBar.cs
index a848901bc3..017a053c48 100644
--- a/src/Avalonia.Controls/ProgressBar.cs
+++ b/src/Avalonia.Controls/ProgressBar.cs
@@ -96,7 +96,7 @@ namespace Avalonia.Controls
private double _indeterminateStartingOffset;
private double _indeterminateEndingOffset;
- private Border _indicator;
+ private Border? _indicator;
public static readonly StyledProperty IsIndeterminateProperty =
AvaloniaProperty.Register(nameof(IsIndeterminate));
diff --git a/src/Avalonia.Controls/Properties/AssemblyInfo.cs b/src/Avalonia.Controls/Properties/AssemblyInfo.cs
index d1743611cd..05561a38ef 100644
--- a/src/Avalonia.Controls/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Controls/Properties/AssemblyInfo.cs
@@ -3,6 +3,7 @@ using Avalonia.Metadata;
[assembly: InternalsVisibleTo("Avalonia.Controls.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
[assembly: InternalsVisibleTo("Avalonia.DesignerSupport, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.LeakTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")]
diff --git a/src/Avalonia.Controls/RadioButton.cs b/src/Avalonia.Controls/RadioButton.cs
index 681278d247..9dbc5f040e 100644
--- a/src/Avalonia.Controls/RadioButton.cs
+++ b/src/Avalonia.Controls/RadioButton.cs
@@ -22,7 +22,7 @@ namespace Avalonia.Controls
readonly Dictionary>> s_registeredGroups
= new Dictionary>>();
- public static RadioButtonGroupManager GetOrCreateForRoot(IRenderRoot root)
+ public static RadioButtonGroupManager GetOrCreateForRoot(IRenderRoot? root)
{
if (root == null)
return Default;
@@ -33,7 +33,7 @@ namespace Avalonia.Controls
{
lock (s_registeredGroups)
{
- string groupName = radioButton.GroupName;
+ string groupName = radioButton.GroupName!;
if (!s_registeredGroups.TryGetValue(groupName, out var group))
{
group = new List>();
@@ -71,7 +71,7 @@ namespace Avalonia.Controls
{
lock (s_registeredGroups)
{
- string groupName = radioButton.GroupName;
+ string groupName = radioButton.GroupName!;
if (s_registeredGroups.TryGetValue(groupName, out var group))
{
int i = 0;
@@ -95,21 +95,21 @@ namespace Avalonia.Controls
}
}
- public static readonly DirectProperty GroupNameProperty =
- AvaloniaProperty.RegisterDirect(
+ public static readonly DirectProperty GroupNameProperty =
+ AvaloniaProperty.RegisterDirect(
nameof(GroupName),
o => o.GroupName,
(o, v) => o.GroupName = v);
- private string _groupName;
- private RadioButtonGroupManager _groupManager;
+ private string? _groupName;
+ private RadioButtonGroupManager? _groupManager;
public RadioButton()
{
this.GetObservable(IsCheckedProperty).Subscribe(IsCheckedChanged);
}
- public string GroupName
+ public string? GroupName
{
get { return _groupName; }
set { SetGroupName(value); }
@@ -127,7 +127,7 @@ namespace Avalonia.Controls
{
if (!string.IsNullOrEmpty(GroupName))
{
- _groupManager?.Remove(this, _groupName);
+ _groupManager?.Remove(this, GroupName);
_groupManager = RadioButtonGroupManager.GetOrCreateForRoot(e.Root);
@@ -142,13 +142,13 @@ namespace Avalonia.Controls
if (!string.IsNullOrEmpty(GroupName))
{
- _groupManager?.Remove(this, _groupName);
+ _groupManager?.Remove(this, GroupName);
}
}
- private void SetGroupName(string newGroupName)
+ private void SetGroupName(string? newGroupName)
{
- string oldGroupName = GroupName;
+ var oldGroupName = GroupName;
if (newGroupName != oldGroupName)
{
if (!string.IsNullOrEmpty(oldGroupName))
@@ -169,7 +169,7 @@ namespace Avalonia.Controls
private void IsCheckedChanged(bool? value)
{
- string groupName = GroupName;
+ var groupName = GroupName;
if (string.IsNullOrEmpty(groupName))
{
var parent = this.GetVisualParent();
diff --git a/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs b/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
index 562b104b04..18cf96ddca 100644
--- a/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
+++ b/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
@@ -1,7 +1,5 @@
using Avalonia.Layout;
-#nullable enable
-
namespace Avalonia.Controls
{
public partial class RelativePanel
diff --git a/src/Avalonia.Controls/RelativePanel.cs b/src/Avalonia.Controls/RelativePanel.cs
index c5de004f09..1125f0eb0e 100644
--- a/src/Avalonia.Controls/RelativePanel.cs
+++ b/src/Avalonia.Controls/RelativePanel.cs
@@ -4,8 +4,6 @@ using System.Collections.Generic;
using System.Linq;
using Avalonia.Layout;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/Remote/RemoteServer.cs b/src/Avalonia.Controls/Remote/RemoteServer.cs
index 419792f004..f4cc91a0e6 100644
--- a/src/Avalonia.Controls/Remote/RemoteServer.cs
+++ b/src/Avalonia.Controls/Remote/RemoteServer.cs
@@ -24,7 +24,7 @@ namespace Avalonia.Controls.Remote
//TODO: Somehow react on closed connection?
}
- public object Content
+ public object? Content
{
get => _topLevel.Content;
set => _topLevel.Content = value;
diff --git a/src/Avalonia.Controls/Remote/RemoteWidget.cs b/src/Avalonia.Controls/Remote/RemoteWidget.cs
index b839a8769a..a88e0fd3d8 100644
--- a/src/Avalonia.Controls/Remote/RemoteWidget.cs
+++ b/src/Avalonia.Controls/Remote/RemoteWidget.cs
@@ -18,8 +18,8 @@ namespace Avalonia.Controls.Remote
}
private readonly IAvaloniaRemoteTransportConnection _connection;
- private FrameMessage _lastFrame;
- private WriteableBitmap _bitmap;
+ private FrameMessage? _lastFrame;
+ private WriteableBitmap? _bitmap;
public RemoteWidget(IAvaloniaRemoteTransportConnection connection)
{
Mode = SizingMode.Local;
diff --git a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
index 931c27c575..c9fd1dc3b8 100644
--- a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
+++ b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
@@ -21,22 +21,22 @@ namespace Avalonia.Controls.Remote.Server
public class RemoteServerTopLevelImpl : OffscreenTopLevelImplBase, IFramebufferPlatformSurface
{
private readonly IAvaloniaRemoteTransportConnection _transport;
- private LockedFramebuffer _framebuffer;
+ private LockedFramebuffer? _framebuffer;
private object _lock = new object();
private long _lastSentFrame = -1;
private long _lastReceivedFrame = -1;
private long _nextFrameNumber = 1;
- private ClientViewportAllocatedMessage _pendingAllocation;
+ private ClientViewportAllocatedMessage? _pendingAllocation;
private bool _invalidated;
private Vector _dpi = new Vector(96, 96);
- private ProtocolPixelFormat[] _supportedFormats;
+ private ProtocolPixelFormat[]? _supportedFormats;
public RemoteServerTopLevelImpl(IAvaloniaRemoteTransportConnection transport)
{
_transport = transport;
_transport.OnMessage += OnMessage;
- KeyboardDevice = AvaloniaLocator.Current.GetService();
+ KeyboardDevice = AvaloniaLocator.Current.GetRequiredService();
}
private static RawPointerEventType GetAvaloniaEventType (Avalonia.Remote.Protocol.Input.MouseButton button, bool pressed)
@@ -155,7 +155,7 @@ namespace Avalonia.Controls.Remote.Server
ClientViewportAllocatedMessage allocation;
lock (_lock)
{
- allocation = _pendingAllocation;
+ allocation = _pendingAllocation!;
_pendingAllocation = null;
}
_dpi = new Vector(allocation.DpiX, allocation.DpiY);
@@ -173,7 +173,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawPointerEventArgs(
MouseDevice,
0,
- InputRoot,
+ InputRoot!,
RawPointerEventType.Move,
new Point(pointer.X, pointer.Y),
GetAvaloniaInputModifiers(pointer.Modifiers)));
@@ -186,7 +186,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawPointerEventArgs(
MouseDevice,
0,
- InputRoot,
+ InputRoot!,
GetAvaloniaEventType(pressed.Button, true),
new Point(pressed.X, pressed.Y),
GetAvaloniaInputModifiers(pressed.Modifiers)));
@@ -199,7 +199,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawPointerEventArgs(
MouseDevice,
0,
- InputRoot,
+ InputRoot!,
GetAvaloniaEventType(released.Button, false),
new Point(released.X, released.Y),
GetAvaloniaInputModifiers(released.Modifiers)));
@@ -212,7 +212,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawMouseWheelEventArgs(
MouseDevice,
0,
- InputRoot,
+ InputRoot!,
new Point(scroll.X, scroll.Y),
new Vector(scroll.DeltaX, scroll.DeltaY),
GetAvaloniaInputModifiers(scroll.Modifiers)));
@@ -227,7 +227,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawKeyEventArgs(
KeyboardDevice,
0,
- InputRoot,
+ InputRoot!,
key.IsDown ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
(Key)key.Key,
GetAvaloniaRawInputModifiers(key.Modifiers)));
@@ -242,7 +242,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawTextInputEventArgs(
KeyboardDevice,
0,
- InputRoot,
+ InputRoot!,
text.Text));
}, DispatcherPriority.Input);
}
@@ -257,7 +257,7 @@ namespace Avalonia.Controls.Remote.Server
protected virtual Size Measure(Size constraint)
{
- var l = (ILayoutable) InputRoot;
+ var l = (ILayoutable) InputRoot!;
l.Measure(constraint);
return l.DesiredSize;
}
@@ -294,7 +294,7 @@ namespace Avalonia.Controls.Remote.Server
return new FrameMessage
{
Data = data,
- Format = (ProtocolPixelFormat) format,
+ Format = fmt,
Width = width,
Height = height,
Stride = width * bpp,
diff --git a/src/Avalonia.Controls/RepeatButton.cs b/src/Avalonia.Controls/RepeatButton.cs
index a21725cadf..0415a78721 100644
--- a/src/Avalonia.Controls/RepeatButton.cs
+++ b/src/Avalonia.Controls/RepeatButton.cs
@@ -21,7 +21,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty DelayProperty =
AvaloniaProperty.Register(nameof(Delay), 300);
- private DispatcherTimer _repeatTimer;
+ private DispatcherTimer? _repeatTimer;
///
/// Gets or sets the amount of time, in milliseconds, of repeating clicks.
@@ -55,10 +55,10 @@ namespace Avalonia.Controls
_repeatTimer.Start();
}
- private void RepeatTimerOnTick(object sender, EventArgs e)
+ private void RepeatTimerOnTick(object? sender, EventArgs e)
{
var interval = TimeSpan.FromMilliseconds(Interval);
- if (_repeatTimer.Interval != interval)
+ if (_repeatTimer!.Interval != interval)
{
_repeatTimer.Interval = interval;
}
diff --git a/src/Avalonia.Controls/Repeater/ElementFactory.cs b/src/Avalonia.Controls/Repeater/ElementFactory.cs
index 644e077221..6b776803d7 100644
--- a/src/Avalonia.Controls/Repeater/ElementFactory.cs
+++ b/src/Avalonia.Controls/Repeater/ElementFactory.cs
@@ -4,7 +4,7 @@ namespace Avalonia.Controls
{
public abstract class ElementFactory : IElementFactory
{
- public IControl Build(object data)
+ public IControl Build(object? data)
{
return GetElementCore(new ElementFactoryGetArgs { Data = data });
}
@@ -14,7 +14,7 @@ namespace Avalonia.Controls
return GetElementCore(args);
}
- public bool Match(object data) => true;
+ public bool Match(object? data) => true;
public void RecycleElement(ElementFactoryRecycleArgs args)
{
diff --git a/src/Avalonia.Controls/Repeater/IElementFactory.cs b/src/Avalonia.Controls/Repeater/IElementFactory.cs
index f424ae29b7..daab7e855f 100644
--- a/src/Avalonia.Controls/Repeater/IElementFactory.cs
+++ b/src/Avalonia.Controls/Repeater/IElementFactory.cs
@@ -12,13 +12,13 @@ namespace Avalonia.Controls
/// Gets or sets the data item for which an appropriate element tree should be realized
/// when calling .
///
- public object Data { get; set; }
+ public object? Data { get; set; }
///
/// Gets or sets the that is expected to be the parent of the
/// realized element from .
///
- public IControl Parent { get; set; }
+ public IControl? Parent { get; set; }
///
/// Gets or sets the index of the item that should be realized.
@@ -36,13 +36,13 @@ namespace Avalonia.Controls
/// Gets or sets the to recycle when calling
/// .
///
- public IControl Element { get; set; }
+ public IControl? Element { get; set; }
///
/// Gets or sets the that is expected to be the parent of the
/// realized element from .
///
- public IControl Parent { get; set; }
+ public IControl? Parent { get; set; }
}
///
diff --git a/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs b/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs
index dd97cde218..eb3b2ea787 100644
--- a/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs
+++ b/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs
@@ -13,8 +13,8 @@ namespace Avalonia.Controls
public ItemTemplateWrapper(IDataTemplate dataTemplate) => _dataTemplate = dataTemplate;
- public IControl Build(object param) => GetElement(null, param);
- public bool Match(object data) => _dataTemplate.Match(data);
+ public IControl Build(object? param) => GetElement(null, param);
+ public bool Match(object? data) => _dataTemplate.Match(data);
public IControl GetElement(ElementFactoryGetArgs args)
{
@@ -23,14 +23,14 @@ namespace Avalonia.Controls
public void RecycleElement(ElementFactoryRecycleArgs args)
{
- RecycleElement(args.Parent, args.Element);
+ RecycleElement(args.Parent, args.Element!);
}
- private IControl GetElement(IControl parent, object data)
+ private IControl GetElement(IControl? parent, object? data)
{
var selectedTemplate = _dataTemplate;
var recyclePool = RecyclePool.GetPoolInstance(selectedTemplate);
- IControl element = null;
+ IControl? element = null;
if (recyclePool != null)
{
@@ -41,7 +41,7 @@ namespace Avalonia.Controls
if (element == null)
{
// no element was found in recycle pool, create a new element
- element = selectedTemplate.Build(data);
+ element = selectedTemplate.Build(data)!;
// Associate template with element
element.SetValue(RecyclePool.OriginTemplateProperty, selectedTemplate);
@@ -50,7 +50,7 @@ namespace Avalonia.Controls
return element;
}
- private void RecycleElement(IControl parent, IControl element)
+ private void RecycleElement(IControl? parent, IControl element)
{
var selectedTemplate = _dataTemplate;
var recyclePool = RecyclePool.GetPoolInstance(selectedTemplate);
diff --git a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
index b40cf26df5..09c0e58332 100644
--- a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
+++ b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
@@ -31,13 +31,13 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty ItemTemplateProperty =
+ public static readonly StyledProperty ItemTemplateProperty =
ItemsControl.ItemTemplateProperty.AddOwner();
///
/// Defines the property.
///
- public static readonly DirectProperty ItemsProperty =
+ public static readonly DirectProperty ItemsProperty =
ItemsControl.ItemsProperty.AddOwner(o => o.Items, (o, v) => o.Items = v);
///
@@ -60,14 +60,14 @@ namespace Avalonia.Controls
private readonly ViewManager _viewManager;
private readonly ViewportManager _viewportManager;
- private IEnumerable _items;
- private VirtualizingLayoutContext _layoutContext;
- private EventHandler _childIndexChanged;
+ private IEnumerable? _items;
+ private VirtualizingLayoutContext? _layoutContext;
+ private EventHandler? _childIndexChanged;
private bool _isLayoutInProgress;
- private NotifyCollectionChangedEventArgs _processingItemsSourceChange;
- private ItemsRepeaterElementPreparedEventArgs _elementPreparedArgs;
- private ItemsRepeaterElementClearingEventArgs _elementClearingArgs;
- private ItemsRepeaterElementIndexChangedEventArgs _elementIndexChangedArgs;
+ private NotifyCollectionChangedEventArgs? _processingItemsSourceChange;
+ private ItemsRepeaterElementPreparedEventArgs? _elementPreparedArgs;
+ private ItemsRepeaterElementClearingEventArgs? _elementClearingArgs;
+ private ItemsRepeaterElementIndexChangedEventArgs? _elementIndexChangedArgs;
///
/// Initializes a new instance of the class.
@@ -102,7 +102,7 @@ namespace Avalonia.Controls
///
/// Gets or sets an object source used to generate the content of the ItemsRepeater.
///
- public IEnumerable Items
+ public IEnumerable? Items
{
get => _items;
set => SetAndRaise(ItemsProperty, ref _items, value);
@@ -111,7 +111,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the template used to display each item.
///
- public IDataTemplate ItemTemplate
+ public IDataTemplate? ItemTemplate
{
get => GetValue(ItemTemplateProperty);
set => SetValue(ItemTemplateProperty, value);
@@ -141,14 +141,14 @@ namespace Avalonia.Controls
/// Gets a standardized view of the supported interactions between a given Items object and
/// the ItemsRepeater control and its associated components.
///
- public ItemsSourceView ItemsSourceView { get; private set; }
+ public ItemsSourceView? ItemsSourceView { get; private set; }
- internal IElementFactory ItemTemplateShim { get; set; }
+ internal IElementFactory? ItemTemplateShim { get; set; }
internal Point LayoutOrigin { get; set; }
- internal object LayoutState { get; set; }
- internal IControl MadeAnchor => _viewportManager.MadeAnchor;
+ internal object? LayoutState { get; set; }
+ internal IControl? MadeAnchor => _viewportManager.MadeAnchor;
internal Rect RealizationWindow => _viewportManager.GetLayoutRealizationWindow();
- internal IControl SuggestedAnchor => _viewportManager.SuggestedAnchor;
+ internal IControl? SuggestedAnchor => _viewportManager.SuggestedAnchor;
private bool IsProcessingCollectionChange => _processingItemsSourceChange != null;
@@ -165,7 +165,7 @@ namespace Avalonia.Controls
}
}
- event EventHandler IChildIndexProvider.ChildIndexChanged
+ event EventHandler? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
@@ -180,7 +180,7 @@ namespace Avalonia.Controls
bool IChildIndexProvider.TryGetTotalCount(out int count)
{
- count = ItemsSourceView.Count;
+ count = ItemsSourceView?.Count ?? 0;
return true;
}
@@ -192,7 +192,7 @@ namespace Avalonia.Controls
/// outside the range of realized items. Elements are cleared when they become available
/// for re-use.
///
- public event EventHandler ElementClearing;
+ public event EventHandler? ElementClearing;
///
/// Occurs for each realized when the index for the item it
@@ -207,7 +207,7 @@ namespace Avalonia.Controls
/// represents has changed. For example, when another item is added or removed in the data
/// source, the index for items that come after in the ordering will be impacted.
///
- public event EventHandler ElementIndexChanged;
+ public event EventHandler? ElementIndexChanged;
///
/// Occurs each time an element is prepared for use.
@@ -216,7 +216,7 @@ namespace Avalonia.Controls
/// The prepared element might be newly created or an existing element that is being re-
/// used.
///
- public event EventHandler ElementPrepared;
+ public event EventHandler? ElementPrepared;
///
/// Retrieves the index of the item from the data source that corresponds to the specified
@@ -240,7 +240,7 @@ namespace Avalonia.Controls
/// he UIElement that corresponds to the item at the specified index if the item is
/// realized, or null if the item is not realized.
///
- public IControl TryGetElement(int index) => GetElementFromIndexImpl(index);
+ public IControl? TryGetElement(int index) => GetElementFromIndexImpl(index);
///
/// Retrieves the UIElement that corresponds to the item at the specified index in the
@@ -497,9 +497,9 @@ namespace Avalonia.Controls
return -1;
}
- private IControl GetElementFromIndexImpl(int index)
+ private IControl? GetElementFromIndexImpl(int index)
{
- IControl result = null;
+ IControl? result = null;
var children = Children;
for (var i = 0; i < children.Count && result == null; ++i)
@@ -517,7 +517,7 @@ namespace Avalonia.Controls
private IControl GetOrCreateElementImpl(int index)
{
- if (index >= 0 && index >= ItemsSourceView.Count)
+ if (index >= 0 && index >= (ItemsSourceView?.Count ?? 0))
{
throw new ArgumentException("Argument index is invalid.", "index");
}
@@ -544,7 +544,7 @@ namespace Avalonia.Controls
_viewportManager.OnMakeAnchor(element, isAnchorOutsideRealizedRange);
InvalidateMeasure();
- return element;
+ return element!;
}
internal void OnElementPrepared(IControl element, VirtualizationInfo virtInfo)
@@ -608,7 +608,7 @@ namespace Avalonia.Controls
_childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(element));
}
- private void OnDataSourcePropertyChanged(ItemsSourceView oldValue, ItemsSourceView newValue)
+ private void OnDataSourcePropertyChanged(ItemsSourceView? oldValue, ItemsSourceView? newValue)
{
if (_isLayoutInProgress)
{
@@ -664,7 +664,7 @@ namespace Avalonia.Controls
}
}
- private void OnItemTemplateChanged(IDataTemplate oldValue, IDataTemplate newValue)
+ private void OnItemTemplateChanged(IDataTemplate? oldValue, IDataTemplate? newValue)
{
if (_isLayoutInProgress && oldValue != null)
{
@@ -705,12 +705,17 @@ namespace Avalonia.Controls
}
}
- ItemTemplateShim = newValue as IElementFactory ?? new ItemTemplateWrapper(newValue);
+ ItemTemplateShim = newValue switch
+ {
+ IElementFactory factory => factory,
+ null => null,
+ _ => new ItemTemplateWrapper(newValue)
+ };
InvalidateMeasure();
}
- private void OnLayoutChanged(AttachedLayout oldValue, AttachedLayout newValue)
+ private void OnLayoutChanged(AttachedLayout? oldValue, AttachedLayout? newValue)
{
if (_isLayoutInProgress)
{
@@ -751,7 +756,7 @@ namespace Avalonia.Controls
InvalidateMeasure();
}
- private void OnItemsSourceViewChanged(object sender, NotifyCollectionChangedEventArgs args)
+ private void OnItemsSourceViewChanged(object? sender, NotifyCollectionChangedEventArgs args)
{
if (_isLayoutInProgress)
{
diff --git a/src/Avalonia.Controls/Repeater/RecyclePool.cs b/src/Avalonia.Controls/Repeater/RecyclePool.cs
index 28f299043c..9e2da81f99 100644
--- a/src/Avalonia.Controls/Repeater/RecyclePool.cs
+++ b/src/Avalonia.Controls/Repeater/RecyclePool.cs
@@ -22,7 +22,7 @@ namespace Avalonia.Controls
private static ConditionalWeakTable s_pools = new ConditionalWeakTable();
private readonly Dictionary> _elements = new Dictionary>();
- public static RecyclePool GetPoolInstance(IDataTemplate dataTemplate)
+ public static RecyclePool? GetPoolInstance(IDataTemplate dataTemplate)
{
s_pools.TryGetValue(dataTemplate, out var result);
return result;
@@ -30,7 +30,7 @@ namespace Avalonia.Controls
public static void SetPoolInstance(IDataTemplate dataTemplate, RecyclePool value) => s_pools.Add(dataTemplate, value);
- public void PutElement(IControl element, string key, IControl owner)
+ public void PutElement(IControl element, string key, IControl? owner)
{
var ownerAsPanel = EnsureOwnerIsPanelOrNull(owner);
var elementInfo = new ElementInfo(element, ownerAsPanel);
@@ -44,7 +44,7 @@ namespace Avalonia.Controls
pool.Add(elementInfo);
}
- public IControl TryGetElement(string key, IControl owner)
+ public IControl? TryGetElement(string key, IControl? owner)
{
if (_elements.TryGetValue(key, out var elements))
{
@@ -54,10 +54,10 @@ namespace Avalonia.Controls
// the enter/leave cost during recycling.
// TODO: prioritize elements with the same owner to those without an owner.
var elementInfo = elements.FirstOrDefault(x => x.Owner == owner) ?? elements.LastOrDefault();
- elements.Remove(elementInfo);
+ elements.Remove(elementInfo!);
var ownerAsPanel = EnsureOwnerIsPanelOrNull(owner);
- if (elementInfo.Owner != null && elementInfo.Owner != ownerAsPanel)
+ if (elementInfo!.Owner != null && elementInfo.Owner != ownerAsPanel)
{
// Element is still under its parent. remove it from its parent.
var panel = elementInfo.Owner;
@@ -83,7 +83,7 @@ namespace Avalonia.Controls
internal string GetReuseKey(IControl element) => element.GetValue(ReuseKeyProperty);
internal void SetReuseKey(IControl element, string value) => element.SetValue(ReuseKeyProperty, value);
- private IPanel EnsureOwnerIsPanelOrNull(IControl owner)
+ private IPanel? EnsureOwnerIsPanelOrNull(IControl? owner)
{
if (owner is IPanel panel)
{
@@ -99,14 +99,14 @@ namespace Avalonia.Controls
private class ElementInfo
{
- public ElementInfo(IControl element, IPanel owner)
+ public ElementInfo(IControl element, IPanel? owner)
{
Element = element;
Owner = owner;
}
public IControl Element { get; }
- public IPanel Owner { get;}
+ public IPanel? Owner { get;}
}
}
}
diff --git a/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs b/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs
index 9503239e34..c1baa66433 100644
--- a/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs
+++ b/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs
@@ -3,8 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using Avalonia.Controls.Templates;
-#nullable enable
-
namespace Avalonia.Controls
{
public class SelectTemplateEventArgs : EventArgs
@@ -71,7 +69,7 @@ namespace Avalonia.Controls
}
var dataTemplate = Templates[templateKey];
- element = dataTemplate.Build(args.Data);
+ element = dataTemplate.Build(args.Data)!;
// Associate ReuseKey with element
RecyclePool.SetReuseKey(element, templateKey);
@@ -82,12 +80,12 @@ namespace Avalonia.Controls
protected override void RecycleElementCore(ElementFactoryRecycleArgs args)
{
- var element = args.Element;
+ var element = args.Element!;
var key = RecyclePool.GetReuseKey(element);
RecyclePool.PutElement(element, key, args.Parent);
}
- protected virtual string OnSelectTemplateKeyCore(object dataContext, IControl owner)
+ protected virtual string OnSelectTemplateKeyCore(object? dataContext, IControl? owner)
{
if (SelectTemplateKey is object)
{
diff --git a/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs b/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs
index 733b045e1b..3370b36801 100644
--- a/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs
+++ b/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs
@@ -26,7 +26,7 @@ namespace Avalonia.Controls
set => _owner.LayoutOrigin = value;
}
- protected override object LayoutStateCore
+ protected override object? LayoutStateCore
{
get => _owner.LayoutState;
set => _owner.LayoutState = value;
@@ -57,7 +57,7 @@ namespace Avalonia.Controls
options.HasAllFlags(ElementRealizationOptions.SuppressAutoRecycle));
}
- protected override object GetItemAtCore(int index) => _owner.ItemsSourceView.GetAt(index);
+ protected override object GetItemAtCore(int index) => _owner.ItemsSourceView!.GetAt(index)!;
protected override void RecycleElementCore(ILayoutable element)
{
diff --git a/src/Avalonia.Controls/Repeater/UniqueIdElementPool.cs b/src/Avalonia.Controls/Repeater/UniqueIdElementPool.cs
index 775aa3f113..778b8bebcc 100644
--- a/src/Avalonia.Controls/Repeater/UniqueIdElementPool.cs
+++ b/src/Avalonia.Controls/Repeater/UniqueIdElementPool.cs
@@ -20,7 +20,7 @@ namespace Avalonia.Controls
public void Add(IControl element)
{
var virtInfo = ItemsRepeater.GetVirtualizationInfo(element);
- var key = virtInfo.UniqueId;
+ var key = virtInfo.UniqueId!;
if (_elementMap.ContainsKey(key))
{
@@ -30,10 +30,10 @@ namespace Avalonia.Controls
_elementMap.Add(key, element);
}
- public IControl Remove(int index)
+ public IControl? Remove(int index)
{
// Check if there is already a element in the mapping and if so, use it.
- string key = _owner.ItemsSourceView.KeyFromIndex(index);
+ string key = _owner.ItemsSourceView!.KeyFromIndex(index);
if (_elementMap.TryGetValue(key, out var element))
{
diff --git a/src/Avalonia.Controls/Repeater/ViewManager.cs b/src/Avalonia.Controls/Repeater/ViewManager.cs
index a7b6cf7f18..b28753b518 100644
--- a/src/Avalonia.Controls/Repeater/ViewManager.cs
+++ b/src/Avalonia.Controls/Repeater/ViewManager.cs
@@ -22,10 +22,10 @@ namespace Avalonia.Controls
private readonly ItemsRepeater _owner;
private readonly List _pinnedPool = new List();
private readonly UniqueIdElementPool _resetPool;
- private IControl _lastFocusedElement;
+ private IControl? _lastFocusedElement;
private bool _isDataSourceStableResetPending;
- private ElementFactoryGetArgs _elementFactoryGetArgs;
- private ElementFactoryRecycleArgs _elementFactoryRecycleArgs;
+ private ElementFactoryGetArgs? _elementFactoryGetArgs;
+ private ElementFactoryRecycleArgs? _elementFactoryRecycleArgs;
private int _firstRealizedElementIndexHeldByLayout = FirstRealizedElementIndexDefault;
private int _lastRealizedElementIndexHeldByLayout = LastRealizedElementIndexDefault;
private bool _eventsSubscribed;
@@ -170,7 +170,7 @@ namespace Avalonia.Controls
_lastFocusedElement = focusedChild;
// Add pin to hold the focused element.
- UpdatePin(focusedChild, true /* addPin */);
+ UpdatePin(focusedChild!, true /* addPin */);
}
else
{
@@ -179,14 +179,14 @@ namespace Avalonia.Controls
}
}
- IControl FindFocusCandidate(int clearedIndex, out IControl focusedChild)
+ IControl? FindFocusCandidate(int clearedIndex, out IControl? focusedChild)
{
// Walk through all the children and find elements with index before and after the cleared index.
// Note that during a delete the next element would now have the same index.
int previousIndex = int.MinValue;
int nextIndex = int.MaxValue;
- IControl nextElement = null;
- IControl previousElement = null;
+ IControl? nextElement = null;
+ IControl? previousElement = null;
foreach (var child in _owner.Children)
{
@@ -287,7 +287,7 @@ namespace Avalonia.Controls
}
}
- public void OnItemsSourceChanged(object sender, NotifyCollectionChangedEventArgs args)
+ public void OnItemsSourceChanged(object? sender, NotifyCollectionChangedEventArgs args)
{
// Note: For items that have been removed, the index will not be touched. It will hold
// the old index before it was removed. It is not valid anymore.
@@ -296,7 +296,7 @@ namespace Avalonia.Controls
case NotifyCollectionChangedAction.Add:
{
var newIndex = args.NewStartingIndex;
- var newCount = args.NewItems.Count;
+ var newCount = args.NewItems!.Count;
EnsureFirstLastRealizedIndices();
if (newIndex <= _lastRealizedElementIndexHeldByLayout)
{
@@ -343,8 +343,8 @@ namespace Avalonia.Controls
// depending on the counts.
var oldStartIndex = args.OldStartingIndex;
var newStartingIndex = args.NewStartingIndex;
- var oldCount = args.OldItems.Count;
- var newCount = args.NewItems.Count;
+ var oldCount = args.OldItems!.Count;
+ var newCount = args.NewItems!.Count;
if (oldStartIndex != newStartingIndex)
{
throw new NotSupportedException("Replace is only allowed with OldStartingIndex equals to NewStartingIndex.");
@@ -388,7 +388,7 @@ namespace Avalonia.Controls
case NotifyCollectionChangedAction.Remove:
{
var oldStartIndex = args.OldStartingIndex;
- var oldCount = args.OldItems.Count;
+ var oldCount = args.OldItems!.Count;
foreach (var element in _owner.Children)
{
var virtInfo = ItemsRepeater.GetVirtualizationInfo(element);
@@ -417,7 +417,7 @@ namespace Avalonia.Controls
// running layout, we dont have to clear all the elements again.
if (!_isDataSourceStableResetPending)
{
- if (_owner.ItemsSourceView.HasKeyIndexMapping)
+ if (_owner.ItemsSourceView!.HasKeyIndexMapping)
{
_isDataSourceStableResetPending = true;
}
@@ -482,9 +482,9 @@ namespace Avalonia.Controls
// If an index that is realized is requested by the layout, we unfortunately have to walk the
// children. Not ideal, but a reasonable default to provide consistent behavior between virtualizing
// and non-virtualizing hosts.
- private IControl GetElementIfAlreadyHeldByLayout(int index)
+ private IControl? GetElementIfAlreadyHeldByLayout(int index)
{
- IControl element = null;
+ IControl? element = null;
bool cachedFirstLastIndicesInvalid = _firstRealizedElementIndexHeldByLayout == FirstRealizedElementIndexDefault;
bool isRequestedIndexInRealizedRange = (_firstRealizedElementIndexHeldByLayout <= index && index <= _lastRealizedElementIndexHeldByLayout);
@@ -518,9 +518,9 @@ namespace Avalonia.Controls
return element;
}
- private IControl GetElementFromUniqueIdResetPool(int index)
+ private IControl? GetElementFromUniqueIdResetPool(int index)
{
- IControl element = null;
+ IControl? element = null;
// See if you can get it from the reset pool.
if (_isDataSourceStableResetPending)
{
@@ -541,9 +541,9 @@ namespace Avalonia.Controls
return element;
}
- private IControl GetElementFromPinnedElements(int index)
+ private IControl? GetElementFromPinnedElements(int index)
{
- IControl element = null;
+ IControl? element = null;
// See if you can find something among the pinned elements.
for (var i = 0; i < _pinnedPool.Count; ++i)
@@ -583,7 +583,7 @@ namespace Avalonia.Controls
private IControl GetElementFromElementFactory(int index)
{
// The view generator is the provider of last resort.
- var data = _owner.ItemsSourceView.GetAt(index);
+ var data = _owner.ItemsSourceView!.GetAt(index);
var providedElementFactory = _owner.ItemTemplateShim;
IElementFactory GetElementFactory()
@@ -592,7 +592,7 @@ namespace Avalonia.Controls
{
var factory = FuncDataTemplate.Default;
_owner.ItemTemplate = factory;
- return _owner.ItemTemplateShim;
+ return _owner.ItemTemplateShim!;
}
return providedElementFactory;
@@ -697,9 +697,9 @@ namespace Avalonia.Controls
private void UpdateFocusedElement()
{
- IControl focusedElement = null;
+ IControl? focusedElement = null;
- var child = FocusManager.Instance.Current;
+ var child = FocusManager.Instance?.Current;
if (child != null)
{
@@ -713,7 +713,9 @@ namespace Avalonia.Controls
if (parent is ItemsRepeater repeater)
{
var element = child as IControl;
- if (repeater == owner && ItemsRepeater.GetVirtualizationInfo(element).IsRealized)
+ if (repeater == owner &&
+ element is not null &&
+ ItemsRepeater.GetVirtualizationInfo(element).IsRealized)
{
focusedElement = element;
}
@@ -722,7 +724,7 @@ namespace Avalonia.Controls
}
child = parent as IInputElement;
- parent = child.VisualParent;
+ parent = child?.VisualParent;
}
}
@@ -744,7 +746,7 @@ namespace Avalonia.Controls
}
}
- private void OnFocusChanged(object sender, RoutedEventArgs e) => UpdateFocusedElement();
+ private void OnFocusChanged(object? sender, RoutedEventArgs e) => UpdateFocusedElement();
private void EnsureEventSubscriptions()
{
diff --git a/src/Avalonia.Controls/Repeater/ViewportManager.cs b/src/Avalonia.Controls/Repeater/ViewportManager.cs
index 1a90da5830..ec25fcb265 100644
--- a/src/Avalonia.Controls/Repeater/ViewportManager.cs
+++ b/src/Avalonia.Controls/Repeater/ViewportManager.cs
@@ -24,8 +24,8 @@ namespace Avalonia.Controls
private const double CacheBufferPerSideInflationPixelDelta = 40.0;
private readonly ItemsRepeater _owner;
private bool _ensuredScroller;
- private IScrollAnchorProvider _scroller;
- private IControl _makeAnchorElement;
+ private IScrollAnchorProvider? _scroller;
+ private IControl? _makeAnchorElement;
private bool _isAnchorOutsideRealizedRange;
private Rect _visibleWindow;
private Rect _layoutExtent;
@@ -57,7 +57,7 @@ namespace Avalonia.Controls
_owner = owner;
}
- public IControl SuggestedAnchor
+ public IControl? SuggestedAnchor
{
get
{
@@ -97,7 +97,7 @@ namespace Avalonia.Controls
public bool HasScroller => _scroller != null;
- public IControl MadeAnchor => _makeAnchorElement;
+ public IControl? MadeAnchor => _makeAnchorElement;
public double HorizontalCacheLength
{
@@ -213,7 +213,7 @@ namespace Avalonia.Controls
// We just finished a measure pass and have a new extent.
// Let's make sure the scrollers will run its arrange so that they track the anchor.
- ((IControl)_scroller)?.InvalidateArrange();
+ ((IControl?)_scroller)?.InvalidateArrange();
}
public Point GetOrigin() => _layoutExtent.TopLeft;
@@ -294,7 +294,7 @@ namespace Avalonia.Controls
}
}
- private void OnLayoutUpdated(object sender, EventArgs args)
+ private void OnLayoutUpdated(object? sender, EventArgs args)
{
_owner.LayoutUpdated -= OnLayoutUpdated;
_layoutUpdatedSubscribed = false;
@@ -324,7 +324,7 @@ namespace Avalonia.Controls
}
}
- public void OnMakeAnchor(IControl anchor, bool isAnchorOutsideRealizedRange)
+ public void OnMakeAnchor(IControl? anchor, bool isAnchorOutsideRealizedRange)
{
if (_makeAnchorElement != anchor)
{
@@ -346,7 +346,7 @@ namespace Avalonia.Controls
// get the targetChild - i.e the immediate child of this repeater that is being brought into view.
// Note that the element being brought into view could be a descendant.
- var targetChild = GetImmediateChildOfRepeater((IControl)args.TargetObject);
+ var targetChild = GetImmediateChildOfRepeater((IControl)args.TargetObject!);
if (targetChild is null)
{
@@ -382,14 +382,14 @@ namespace Avalonia.Controls
_scroller?.RegisterAnchorCandidate(element);
}
- private IControl GetImmediateChildOfRepeater(IControl descendant)
+ private IControl? GetImmediateChildOfRepeater(IControl descendant)
{
var targetChild = descendant;
- var parent = (IControl)descendant.VisualParent;
+ var parent = (IControl?)descendant.VisualParent;
while (parent != null && parent != _owner)
{
targetChild = parent;
- parent = (IControl)parent.VisualParent;
+ parent = (IControl?)parent.VisualParent;
}
if (parent == null)
@@ -441,7 +441,7 @@ namespace Avalonia.Controls
_ensuredScroller = false;
}
- private void OnEffectiveViewportChanged(object sender, EffectiveViewportChangedEventArgs e)
+ private void OnEffectiveViewportChanged(object? sender, EffectiveViewportChangedEventArgs e)
{
Logger.TryGet(LogEventLevel.Verbose, "Repeater")?.Log(this, "{LayoutId}: EffectiveViewportChanged event callback", _owner.Layout.LayoutId);
UpdateViewport(e.EffectiveViewport);
diff --git a/src/Avalonia.Controls/Repeater/VirtualizationInfo.cs b/src/Avalonia.Controls/Repeater/VirtualizationInfo.cs
index 7e6b24f1b5..7378dbcfa1 100644
--- a/src/Avalonia.Controls/Repeater/VirtualizationInfo.cs
+++ b/src/Avalonia.Controls/Repeater/VirtualizationInfo.cs
@@ -39,7 +39,7 @@ namespace Avalonia.Controls
public bool KeepAlive { get; set; }
public bool IsRegisteredAsAnchorCandidate { get; set; }
public ElementOwner Owner { get; private set; } = ElementOwner.ElementFactory;
- public string UniqueId { get; private set; }
+ public string? UniqueId { get; private set; }
public void MoveOwnershipToLayoutFromElementFactory(int index, string uniqueId)
{
diff --git a/src/Avalonia.Controls/RequestBringIntoViewEventArgs.cs b/src/Avalonia.Controls/RequestBringIntoViewEventArgs.cs
index dd55de85d4..5396ad67a7 100644
--- a/src/Avalonia.Controls/RequestBringIntoViewEventArgs.cs
+++ b/src/Avalonia.Controls/RequestBringIntoViewEventArgs.cs
@@ -5,7 +5,7 @@ namespace Avalonia.Controls
{
public class RequestBringIntoViewEventArgs : RoutedEventArgs
{
- public IVisual TargetObject { get; set; }
+ public IVisual? TargetObject { get; set; }
public Rect TargetRect { get; set; }
}
diff --git a/src/Avalonia.Controls/Screens.cs b/src/Avalonia.Controls/Screens.cs
index 8a0a0fa728..ef438576a7 100644
--- a/src/Avalonia.Controls/Screens.cs
+++ b/src/Avalonia.Controls/Screens.cs
@@ -9,20 +9,20 @@ namespace Avalonia.Controls
{
public class Screens
{
- private readonly IScreenImpl _iScreenImpl;
+ private readonly IScreenImpl? _iScreenImpl;
- public int ScreenCount => _iScreenImpl.ScreenCount;
+ public int ScreenCount => _iScreenImpl?.ScreenCount ?? 0;
public IReadOnlyList All => _iScreenImpl?.AllScreens ?? Array.Empty();
- public Screen Primary => All.FirstOrDefault(x => x.Primary);
+ public Screen? Primary => All.FirstOrDefault(x => x.Primary);
- public Screens(IScreenImpl iScreenImpl)
+ public Screens(IScreenImpl? iScreenImpl)
{
_iScreenImpl = iScreenImpl;
}
- public Screen ScreenFromBounds(PixelRect bounds){
+ public Screen? ScreenFromBounds(PixelRect bounds){
- Screen currMaxScreen = null;
+ Screen? currMaxScreen = null;
double maxAreaSize = 0;
foreach (Screen screen in All)
{
@@ -41,12 +41,12 @@ namespace Avalonia.Controls
return currMaxScreen;
}
- public Screen ScreenFromPoint(PixelPoint point)
+ public Screen? ScreenFromPoint(PixelPoint point)
{
return All.FirstOrDefault(x => x.Bounds.Contains(point));
}
- public Screen ScreenFromVisual(IVisual visual)
+ public Screen? ScreenFromVisual(IVisual visual)
{
var tl = visual.PointToScreen(visual.Bounds.TopLeft);
var br = visual.PointToScreen(visual.Bounds.BottomRight);
diff --git a/src/Avalonia.Controls/ScrollViewer.cs b/src/Avalonia.Controls/ScrollViewer.cs
index eee6216587..7c4b87e66a 100644
--- a/src/Avalonia.Controls/ScrollViewer.cs
+++ b/src/Avalonia.Controls/ScrollViewer.cs
@@ -181,6 +181,14 @@ namespace Avalonia.Controls
nameof(AllowAutoHide),
true);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly AttachedProperty IsScrollChainingEnabledProperty =
+ AvaloniaProperty.RegisterAttached(
+ nameof(IsScrollChainingEnabled),
+ defaultValue: true);
+
///
/// Defines the event.
///
@@ -191,8 +199,8 @@ namespace Avalonia.Controls
internal const double DefaultSmallChange = 16;
- private IDisposable _childSubscription;
- private ILogicalScrollable _logicalScrollable;
+ private IDisposable? _childSubscription;
+ private ILogicalScrollable? _logicalScrollable;
private Size _extent;
private Vector _offset;
private Size _viewport;
@@ -202,7 +210,7 @@ namespace Avalonia.Controls
private Size _largeChange;
private Size _smallChange = new Size(DefaultSmallChange, DefaultSmallChange);
private bool _isExpanded;
- private IDisposable _scrollBarExpandSubscription;
+ private IDisposable? _scrollBarExpandSubscription;
///
/// Initializes static members of the class.
@@ -224,7 +232,7 @@ namespace Avalonia.Controls
///
/// Occurs when changes are detected to the scroll position, extent, or viewport size.
///
- public event EventHandler ScrollChanged
+ public event EventHandler? ScrollChanged
{
add => AddHandler(ScrollChangedEvent, value);
remove => RemoveHandler(ScrollChangedEvent, value);
@@ -332,7 +340,7 @@ namespace Avalonia.Controls
}
///
- public IControl CurrentAnchor => (Presenter as IScrollAnchorProvider)?.CurrentAnchor;
+ public IControl? CurrentAnchor => (Presenter as IScrollAnchorProvider)?.CurrentAnchor;
///
/// Gets the maximum horizontal scrollbar value.
@@ -418,6 +426,20 @@ namespace Avalonia.Controls
set => SetValue(AllowAutoHideProperty, value);
}
+ ///
+ /// Gets or sets if scroll chaining is enabled. The default value is true.
+ ///
+ ///
+ /// After a user hits a scroll limit on an element that has been nested within another scrollable element,
+ /// you can specify whether that parent element should continue the scrolling operation begun in its child element.
+ /// This is called scroll chaining.
+ ///
+ public bool IsScrollChainingEnabled
+ {
+ get => GetValue(IsScrollChainingEnabledProperty);
+ set => SetValue(IsScrollChainingEnabledProperty, value);
+ }
+
///
/// Scrolls the content up one line.
///
@@ -548,6 +570,36 @@ namespace Avalonia.Controls
return control.GetValue(AllowAutoHideProperty);
}
+ ///
+ /// Sets the value of the IsScrollChainingEnabled attached property.
+ ///
+ /// The control to set the value on.
+ /// The value of the property.
+ ///
+ /// After a user hits a scroll limit on an element that has been nested within another scrollable element,
+ /// you can specify whether that parent element should continue the scrolling operation begun in its child element.
+ /// This is called scroll chaining.
+ ///
+ public static void SetIsScrollChainingEnabled(Control control, bool value)
+ {
+ control.SetValue(IsScrollChainingEnabledProperty, value);
+ }
+
+ ///
+ /// Gets the value of the IsScrollChainingEnabled attached property.
+ ///
+ /// The control to read the value from.
+ /// The value of the property.
+ ///
+ /// After a user hits a scroll limit on an element that has been nested within another scrollable element,
+ /// you can specify whether that parent element should continue the scrolling operation begun in its child element.
+ /// This is called scroll chaining.
+ ///
+ public static bool GetIsScrollChainingEnabled(Control control)
+ {
+ return control.GetValue(IsScrollChainingEnabledProperty);
+ }
+
///
/// Gets the value of the VerticalScrollBarVisibility attached property.
///
@@ -604,7 +656,7 @@ namespace Avalonia.Controls
return double.IsNaN(result) ? 0 : result;
}
- private void ChildChanged(IControl child)
+ private void ChildChanged(IControl? child)
{
if (_logicalScrollable is object)
{
@@ -621,7 +673,7 @@ namespace Avalonia.Controls
CalculatedPropertiesChanged();
}
- private void LogicalScrollInvalidated(object sender, EventArgs e)
+ private void LogicalScrollInvalidated(object? sender, EventArgs e)
{
CalculatedPropertiesChanged();
}
@@ -710,9 +762,9 @@ namespace Avalonia.Controls
_scrollBarExpandSubscription = SubscribeToScrollBars(e);
}
- private IDisposable SubscribeToScrollBars(TemplateAppliedEventArgs e)
+ private IDisposable? SubscribeToScrollBars(TemplateAppliedEventArgs e)
{
- static IObservable GetExpandedObservable(ScrollBar scrollBar)
+ static IObservable? GetExpandedObservable(ScrollBar? scrollBar)
{
return scrollBar?.GetObservable(ScrollBar.IsExpandedProperty);
}
@@ -723,7 +775,7 @@ namespace Avalonia.Controls
var horizontalExpanded = GetExpandedObservable(horizontalScrollBar);
var verticalExpanded = GetExpandedObservable(verticalScrollBar);
- IObservable actualExpanded = null;
+ IObservable? actualExpanded = null;
if (horizontalExpanded != null && verticalExpanded != null)
{
@@ -749,7 +801,7 @@ namespace Avalonia.Controls
IsExpanded = isExpanded;
}
- private void OnLayoutUpdated(object sender, EventArgs e) => RaiseScrollChanged();
+ private void OnLayoutUpdated(object? sender, EventArgs e) => RaiseScrollChanged();
private void RaiseScrollChanged()
{
diff --git a/src/Avalonia.Controls/Selection/ISelectionModel.cs b/src/Avalonia.Controls/Selection/ISelectionModel.cs
index 3b8fd0c8b7..3f4ae48263 100644
--- a/src/Avalonia.Controls/Selection/ISelectionModel.cs
+++ b/src/Avalonia.Controls/Selection/ISelectionModel.cs
@@ -3,8 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
public interface ISelectionModel : INotifyPropertyChanged
diff --git a/src/Avalonia.Controls/Selection/IndexRange.cs b/src/Avalonia.Controls/Selection/IndexRange.cs
index fa7b44faea..dd3445fb70 100644
--- a/src/Avalonia.Controls/Selection/IndexRange.cs
+++ b/src/Avalonia.Controls/Selection/IndexRange.cs
@@ -6,8 +6,6 @@
using System;
using System.Collections.Generic;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
internal readonly struct IndexRange : IEquatable
diff --git a/src/Avalonia.Controls/Selection/InternalSelectionModel.cs b/src/Avalonia.Controls/Selection/InternalSelectionModel.cs
index 73c0184ebb..40c6f63ed8 100644
--- a/src/Avalonia.Controls/Selection/InternalSelectionModel.cs
+++ b/src/Avalonia.Controls/Selection/InternalSelectionModel.cs
@@ -6,8 +6,6 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Avalonia.Collections;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
internal class InternalSelectionModel : SelectionModel
@@ -174,7 +172,7 @@ namespace Avalonia.Controls.Selection
}
}
- private void OnSelectionChanged(object sender, SelectionModelSelectionChangedEventArgs e)
+ private void OnSelectionChanged(object? sender, SelectionModelSelectionChangedEventArgs e)
{
if (_ignoreModelChanges > 0)
{
@@ -227,9 +225,9 @@ namespace Avalonia.Controls.Selection
}
}
- private void OnSourceReset(object sender, EventArgs e) => SyncFromSelectedItems();
+ private void OnSourceReset(object? sender, EventArgs e) => SyncFromSelectedItems();
- private void OnSelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void OnSelectedItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (_ignoreSelectedItemsChanges)
{
@@ -243,7 +241,7 @@ namespace Avalonia.Controls.Selection
void Remove()
{
- foreach (var i in e.OldItems)
+ foreach (var i in e.OldItems!)
{
var index = IndexOf(Source, i);
@@ -263,14 +261,14 @@ namespace Avalonia.Controls.Selection
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
- Add(e.NewItems);
+ Add(e.NewItems!);
break;
case NotifyCollectionChangedAction.Remove:
Remove();
break;
case NotifyCollectionChangedAction.Replace:
Remove();
- Add(e.NewItems);
+ Add(e.NewItems!);
break;
case NotifyCollectionChangedAction.Reset:
Clear();
diff --git a/src/Avalonia.Controls/Selection/SelectedIndexes.cs b/src/Avalonia.Controls/Selection/SelectedIndexes.cs
index 36df175ed2..a65f45e64f 100644
--- a/src/Avalonia.Controls/Selection/SelectedIndexes.cs
+++ b/src/Avalonia.Controls/Selection/SelectedIndexes.cs
@@ -3,8 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
internal class SelectedIndexes : IReadOnlyList
diff --git a/src/Avalonia.Controls/Selection/SelectedItems.cs b/src/Avalonia.Controls/Selection/SelectedItems.cs
index 92781fd54a..4fbcfde438 100644
--- a/src/Avalonia.Controls/Selection/SelectedItems.cs
+++ b/src/Avalonia.Controls/Selection/SelectedItems.cs
@@ -3,8 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
internal class SelectedItems : IReadOnlyList
diff --git a/src/Avalonia.Controls/Selection/SelectionModel.cs b/src/Avalonia.Controls/Selection/SelectionModel.cs
index 138a765b43..154f1868f3 100644
--- a/src/Avalonia.Controls/Selection/SelectionModel.cs
+++ b/src/Avalonia.Controls/Selection/SelectionModel.cs
@@ -6,8 +6,6 @@ using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
public class SelectionModel : SelectionNodeBase, ISelectionModel
@@ -78,8 +76,7 @@ namespace Avalonia.Controls.Selection
public IReadOnlyList SelectedIndexes => _selectedIndexes ??= new SelectedIndexes(this);
- [MaybeNull, AllowNull]
- public T SelectedItem
+ public T? SelectedItem
{
get
{
@@ -89,7 +86,7 @@ namespace Avalonia.Controls.Selection
}
else if (_initSelectedItems is object && _initSelectedItems.Count > 0)
{
- return (T)_initSelectedItems[0];
+ return (T?)_initSelectedItems[0];
}
return default;
@@ -394,9 +391,7 @@ namespace Avalonia.Controls.Selection
{
if (SingleSelect)
{
-#pragma warning disable CS8604
- removed = new List { (T)items[SelectedIndex - index] };
-#pragma warning restore CS8604
+ removed = new List { (T)items[SelectedIndex - index]! };
}
_selectedIndex = GetFirstSelectedIndexFromRanges();
@@ -466,12 +461,12 @@ namespace Avalonia.Controls.Selection
{
if (e.NewStartingIndex <= _selectedIndex)
{
- return _selectedIndex + e.NewItems.Count < ItemsView.Count;
+ return _selectedIndex + e.NewItems!.Count < ItemsView.Count;
}
if (e.NewStartingIndex <= _anchorIndex)
{
- return _anchorIndex + e.NewItems.Count < ItemsView.Count;
+ return _anchorIndex + e.NewItems!.Count < ItemsView.Count;
}
}
diff --git a/src/Avalonia.Controls/Selection/SelectionModelIndexesChangedEventArgs.cs b/src/Avalonia.Controls/Selection/SelectionModelIndexesChangedEventArgs.cs
index a1fef578a2..621fba48e8 100644
--- a/src/Avalonia.Controls/Selection/SelectionModelIndexesChangedEventArgs.cs
+++ b/src/Avalonia.Controls/Selection/SelectionModelIndexesChangedEventArgs.cs
@@ -1,7 +1,5 @@
using System;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
public class SelectionModelIndexesChangedEventArgs : EventArgs
diff --git a/src/Avalonia.Controls/Selection/SelectionModelSelectionChangedEventArgs.cs b/src/Avalonia.Controls/Selection/SelectionModelSelectionChangedEventArgs.cs
index 396943592d..64c1b14253 100644
--- a/src/Avalonia.Controls/Selection/SelectionModelSelectionChangedEventArgs.cs
+++ b/src/Avalonia.Controls/Selection/SelectionModelSelectionChangedEventArgs.cs
@@ -3,8 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using Avalonia.Controls.Selection;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
public abstract class SelectionModelSelectionChangedEventArgs : EventArgs
diff --git a/src/Avalonia.Controls/Selection/SelectionNodeBase.cs b/src/Avalonia.Controls/Selection/SelectionNodeBase.cs
index 230575074a..5994025d56 100644
--- a/src/Avalonia.Controls/Selection/SelectionNodeBase.cs
+++ b/src/Avalonia.Controls/Selection/SelectionNodeBase.cs
@@ -5,8 +5,6 @@ using System.Collections.Specialized;
using System.Linq;
using Avalonia.Controls.Utils;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
public abstract class SelectionNodeBase : ICollectionChangedListener
@@ -202,9 +200,7 @@ namespace Avalonia.Controls.Selection
{
for (var i = range.Begin; i <= range.End; ++i)
{
-#pragma warning disable CS8604
- removed.Add((T)items[i - index]);
-#pragma warning restore CS8604
+ removed.Add((T)items[i - index]!);
}
}
}
@@ -244,14 +240,14 @@ namespace Avalonia.Controls.Selection
{
case NotifyCollectionChangedAction.Add:
{
- var change = OnItemsAdded(e.NewStartingIndex, e.NewItems);
+ var change = OnItemsAdded(e.NewStartingIndex, e.NewItems!);
shiftIndex = change.ShiftIndex;
shiftDelta = change.ShiftDelta;
break;
}
case NotifyCollectionChangedAction.Remove:
{
- var change = OnItemsRemoved(e.OldStartingIndex, e.OldItems);
+ var change = OnItemsRemoved(e.OldStartingIndex, e.OldItems!);
shiftIndex = change.ShiftIndex;
shiftDelta = change.ShiftDelta;
removed = change.RemovedItems;
@@ -259,8 +255,8 @@ namespace Avalonia.Controls.Selection
}
case NotifyCollectionChangedAction.Replace:
{
- var removeChange = OnItemsRemoved(e.OldStartingIndex, e.OldItems);
- var addChange = OnItemsAdded(e.NewStartingIndex, e.NewItems);
+ var removeChange = OnItemsRemoved(e.OldStartingIndex, e.OldItems!);
+ var addChange = OnItemsAdded(e.NewStartingIndex, e.NewItems!);
shiftIndex = removeChange.ShiftIndex;
shiftDelta = removeChange.ShiftDelta + addChange.ShiftDelta;
removed = removeChange.RemovedItems;
@@ -303,7 +299,7 @@ namespace Avalonia.Controls.Selection
if (e.NewStartingIndex <= lastIndex)
{
- return lastIndex + e.NewItems.Count < ItemsView.Count;
+ return lastIndex + e.NewItems!.Count < ItemsView.Count;
}
}
diff --git a/src/Avalonia.Controls/Shapes/Path.cs b/src/Avalonia.Controls/Shapes/Path.cs
index d0ffc27d20..3502b4581f 100644
--- a/src/Avalonia.Controls/Shapes/Path.cs
+++ b/src/Avalonia.Controls/Shapes/Path.cs
@@ -8,7 +8,7 @@ namespace Avalonia.Controls.Shapes
public static readonly StyledProperty DataProperty =
AvaloniaProperty.Register(nameof(Data));
- private EventHandler _geometryChangedHandler;
+ private EventHandler? _geometryChangedHandler;
static Path()
{
@@ -22,7 +22,7 @@ namespace Avalonia.Controls.Shapes
set { SetValue(DataProperty, value); }
}
- private EventHandler GeometryChangedHandler => _geometryChangedHandler ??= GeometryChanged;
+ private EventHandler? GeometryChangedHandler => _geometryChangedHandler ??= GeometryChanged;
protected override Geometry CreateDefiningGeometry() => Data;
@@ -53,8 +53,8 @@ namespace Avalonia.Controls.Shapes
return;
}
- var oldGeometry = (Geometry)e.OldValue;
- var newGeometry = (Geometry)e.NewValue;
+ var oldGeometry = (Geometry?)e.OldValue;
+ var newGeometry = (Geometry?)e.NewValue;
if (oldGeometry is object)
{
@@ -67,7 +67,7 @@ namespace Avalonia.Controls.Shapes
}
}
- private void GeometryChanged(object sender, EventArgs e)
+ private void GeometryChanged(object? sender, EventArgs e)
{
InvalidateGeometry();
}
diff --git a/src/Avalonia.Controls/Shapes/Shape.cs b/src/Avalonia.Controls/Shapes/Shape.cs
index 0d1d9e3ffe..1a7218ff2a 100644
--- a/src/Avalonia.Controls/Shapes/Shape.cs
+++ b/src/Avalonia.Controls/Shapes/Shape.cs
@@ -3,8 +3,6 @@ using Avalonia.Collections;
using Avalonia.Media;
using Avalonia.Media.Immutable;
-#nullable enable
-
namespace Avalonia.Controls.Shapes
{
///
diff --git a/src/Avalonia.Controls/Slider.cs b/src/Avalonia.Controls/Slider.cs
index 6af40b0281..87de04f92f 100644
--- a/src/Avalonia.Controls/Slider.cs
+++ b/src/Avalonia.Controls/Slider.cs
@@ -81,14 +81,14 @@ namespace Avalonia.Controls
// Slider required parts
private bool _isDragging = false;
- private Track _track;
- private Button _decreaseButton;
- private Button _increaseButton;
- private IDisposable _decreaseButtonPressDispose;
- private IDisposable _decreaseButtonReleaseDispose;
- private IDisposable _increaseButtonSubscription;
- private IDisposable _increaseButtonReleaseDispose;
- private IDisposable _pointerMovedDispose;
+ private Track? _track;
+ private Button? _decreaseButton;
+ private Button? _increaseButton;
+ private IDisposable? _decreaseButtonPressDispose;
+ private IDisposable? _decreaseButtonReleaseDispose;
+ private IDisposable? _increaseButtonSubscription;
+ private IDisposable? _increaseButtonReleaseDispose;
+ private IDisposable? _pointerMovedDispose;
private const double Tolerance = 0.0001;
@@ -309,7 +309,7 @@ namespace Avalonia.Controls
}
}
- private void TrackMoved(object sender, PointerEventArgs e)
+ private void TrackMoved(object? sender, PointerEventArgs e)
{
if (_isDragging)
{
@@ -317,12 +317,12 @@ namespace Avalonia.Controls
}
}
- private void TrackReleased(object sender, PointerReleasedEventArgs e)
+ private void TrackReleased(object? sender, PointerReleasedEventArgs e)
{
_isDragging = false;
}
- private void TrackPressed(object sender, PointerPressedEventArgs e)
+ private void TrackPressed(object? sender, PointerPressedEventArgs e)
{
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{
@@ -333,6 +333,9 @@ namespace Avalonia.Controls
private void MoveToPoint(PointerPoint posOnTrack)
{
+ if (_track is null)
+ return;
+
var orient = Orientation == Orientation.Horizontal;
var thumbLength = (orient
? _track.Thumb.Bounds.Width
diff --git a/src/Avalonia.Controls/Spinner.cs b/src/Avalonia.Controls/Spinner.cs
index 5ee13f45c4..cfcf0ee376 100644
--- a/src/Avalonia.Controls/Spinner.cs
+++ b/src/Avalonia.Controls/Spinner.cs
@@ -114,7 +114,7 @@ namespace Avalonia.Controls
///
/// Occurs when spinning is initiated by the end-user.
///
- public event EventHandler Spin
+ public event EventHandler? Spin
{
add { AddHandler(SpinEvent, value); }
remove { RemoveHandler(SpinEvent, value); }
@@ -163,8 +163,8 @@ namespace Avalonia.Controls
{
if (e.Sender is Spinner spinner)
{
- var oldValue = (ValidSpinDirections)e.OldValue;
- var newValue = (ValidSpinDirections)e.NewValue;
+ var oldValue = (ValidSpinDirections)e.OldValue!;
+ var newValue = (ValidSpinDirections)e.NewValue!;
spinner.OnValidSpinDirectionChanged(oldValue, newValue);
}
}
diff --git a/src/Avalonia.Controls/SplitView.cs b/src/Avalonia.Controls/SplitView.cs
index 2ea58e6b0d..d2161deb6e 100644
--- a/src/Avalonia.Controls/SplitView.cs
+++ b/src/Avalonia.Controls/SplitView.cs
@@ -118,8 +118,8 @@ namespace Avalonia.Controls
///
/// Defines the property
///
- public static readonly StyledProperty PaneBackgroundProperty =
- AvaloniaProperty.Register(nameof(PaneBackground));
+ public static readonly StyledProperty PaneBackgroundProperty =
+ AvaloniaProperty.Register(nameof(PaneBackground));
///
/// Defines the property
@@ -130,8 +130,8 @@ namespace Avalonia.Controls
///
/// Defines the property
///
- public static readonly StyledProperty PaneProperty =
- AvaloniaProperty.Register(nameof(Pane));
+ public static readonly StyledProperty PaneProperty =
+ AvaloniaProperty.Register(nameof(Pane));
///
/// Defines the property.
@@ -152,8 +152,8 @@ namespace Avalonia.Controls
AvaloniaProperty.Register(nameof(TemplateSettings));
private bool _isPaneOpen;
- private Panel _pane;
- private IDisposable _pointerDisposable;
+ private Panel? _pane;
+ private IDisposable? _pointerDisposable;
public SplitView()
{
@@ -207,12 +207,12 @@ namespace Avalonia.Controls
if (value)
{
- OnPaneOpening(this, null);
+ OnPaneOpening(this, EventArgs.Empty);
SetAndRaise(IsPaneOpenProperty, ref _isPaneOpen, value);
PseudoClasses.Add(":open");
PseudoClasses.Remove(":closed");
- OnPaneOpened(this, null);
+ OnPaneOpened(this, EventArgs.Empty);
}
else
{
@@ -224,7 +224,7 @@ namespace Avalonia.Controls
PseudoClasses.Add(":closed");
PseudoClasses.Remove(":open");
- OnPaneClosed(this, null);
+ OnPaneClosed(this, EventArgs.Empty);
}
}
}
@@ -242,7 +242,7 @@ namespace Avalonia.Controls
///