diff --git a/.ncrunch/AppWithoutLifetime.v3.ncrunchproject b/.ncrunch/AppWithoutLifetime.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/AppWithoutLifetime.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject b/.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject b/.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/Avalonia.Desktop.slnf b/Avalonia.Desktop.slnf index 92c924f107..5e770a0170 100644 --- a/Avalonia.Desktop.slnf +++ b/Avalonia.Desktop.slnf @@ -39,14 +39,13 @@ "src\\Markup\\Avalonia.Markup.Xaml\\Avalonia.Markup.Xaml.csproj", "src\\Markup\\Avalonia.Markup\\Avalonia.Markup.csproj", "src\\Skia\\Avalonia.Skia\\Avalonia.Skia.csproj", - "src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj", - "src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj", - "src\\tools\\DevAnalyzers\\DevAnalyzers.csproj", - "src\\tools\\DevGenerators\\DevGenerators.csproj", - "src\\tools\\PublicAnalyzers\\Avalonia.Analyzers.csproj", "src\\Windows\\Avalonia.Direct2D1\\Avalonia.Direct2D1.csproj", "src\\Windows\\Avalonia.Win32.Interop\\Avalonia.Win32.Interop.csproj", "src\\Windows\\Avalonia.Win32\\Avalonia.Win32.csproj", + "src\\tools\\Avalonia.Analyzers\\Avalonia.Analyzers.csproj", + "src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj", + "src\\tools\\DevAnalyzers\\DevAnalyzers.csproj", + "src\\tools\\DevGenerators\\DevGenerators.csproj", "tests\\Avalonia.Base.UnitTests\\Avalonia.Base.UnitTests.csproj", "tests\\Avalonia.Benchmarks\\Avalonia.Benchmarks.csproj", "tests\\Avalonia.Controls.DataGrid.UnitTests\\Avalonia.Controls.DataGrid.UnitTests.csproj", @@ -66,4 +65,4 @@ "tests\\Avalonia.UnitTests\\Avalonia.UnitTests.csproj" ] } -} +} \ No newline at end of file diff --git a/Avalonia.sln b/Avalonia.sln index 9670327d67..0bae725d33 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -135,7 +135,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.LinuxFramebuffer", "src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj", "{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.Interop", "src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.Interoperability", "src\Windows\Avalonia.Win32.Interoperability\Avalonia.Win32.Interoperability.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.RenderTests", "tests\Avalonia.Skia.RenderTests\Avalonia.Skia.RenderTests.csproj", "{E1582370-37B3-403C-917F-8209551B1634}" EndProject @@ -251,6 +251,7 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Generators.Sandbox", "samples\Generators.Sandbox\Generators.Sandbox.csproj", "{A82AD1BC-EBE6-4FC3-A13B-D52A50297533}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppWithoutLifetime", "samples\AppWithoutLifetime\AppWithoutLifetime.csproj", "{F8928267-688E-4A51-989C-612A72446D33}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo", "samples\SafeAreaDemo\SafeAreaDemo.csproj", "{6B60A970-D5D2-49C2-8BAB-F9C7973B74B6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo.Android", "samples\SafeAreaDemo.Android\SafeAreaDemo.Android.csproj", "{22E3BC08-EAF7-4889-BDC4-B4D3046C4E2D}" diff --git a/build/SharedVersion.props b/build/SharedVersion.props index 2849262591..3239ca830a 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -4,7 +4,7 @@ Avalonia 11.0.999 Avalonia Team - Copyright 2022 © The AvaloniaUI Project + Copyright 2013-$([System.DateTime]::Now.ToString(`yyyy`)) © The AvaloniaUI Project https://avaloniaui.net https://github.com/AvaloniaUI/Avalonia/ true diff --git a/dirs.proj b/dirs.proj index d29aa61fcb..120212bd9f 100644 --- a/dirs.proj +++ b/dirs.proj @@ -14,11 +14,11 @@ + - - + + - diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs index 87e1e86bf9..524c9fa4e4 100644 --- a/nukebuild/Build.cs +++ b/nukebuild/Build.cs @@ -312,7 +312,7 @@ partial class Build : NukeBuild public static int Main() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) - ? Execute(x => x.RunToolsTests) + ? Execute(x => x.Package) : Execute(x => x.RunTests); } diff --git a/nukebuild/RefAssemblyGenerator.cs b/nukebuild/RefAssemblyGenerator.cs index f0d5c81a37..54e428c442 100644 --- a/nukebuild/RefAssemblyGenerator.cs +++ b/nukebuild/RefAssemblyGenerator.cs @@ -63,52 +63,89 @@ public class RefAssemblyGenerator }); } + static bool HasPrivateApi(IEnumerable attrs) => attrs.Any(a => + a.AttributeType.FullName == "Avalonia.Metadata.PrivateApiAttribute"); + static void ProcessType(TypeDefinition type, MethodReference obsoleteCtor) { foreach (var nested in type.NestedTypes) ProcessType(nested, obsoleteCtor); - if (type.IsInterface) + + var hideMembers = (type.IsInterface && type.Name.EndsWith("Impl")) + || HasPrivateApi(type.CustomAttributes); + + var injectMethod = hideMembers + || type.CustomAttributes.Any(a => + a.AttributeType.FullName == "Avalonia.Metadata.NotClientImplementableAttribute"); + + + + if (injectMethod) { - var hideMethods = type.Name.EndsWith("Impl") - || (type.HasCustomAttributes && type.CustomAttributes.Any(a => - a.AttributeType.FullName == "Avalonia.Metadata.PrivateApiAttribute")); + type.Methods.Add(new MethodDefinition( + "(This interface or abstract class is -not- implementable by user code !)", + MethodAttributes.Assembly + | MethodAttributes.Abstract + | MethodAttributes.NewSlot + | MethodAttributes.HideBySig, type.Module.TypeSystem.Void)); + } - var injectMethod = hideMethods - || type.CustomAttributes.Any(a => - a.AttributeType.FullName == "Avalonia.Metadata.NotClientImplementableAttribute"); - - if (hideMethods) + var forceUnstable = type.CustomAttributes.FirstOrDefault(a => + a.AttributeType.FullName == "Avalonia.Metadata.UnstableAttribute"); + + foreach (var m in type.Methods) + { + if (hideMembers || HasPrivateApi(m.CustomAttributes)) { - foreach (var m in type.Methods) - { - var dflags = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.FamORAssem | - MethodAttributes.FamANDAssem | MethodAttributes.Assembly; - m.Attributes = ((m.Attributes | dflags) ^ dflags) | MethodAttributes.Assembly; - } + HideMethod(m); } - - if(injectMethod) + MarkAsUnstable(m, obsoleteCtor, forceUnstable); + } + + foreach (var p in type.Properties) + { + if (HasPrivateApi(p.CustomAttributes)) { - type.Methods.Add(new MethodDefinition("NotClientImplementable", - MethodAttributes.Assembly - | MethodAttributes.Abstract - | MethodAttributes.NewSlot - | MethodAttributes.HideBySig, type.Module.TypeSystem.Void)); + if (p.SetMethod != null) + HideMethod(p.SetMethod); + if (p.GetMethod != null) + HideMethod(p.GetMethod); } + } - var forceUnstable = type.CustomAttributes.FirstOrDefault(a => - a.AttributeType.FullName == "Avalonia.Metadata.UnstableAttribute"); - - foreach (var m in type.Methods) - MarkAsUnstable(m, obsoleteCtor, forceUnstable); - foreach (var m in type.Properties) - MarkAsUnstable(m, obsoleteCtor, forceUnstable); - foreach (var m in type.Events) - MarkAsUnstable(m, obsoleteCtor, forceUnstable); - + foreach (var f in type.Fields) + { + if (hideMembers || HasPrivateApi(f.CustomAttributes)) + { + var dflags = FieldAttributes.Public | FieldAttributes.Family | FieldAttributes.FamORAssem | + FieldAttributes.FamANDAssem | FieldAttributes.Assembly; + f.Attributes = ((f.Attributes | dflags) ^ dflags) | FieldAttributes.Assembly; + } } + + foreach (var cl in type.NestedTypes) + { + ProcessType(cl, obsoleteCtor); + if (hideMembers) + { + var dflags = TypeAttributes.Public; + cl.Attributes = ((cl.Attributes | dflags) ^ dflags) | TypeAttributes.NotPublic; + } + } + + foreach (var m in type.Properties) + MarkAsUnstable(m, obsoleteCtor, forceUnstable); + foreach (var m in type.Events) + MarkAsUnstable(m, obsoleteCtor, forceUnstable); } + static void HideMethod(MethodDefinition m) + { + var dflags = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.FamORAssem | + MethodAttributes.FamANDAssem | MethodAttributes.Assembly; + m.Attributes = ((m.Attributes | dflags) ^ dflags) | MethodAttributes.Assembly; + } + static void MarkAsUnstable(IMemberDefinition def, MethodReference obsoleteCtor, ICustomAttribute unstableAttribute) { if (def.CustomAttributes.Any(a => a.AttributeType.FullName == "System.ObsoleteAttribute")) diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj index 8999b7ca76..30e1200220 100644 --- a/nukebuild/_build.csproj +++ b/nukebuild/_build.csproj @@ -35,6 +35,12 @@ + + + + dirs.proj + + diff --git a/packages/Avalonia/Avalonia.csproj b/packages/Avalonia/Avalonia.csproj index 412251bc9c..3f313ead1b 100644 --- a/packages/Avalonia/Avalonia.csproj +++ b/packages/Avalonia/Avalonia.csproj @@ -5,7 +5,7 @@ - + all diff --git a/packages/Avalonia/Avalonia.targets b/packages/Avalonia/Avalonia.targets index 50306f2cdc..eacd287b59 100644 --- a/packages/Avalonia/Avalonia.targets +++ b/packages/Avalonia/Avalonia.targets @@ -1,3 +1,4 @@ + diff --git a/packages/Avalonia/AvaloniaPrivateApis.targets b/packages/Avalonia/AvaloniaPrivateApis.targets new file mode 100644 index 0000000000..5343559c07 --- /dev/null +++ b/packages/Avalonia/AvaloniaPrivateApis.targets @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + net6.0 + netstandard2.0 + + + + + + + + + diff --git a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj index c6405dabb6..2c47effa38 100644 --- a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj +++ b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj @@ -4,10 +4,17 @@ Exe net461 x64 + true + ../ControlCatalog.NetCore/app.manifest + + + + + diff --git a/samples/ControlCatalog.Desktop/Program.cs b/samples/ControlCatalog.Desktop/Program.cs index 4d28f15e2c..eeb2095201 100644 --- a/samples/ControlCatalog.Desktop/Program.cs +++ b/samples/ControlCatalog.Desktop/Program.cs @@ -3,6 +3,8 @@ using System.Linq; using Avalonia; using Avalonia.Controls; using Avalonia.Platform; +using ControlCatalog.NetCore; +using ControlCatalog.Pages; namespace ControlCatalog { @@ -18,6 +20,15 @@ namespace ControlCatalog public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure() .LogToTrace() + .AfterSetup(builder => + { + builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions() + { + StartupScreenIndex = 1, + }); + + EmbedSample.Implementation = new EmbedSampleWin(); + }) .UsePlatformDetect(); private static void ConfigureAssetAssembly(AppBuilder builder) diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj index 877d475fb6..37719b77d8 100644 --- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj +++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj @@ -16,6 +16,7 @@ + diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs index 9c511f9eb0..801844a43c 100644 --- a/samples/ControlCatalog/MainView.xaml.cs +++ b/samples/ControlCatalog/MainView.xaml.cs @@ -83,9 +83,10 @@ namespace ControlCatalog if (transparencyLevels.SelectedItem is WindowTransparencyLevel selected) { var topLevel = (TopLevel)this.GetVisualRoot()!; - topLevel.TransparencyLevelHint = selected; + topLevel.TransparencyLevelHint = new[] { selected }; - if (selected != WindowTransparencyLevel.None) + if (topLevel.ActualTransparencyLevel != WindowTransparencyLevel.None && + topLevel.ActualTransparencyLevel == selected) { var transparentBrush = new ImmutableSolidColorBrush(Colors.White, 0); var semiTransparentBrush = new ImmutableSolidColorBrush(Colors.Gray, 0.2); diff --git a/samples/ControlCatalog/Pages/ColorPickerPage.xaml b/samples/ControlCatalog/Pages/ColorPickerPage.xaml index b759720cf2..25fffabfd2 100644 --- a/samples/ControlCatalog/Pages/ColorPickerPage.xaml +++ b/samples/ControlCatalog/Pages/ColorPickerPage.xaml @@ -103,7 +103,8 @@ HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}" />--> + HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}" + Margin="0,2,0,0" /> diff --git a/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs b/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs index 96fcb54650..664264956f 100644 --- a/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs @@ -19,8 +19,8 @@ namespace ControlCatalog.Pages customContextRequestedBorder.AddHandler(ContextRequestedEvent, CustomContextRequested, RoutingStrategies.Tunnel); var cancellableContextBorder = this.Get("CancellableContextBorder"); - cancellableContextBorder.ContextMenu!.ContextMenuClosing += ContextFlyoutPage_Closing; - cancellableContextBorder.ContextMenu!.ContextMenuOpening += ContextFlyoutPage_Opening; + cancellableContextBorder.ContextMenu!.Closing += ContextFlyoutPage_Closing; + cancellableContextBorder.ContextMenu!.Opening += ContextFlyoutPage_Opening; } private ContextPageViewModel? _model; diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs index 971a6a6718..4d617fd313 100644 --- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs +++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs @@ -307,7 +307,7 @@ namespace ControlCatalog.Pages Content: "; - resultText += await ReadTextFromFile(file, 10000); + resultText += await ReadTextFromFile(file, 500); } openedFileContent.Text = resultText; diff --git a/samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs b/samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs index 7fb5bec589..aef82768c8 100644 --- a/samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs +++ b/samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Linq; using System.Reflection; using Avalonia.Controls; @@ -23,7 +22,7 @@ namespace ControlCatalog.Pages $"Text was dragged {++textCount} times"), DragDropEffects.Copy | DragDropEffects.Move | DragDropEffects.Link); SetupDnd("Custom", d => d.Set(CustomFormat, "Test123"), DragDropEffects.Move); - SetupDnd("Files", d => d.Set(DataFormats.Files, new[] { Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName }), DragDropEffects.Copy); + SetupDnd("Files", async d => d.Set(DataFormats.Files, new[] { await (VisualRoot as TopLevel)!.StorageProvider.TryGetFileFromPathAsync(Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName) }), DragDropEffects.Copy); } void SetupDnd(string suffix, Action factory, DragDropEffects effects) @@ -99,7 +98,7 @@ namespace ControlCatalog.Pages { if (item is IStorageFile file) { - var content = await DialogsPage.ReadTextFromFile(file, 1000); + var content = await DialogsPage.ReadTextFromFile(file, 500); contentStr += $"File {item.Name}:{Environment.NewLine}{content}{Environment.NewLine}{Environment.NewLine}"; } else if (item is IStorageFolder folder) diff --git a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs index 70ce6107ad..2219966daa 100644 --- a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs @@ -117,9 +117,8 @@ namespace ControlCatalog.Pages private void ScrollTo(int index) { System.Diagnostics.Debug.WriteLine("Scroll to " + index); - var layoutManager = ((TopLevel)VisualRoot!).LayoutManager; var element = _repeater.GetOrCreateElement(index); - layoutManager.ExecuteLayoutPass(); + ((TopLevel)VisualRoot!).UpdateLayout(); element.BringIntoView(); } diff --git a/samples/ControlCatalog/Pages/TabControlPage.xaml b/samples/ControlCatalog/Pages/TabControlPage.xaml index 3a2464e9fd..1faa74c1ce 100644 --- a/samples/ControlCatalog/Pages/TabControlPage.xaml +++ b/samples/ControlCatalog/Pages/TabControlPage.xaml @@ -4,7 +4,27 @@ xmlns="https://github.com/avaloniaui" xmlns:viewModels="using:ControlCatalog.ViewModels" x:DataType="viewModels:TabControlPageViewModel"> - + + + + + + - + - + + + + + + --> + diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml index e05fa5a907..520e6e8db3 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml @@ -1,6 +1,7 @@  + xmlns:pc="using:Avalonia.Controls.Primitives.Converters" + x:ClassModifier="internal"> 80 @@ -8,7 +9,9 @@ - + + + @@ -21,7 +24,6 @@ Height="{StaticResource ColorPreviewerAccentSectionHeight}" Width="{StaticResource ColorPreviewerAccentSectionWidth}" ColumnDefinitions="*,*" - Margin="0,0,-10,0" VerticalAlignment="Center"> + CornerRadius="{TemplateBinding CornerRadius}"> @@ -82,8 +81,7 @@ + VerticalAlignment="Stretch"> diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml index 789473571b..edc6246ddd 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml index ebbb006fd1..c9972125a0 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml @@ -1,6 +1,7 @@  + xmlns:controls="using:Avalonia.Controls" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml index acd2c7ff15..9ca55566f3 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml @@ -4,7 +4,8 @@ xmlns:converters="using:Avalonia.Controls.Converters" xmlns:primitives="using:Avalonia.Controls.Primitives" xmlns:pc="using:Avalonia.Controls.Primitives.Converters" - xmlns:globalization="using:System.Globalization"> + xmlns:globalization="using:System.Globalization" + x:ClassModifier="internal"> @@ -360,8 +361,8 @@ - + + + + diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPicker.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPicker.xaml index ff4e1d93a8..c20f7935f4 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPicker.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPicker.xaml @@ -1,7 +1,8 @@  + xmlns:primitives="using:Avalonia.Controls.Primitives" + x:ClassModifier="internal"> @@ -112,8 +113,8 @@ - + @@ -501,6 +502,23 @@ + + + diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPreviewer.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPreviewer.xaml index a39dd91f52..23f0b34ddd 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPreviewer.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorPreviewer.xaml @@ -1,6 +1,7 @@  + xmlns:pc="using:Avalonia.Controls.Primitives.Converters" + x:ClassModifier="internal"> 80 @@ -8,7 +9,9 @@ - + + + @@ -21,7 +24,6 @@ Height="{StaticResource ColorPreviewerAccentSectionHeight}" Width="{StaticResource ColorPreviewerAccentSectionWidth}" ColumnDefinitions="*,*" - Margin="0,0,-10,0" VerticalAlignment="Center"> + CornerRadius="{TemplateBinding CornerRadius}"> @@ -82,8 +81,7 @@ + VerticalAlignment="Stretch"> diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSlider.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSlider.xaml index 472f1ca100..6b4ad68275 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSlider.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSlider.xaml @@ -1,5 +1,6 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSpectrum.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSpectrum.xaml index a7ad56d8b4..101a06ccb9 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSpectrum.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorSpectrum.xaml @@ -1,6 +1,7 @@  + xmlns:controls="using:Avalonia.Controls" + x:ClassModifier="internal"> diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml index a26d3179b5..994a5e1bbc 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Simple/ColorView.xaml @@ -4,7 +4,8 @@ xmlns:converters="using:Avalonia.Controls.Converters" xmlns:primitives="using:Avalonia.Controls.Primitives" xmlns:pc="using:Avalonia.Controls.Primitives.Converters" - xmlns:globalization="using:System.Globalization"> + xmlns:globalization="using:System.Globalization" + x:ClassModifier="internal"> @@ -322,8 +323,8 @@ - + + + + diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs index a55a47fa53..7ade9f2437 100644 --- a/src/Avalonia.Controls.DataGrid/DataGrid.cs +++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs @@ -2660,25 +2660,25 @@ namespace Avalonia.Controls internal bool ProcessDownKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); return ProcessDownKeyInternal(shift, ctrl); } internal bool ProcessEndKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); return ProcessEndKey(shift, ctrl); } internal bool ProcessEnterKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); return ProcessEnterKey(shift, ctrl); } internal bool ProcessHomeKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); return ProcessHomeKey(shift, ctrl); } @@ -2718,25 +2718,25 @@ namespace Avalonia.Controls internal bool ProcessLeftKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); return ProcessLeftKey(shift, ctrl); } internal bool ProcessNextKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); return ProcessNextKey(shift, ctrl); } internal bool ProcessPriorKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); return ProcessPriorKey(shift, ctrl); } internal bool ProcessRightKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); return ProcessRightKey(shift, ctrl); } @@ -2854,7 +2854,7 @@ namespace Avalonia.Controls internal bool ProcessUpKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); return ProcessUpKey(shift, ctrl); } @@ -3124,13 +3124,13 @@ namespace Avalonia.Controls //TODO: Ensure right button is checked for internal bool UpdateStateOnMouseRightButtonDown(PointerPressedEventArgs pointerPressedEventArgs, int columnIndex, int slot, bool allowEdit) { - KeyboardHelper.GetMetaKeyState(pointerPressedEventArgs.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, pointerPressedEventArgs.KeyModifiers, out bool ctrl, out bool shift); return UpdateStateOnMouseRightButtonDown(pointerPressedEventArgs, columnIndex, slot, allowEdit, shift, ctrl); } //TODO: Ensure left button is checked for internal bool UpdateStateOnMouseLeftButtonDown(PointerPressedEventArgs pointerPressedEventArgs, int columnIndex, int slot, bool allowEdit) { - KeyboardHelper.GetMetaKeyState(pointerPressedEventArgs.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, pointerPressedEventArgs.KeyModifiers, out bool ctrl, out bool shift); return UpdateStateOnMouseLeftButtonDown(pointerPressedEventArgs, columnIndex, slot, allowEdit, shift, ctrl); } @@ -3958,7 +3958,7 @@ namespace Avalonia.Controls { bool focusLeftDataGrid = true; bool dataGridWillReceiveRoutedEvent = true; - Visual focusedObject = FocusManager.Instance.Current as Visual; + Visual focusedObject = FocusManager.GetFocusManager(this)?.GetFocusedElement() as Visual; DataGridColumn editingColumn = null; while (focusedObject != null) @@ -4654,7 +4654,7 @@ namespace Avalonia.Controls private bool ProcessAKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift, out bool alt); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift, out bool alt); if (ctrl && !shift && !alt && SelectionMode == DataGridSelectionMode.Extended) { @@ -4865,7 +4865,8 @@ namespace Avalonia.Controls if (!ctrl) { // If Enter was used by a TextBox, we shouldn't handle the key - if (FocusManager.Instance.Current is TextBox focusedTextBox && focusedTextBox.AcceptsReturn) + if (FocusManager.GetFocusManager(this)?.GetFocusedElement() is TextBox focusedTextBox + && focusedTextBox.AcceptsReturn) { return false; } @@ -4922,7 +4923,7 @@ namespace Avalonia.Controls private bool ProcessF2Key(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); if (!shift && !ctrl && _editingColumnIndex == -1 && CurrentColumnIndex != -1 && GetRowSelection(CurrentSlot) && @@ -5279,7 +5280,7 @@ namespace Avalonia.Controls private bool ProcessTabKey(KeyEventArgs e) { - KeyboardHelper.GetMetaKeyState(e.KeyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, e.KeyModifiers, out bool ctrl, out bool shift); return ProcessTabKey(e, shift, ctrl); } @@ -6098,7 +6099,7 @@ namespace Avalonia.Controls /// Whether or not the DataGrid handled the key press. private bool ProcessCopyKey(KeyModifiers modifiers) { - KeyboardHelper.GetMetaKeyState(modifiers, out bool ctrl, out bool shift, out bool alt); + KeyboardHelper.GetMetaKeyState(this, modifiers, out bool ctrl, out bool shift, out bool alt); if (ctrl && !shift && !alt && ClipboardCopyMode != DataGridClipboardCopyMode.None && SelectedItems.Count > 0) { diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs index d1e1efdd85..96d072260c 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumn.cs @@ -703,7 +703,7 @@ namespace Avalonia.Controls public void ClearSort() { //InvokeProcessSort is already validating if sorting is possible - _headerCell?.InvokeProcessSort(KeyboardHelper.GetPlatformCtrlOrCmdKeyModifier()); + _headerCell?.InvokeProcessSort(KeyboardHelper.GetPlatformCtrlOrCmdKeyModifier(OwningGrid)); } /// diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs index ef1e84c745..0755864c25 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs @@ -241,7 +241,7 @@ namespace Avalonia.Controls DataGrid owningGrid = OwningGrid; DataGridSortDescription newSort; - KeyboardHelper.GetMetaKeyState(keyModifiers, out bool ctrl, out bool shift); + KeyboardHelper.GetMetaKeyState(this, keyModifiers, out bool ctrl, out bool shift); DataGridSortDescription sort = OwningColumn.GetSortDescription(); IDataGridCollectionView collectionView = owningGrid.DataConnection.CollectionView; diff --git a/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs b/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs index d2b1fd4b8e..bcb30888dc 100644 --- a/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs +++ b/src/Avalonia.Controls.DataGrid/Utils/KeyboardHelper.cs @@ -10,23 +10,23 @@ namespace Avalonia.Controls.Utils { internal static class KeyboardHelper { - public static void GetMetaKeyState(KeyModifiers modifiers, out bool ctrlOrCmd, out bool shift) + public static void GetMetaKeyState(Control target, KeyModifiers modifiers, out bool ctrlOrCmd, out bool shift) { - ctrlOrCmd = modifiers.HasFlag(GetPlatformCtrlOrCmdKeyModifier()); + ctrlOrCmd = modifiers.HasFlag(GetPlatformCtrlOrCmdKeyModifier(target)); shift = modifiers.HasFlag(KeyModifiers.Shift); } - public static void GetMetaKeyState(KeyModifiers modifiers, out bool ctrlOrCmd, out bool shift, out bool alt) + public static void GetMetaKeyState(Control target, KeyModifiers modifiers, out bool ctrlOrCmd, out bool shift, out bool alt) { - ctrlOrCmd = modifiers.HasFlag(GetPlatformCtrlOrCmdKeyModifier()); + ctrlOrCmd = modifiers.HasFlag(GetPlatformCtrlOrCmdKeyModifier(target)); shift = modifiers.HasFlag(KeyModifiers.Shift); alt = modifiers.HasFlag(KeyModifiers.Alt); } - public static KeyModifiers GetPlatformCtrlOrCmdKeyModifier() - { - var keymap = AvaloniaLocator.Current.GetService(); - return keymap?.CommandModifiers ?? KeyModifiers.Control; + public static KeyModifiers GetPlatformCtrlOrCmdKeyModifier(Control target) + { + var keymap = TopLevel.GetTopLevel(target)!.PlatformSettings!.HotkeyConfiguration; + return keymap.CommandModifiers; } } } diff --git a/src/Avalonia.Controls.ItemsRepeater/Controls/RepeaterLayoutContext.cs b/src/Avalonia.Controls.ItemsRepeater/Controls/RepeaterLayoutContext.cs index 49c8b9ff92..d03949c1c2 100644 --- a/src/Avalonia.Controls.ItemsRepeater/Controls/RepeaterLayoutContext.cs +++ b/src/Avalonia.Controls.ItemsRepeater/Controls/RepeaterLayoutContext.cs @@ -53,8 +53,8 @@ namespace Avalonia.Controls { return _owner.GetElementImpl( index, - options.HasAllFlags(ElementRealizationOptions.ForceCreate), - options.HasAllFlags(ElementRealizationOptions.SuppressAutoRecycle)); + options.HasFlag(ElementRealizationOptions.ForceCreate), + options.HasFlag(ElementRealizationOptions.SuppressAutoRecycle)); } protected override object GetItemAtCore(int index) => _owner.ItemsSourceView!.GetAt(index)!; diff --git a/src/Avalonia.Controls.ItemsRepeater/Controls/ViewManager.cs b/src/Avalonia.Controls.ItemsRepeater/Controls/ViewManager.cs index 6b9d7934bf..674389d77c 100644 --- a/src/Avalonia.Controls.ItemsRepeater/Controls/ViewManager.cs +++ b/src/Avalonia.Controls.ItemsRepeater/Controls/ViewManager.cs @@ -695,7 +695,7 @@ namespace Avalonia.Controls { Control? focusedElement = null; - if (FocusManager.Instance?.Current is Visual child) + if (TopLevel.GetTopLevel(_owner)?.FocusManager?.GetFocusedElement() is Visual child) { var parent = child.GetVisualParent(); var owner = _owner; diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index e907fd5988..30791551f5 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -8,6 +8,7 @@ using Avalonia.Data; using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Input.Raw; +using Avalonia.Media; using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.Styling; @@ -117,25 +118,13 @@ namespace Avalonia /// public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates()); - /// - /// Gets the application's focus manager. - /// - /// - /// The application's focus manager. - /// - public IFocusManager? FocusManager - { - get; - private set; - } - /// /// Gets the application's input manager. /// /// /// The application's input manager. /// - public InputManager? InputManager + internal InputManager? InputManager { get; private set; @@ -191,6 +180,17 @@ namespace Avalonia /// public IApplicationLifetime? ApplicationLifetime { get; set; } + /// + /// Represents a contract for accessing global platform-specific settings. + /// + /// + /// PlatformSettings can be null only if application wasn't initialized yet. + /// 's is an equivalent API + /// which should always be preferred over a global one, + /// as specific top levels might have different settings set-up. + /// + public IPlatformSettings? PlatformSettings => AvaloniaLocator.Current.GetService(); + event Action>? IGlobalStyles.GlobalStylesAdded { add => _stylesAdded += value; @@ -237,32 +237,32 @@ namespace Avalonia public virtual void RegisterServices() { AvaloniaSynchronizationContext.InstallIfNeeded(); - FocusManager = new FocusManager(); + var focusManager = new FocusManager(); InputManager = new InputManager(); - var settings = AvaloniaLocator.Current.GetRequiredService(); - settings.ColorValuesChanged += OnColorValuesChanged; - OnColorValuesChanged(settings, settings.GetColorValues()); - + if (PlatformSettings is { } settings) + { + settings.ColorValuesChanged += OnColorValuesChanged; + OnColorValuesChanged(settings, settings.GetColorValues()); + } + AvaloniaLocator.CurrentMutable .Bind().ToTransient() .Bind().ToConstant(this) .Bind().ToConstant(this) .Bind().ToConstant(this) - .Bind().ToConstant(FocusManager) + .Bind().ToConstant(focusManager) .Bind().ToConstant(InputManager) .Bind().ToTransient() .Bind().ToConstant(DragDropDevice.Instance); - + // TODO: Fix this, for now we keep this behavior since someone might be relying on it in 0.9.x if (AvaloniaLocator.Current.GetService() == null) AvaloniaLocator.CurrentMutable .Bind().ToTransient(); - var clock = new RenderLoopClock(); - AvaloniaLocator.CurrentMutable - .Bind().ToConstant(clock) - .GetService()?.Add(clock); + AvaloniaLocator.CurrentMutable.Bind() + .ToConstant(MediaContext.Instance.Clock); } public virtual void OnFrameworkInitializationCompleted() diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs index 20711eecbc..d0b894101f 100644 --- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs +++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs @@ -762,7 +762,7 @@ namespace Avalonia.Controls /// otherwise, false. protected bool HasFocus() { - Visual? focused = FocusManager.Instance?.Current as Visual; + Visual? focused = FocusManager.GetFocusManager(this)?.GetFocusedElement() as Visual; while (focused != null) { diff --git a/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs b/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs index d04dfec3e8..756951667b 100644 --- a/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs +++ b/src/Avalonia.Controls/Automation/Peers/ControlAutomationPeer.cs @@ -31,11 +31,31 @@ namespace Avalonia.Automation.Peers return CreatePeerForElement(element); } + /// + /// Gets the for a , creating it if + /// necessary. + /// + /// The control. + /// The automation peer. + /// + /// Despite the name (which comes from the analogous WPF API), this method does not create + /// a new peer if one already exists: instead it returns the existing peer. + /// public static AutomationPeer CreatePeerForElement(Control element) { return element.GetOrCreateAutomationPeer(); } + /// + /// Gets an existing for a . + /// + /// The control. + /// The automation peer if already created; otherwise null. + /// + /// To ensure that a peer is created, use . + /// + public static AutomationPeer? FromElement(Control element) => element.GetAutomationPeer(); + protected override void BringIntoViewCore() => Owner.BringIntoView(); protected override IReadOnlyList GetOrCreateChildrenCore() @@ -151,7 +171,7 @@ namespace Avalonia.Automation.Peers protected override bool HasKeyboardFocusCore() => Owner.IsFocused; protected override bool IsContentElementCore() => true; protected override bool IsControlElementCore() => true; - protected override bool IsEnabledCore() => Owner.IsEnabled; + protected override bool IsEnabledCore() => Owner.IsEffectivelyEnabled; protected override bool IsKeyboardFocusableCore() => Owner.Focusable; protected override void SetFocusCore() => Owner.Focus(); diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index 48761ca8b8..304454777f 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -13,7 +13,10 @@ + + + @@ -22,5 +25,6 @@ + diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs index 78ba23c1dd..e7373a813e 100644 --- a/src/Avalonia.Controls/Border.cs +++ b/src/Avalonia.Controls/Border.cs @@ -47,30 +47,6 @@ namespace Avalonia.Controls public static readonly StyledProperty BoxShadowProperty = AvaloniaProperty.Register(nameof(BoxShadow)); - /// - /// Defines the property. - /// - public static readonly StyledProperty BorderDashOffsetProperty = - AvaloniaProperty.Register(nameof(BorderDashOffset)); - - /// - /// Defines the property. - /// - public static readonly StyledProperty?> BorderDashArrayProperty = - AvaloniaProperty.Register?>(nameof(BorderDashArray)); - - /// - /// Defines the property. - /// - public static readonly StyledProperty BorderLineCapProperty = - AvaloniaProperty.Register(nameof(BorderLineCap), PenLineCap.Flat); - - /// - /// Defines the property. - /// - public static readonly StyledProperty BorderLineJoinProperty = - AvaloniaProperty.Register(nameof(BorderLineJoin), PenLineJoin.Miter); - private readonly BorderRenderHelper _borderRenderHelper = new BorderRenderHelper(); private Thickness? _layoutThickness; private double _scale; @@ -86,10 +62,6 @@ namespace Avalonia.Controls BorderBrushProperty, BorderThicknessProperty, CornerRadiusProperty, - BorderDashArrayProperty, - BorderLineCapProperty, - BorderLineJoinProperty, - BorderDashOffsetProperty, BoxShadowProperty); AffectsMeasure(BorderThicknessProperty); } @@ -115,8 +87,8 @@ namespace Avalonia.Controls /// public IBrush? Background { - get { return GetValue(BackgroundProperty); } - set { SetValue(BackgroundProperty, value); } + get => GetValue(BackgroundProperty); + set => SetValue(BackgroundProperty, value); } /// @@ -124,17 +96,8 @@ namespace Avalonia.Controls /// public IBrush? BorderBrush { - get { return GetValue(BorderBrushProperty); } - set { SetValue(BorderBrushProperty, value); } - } - - /// - /// Gets or sets a collection of values that indicate the pattern of dashes and gaps that is used to outline shapes. - /// - public AvaloniaList? BorderDashArray - { - get { return GetValue(BorderDashArrayProperty); } - set { SetValue(BorderDashArrayProperty, value); } + get => GetValue(BorderBrushProperty); + set => SetValue(BorderBrushProperty, value); } /// @@ -142,35 +105,8 @@ namespace Avalonia.Controls /// public Thickness BorderThickness { - get { return GetValue(BorderThicknessProperty); } - set { SetValue(BorderThicknessProperty, value); } - } - - /// - /// Gets or sets a value that specifies the distance within the dash pattern where a dash begins. - /// - public double BorderDashOffset - { - get { return GetValue(BorderDashOffsetProperty); } - set { SetValue(BorderDashOffsetProperty, value); } - } - - /// - /// Gets or sets a enumeration value that describes the shape at the ends of a line. - /// - public PenLineCap BorderLineCap - { - get { return GetValue(BorderLineCapProperty); } - set { SetValue(BorderLineCapProperty, value); } - } - - /// - /// Gets or sets a enumeration value that specifies the type of join that is used at the vertices of a Shape. - /// - public PenLineJoin BorderLineJoin - { - get { return GetValue(BorderLineJoinProperty); } - set { SetValue(BorderLineJoinProperty, value); } + get => GetValue(BorderThicknessProperty); + set => SetValue(BorderThicknessProperty, value); } /// @@ -178,8 +114,8 @@ namespace Avalonia.Controls /// public CornerRadius CornerRadius { - get { return GetValue(CornerRadiusProperty); } - set { SetValue(CornerRadiusProperty, value); } + get => GetValue(CornerRadiusProperty); + set => SetValue(CornerRadiusProperty, value); } /// @@ -227,8 +163,14 @@ namespace Avalonia.Controls /// The drawing context. public sealed override void Render(DrawingContext context) { - _borderRenderHelper.Render(context, Bounds.Size, LayoutThickness, CornerRadius, Background, BorderBrush, - BoxShadow, BorderDashOffset, BorderLineCap, BorderLineJoin, BorderDashArray); + _borderRenderHelper.Render( + context, + Bounds.Size, + LayoutThickness, + CornerRadius, + Background, + BorderBrush, + BoxShadow); } /// diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index f48d7a7cc1..d8c31fc477 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -34,8 +34,8 @@ namespace Avalonia.Controls [PseudoClasses(pcFlyoutOpen, pcPressed)] public class Button : ContentControl, ICommandSource, IClickableControl { - protected const string pcPressed = ":pressed"; - protected const string pcFlyoutOpen = ":flyout-open"; + private const string pcPressed = ":pressed"; + private const string pcFlyoutOpen = ":flyout-open"; /// /// Defines the property. diff --git a/src/Avalonia.Controls/Calendar/Calendar.cs b/src/Avalonia.Controls/Calendar/Calendar.cs index 10aadfa759..6468d0b4e8 100644 --- a/src/Avalonia.Controls/Calendar/Calendar.cs +++ b/src/Avalonia.Controls/Calendar/Calendar.cs @@ -1567,7 +1567,7 @@ namespace Avalonia.Controls base.OnPointerReleased(e); if (!HasFocusInternal && e.InitialPressMouseButton == MouseButton.Left) { - FocusManager.Instance?.Focus(this); + Focus(); } } diff --git a/src/Avalonia.Controls/Calendar/CalendarButton.cs b/src/Avalonia.Controls/Calendar/CalendarButton.cs index d8672cbf18..b35298b101 100644 --- a/src/Avalonia.Controls/Calendar/CalendarButton.cs +++ b/src/Avalonia.Controls/Calendar/CalendarButton.cs @@ -39,7 +39,7 @@ namespace Avalonia.Controls.Primitives public CalendarButton() : base() { - Content = DateTimeHelper.GetCurrentDateFormat().AbbreviatedMonthNames[0]; + SetCurrentValue(ContentProperty, DateTimeHelper.GetCurrentDateFormat().AbbreviatedMonthNames[0]); } /// diff --git a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs index 3d0befdba7..ea3ca8e8fc 100644 --- a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs +++ b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs @@ -34,7 +34,7 @@ namespace Avalonia.Controls.Primitives : base() { //Focusable = false; - Content = DefaultContent.ToString(CultureInfo.CurrentCulture); + SetCurrentValue(ContentProperty, DefaultContent.ToString(CultureInfo.CurrentCulture)); } /// diff --git a/src/Avalonia.Controls/Calendar/CalendarItem.cs b/src/Avalonia.Controls/Calendar/CalendarItem.cs index 2e3f1f96ce..e81ed8072e 100644 --- a/src/Avalonia.Controls/Calendar/CalendarItem.cs +++ b/src/Avalonia.Controls/Calendar/CalendarItem.cs @@ -171,7 +171,7 @@ namespace Avalonia.Controls.Primitives var childCount = Calendar.RowsPerMonth + Calendar.RowsPerMonth * Calendar.ColumnsPerMonth; using var children = new PooledList(childCount); - for (int i = 0; i < Calendar.RowsPerMonth; i++) + for (int i = 0; i < Calendar.ColumnsPerMonth; i++) { if (DayTitleTemplate?.Build() is Control cell) { diff --git a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs index 90153d3293..679ac4a853 100644 --- a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs +++ b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs @@ -26,8 +26,8 @@ namespace Avalonia.Controls [PseudoClasses(pcFlyoutOpen, pcPressed)] public partial class CalendarDatePicker : TemplatedControl { - protected const string pcPressed = ":pressed"; - protected const string pcFlyoutOpen = ":flyout-open"; + private const string pcPressed = ":pressed"; + private const string pcFlyoutOpen = ":flyout-open"; private const string ElementTextBox = "PART_TextBox"; private const string ElementButton = "PART_Button"; diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index f41c00662d..bce1a3685f 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -21,8 +21,9 @@ namespace Avalonia.Controls [PseudoClasses(pcDropdownOpen, pcPressed)] public class ComboBox : SelectingItemsControl { - public const string pcDropdownOpen = ":dropdownopen"; - public const string pcPressed = ":pressed"; + internal const string pcDropdownOpen = ":dropdownopen"; + internal const string pcPressed = ":pressed"; + /// /// The default value for the property. /// @@ -164,7 +165,7 @@ namespace Avalonia.Controls UpdateSelectionBoxItem(SelectedItem); } - public override void InvalidateMirrorTransform() + protected internal override void InvalidateMirrorTransform() { base.InvalidateMirrorTransform(); UpdateFlowDirection(); @@ -230,8 +231,7 @@ namespace Avalonia.Controls var firstChild = Presenter?.Panel?.Children.FirstOrDefault(c => CanFocus(c)); if (firstChild != null) { - FocusManager.Instance?.Focus(firstChild, NavigationMethod.Directional); - e.Handled = true; + e.Handled = firstChild.Focus(NavigationMethod.Directional); } } } @@ -361,19 +361,6 @@ namespace Avalonia.Controls _subscriptionsOnOpen.Clear(); - var toplevel = TopLevel.GetTopLevel(this); - if (toplevel != null) - { - toplevel.AddDisposableHandler(PointerWheelChangedEvent, (s, ev) => - { - //eat wheel scroll event outside dropdown popup while it's open - if (IsDropDownOpen && (ev.Source as Visual)?.GetVisualRoot() == toplevel) - { - ev.Handled = true; - } - }, Interactivity.RoutingStrategies.Tunnel).DisposeWith(_subscriptionsOnOpen); - } - this.GetObservable(IsVisibleProperty).Subscribe(IsVisibleChanged).DisposeWith(_subscriptionsOnOpen); foreach (var parent in this.GetVisualAncestors().OfType()) diff --git a/src/Avalonia.Controls/ContentControl.cs b/src/Avalonia.Controls/ContentControl.cs index f30920ed2e..867dca2be1 100644 --- a/src/Avalonia.Controls/ContentControl.cs +++ b/src/Avalonia.Controls/ContentControl.cs @@ -13,7 +13,7 @@ namespace Avalonia.Controls /// /// Displays according to an . /// - [TemplatePart("PART_ContentPresenter", typeof(IContentPresenter))] + [TemplatePart("PART_ContentPresenter", typeof(ContentPresenter))] public class ContentControl : TemplatedControl, IContentControl, IContentPresenterHost { /// @@ -68,7 +68,7 @@ namespace Avalonia.Controls /// /// Gets the presenter from the control's template. /// - public IContentPresenter? Presenter + public ContentPresenter? Presenter { get; private set; @@ -96,16 +96,16 @@ namespace Avalonia.Controls IAvaloniaList IContentPresenterHost.LogicalChildren => LogicalChildren; /// - bool IContentPresenterHost.RegisterContentPresenter(IContentPresenter presenter) + bool IContentPresenterHost.RegisterContentPresenter(ContentPresenter presenter) { return RegisterContentPresenter(presenter); } /// - /// Called when an is registered with the control. + /// Called when an is registered with the control. /// /// The presenter. - protected virtual bool RegisterContentPresenter(IContentPresenter presenter) + protected virtual bool RegisterContentPresenter(ContentPresenter presenter) { if (presenter.Name == "PART_ContentPresenter") { @@ -116,19 +116,14 @@ namespace Avalonia.Controls return false; } - protected virtual void ContentChanged(AvaloniaPropertyChangedEventArgs e) + private void ContentChanged(AvaloniaPropertyChangedEventArgs e) { - UpdateLogicalTree(e.OldValue, e.NewValue); - } - - protected void UpdateLogicalTree(object? toRemove, object? toAdd) - { - if (toRemove is ILogical oldChild) + if (e.OldValue is ILogical oldChild) { LogicalChildren.Remove(oldChild); } - if (toAdd is ILogical newChild) + if (e.NewValue is ILogical newChild) { LogicalChildren.Add(newChild); } diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs index 97a8c6fe97..e3a419d7b3 100644 --- a/src/Avalonia.Controls/ContextMenu.cs +++ b/src/Avalonia.Controls/ContextMenu.cs @@ -196,14 +196,14 @@ namespace Avalonia.Controls /// /// property is changing from false to true. /// - public event CancelEventHandler? ContextMenuOpening; + public event CancelEventHandler? Opening; /// /// Occurs when the value of the /// /// property is changing from true to false. /// - public event CancelEventHandler? ContextMenuClosing; + public event CancelEventHandler? Closing; /// /// Called when the property changes on a control. @@ -285,7 +285,7 @@ namespace Avalonia.Controls } } - void ISetterValue.Initialize(ISetter setter) + void ISetterValue.Initialize(SetterBase setter) { // ContextMenu can be assigned to the ContextMenu property in a setter. This overrides // the behavior defined in Control which requires controls to be wrapped in a