diff --git a/azure-pipelines.yml b/azure-pipelines.yml index bc8d065137..9fa79ec5ba 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,3 +1,6 @@ +variables: + MSBuildEnableWorkloadResolver: 'false' + jobs: - job: Linux pool: @@ -9,9 +12,9 @@ jobs: version: 3.1.414 - task: UseDotNet@2 - displayName: 'Use .NET Core SDK 5.0.402' + displayName: 'Use .NET Core SDK 6.0.100' inputs: - version: 5.0.402 + version: 6.0.100 - task: CmdLine@2 displayName: 'Run Build' @@ -40,9 +43,9 @@ jobs: version: 3.1.414 - task: UseDotNet@2 - displayName: 'Use .NET Core SDK 5.0.402' + displayName: 'Use .NET Core SDK 6.0.100' inputs: - version: 5.0.402 + version: 6.0.100 - task: CmdLine@2 displayName: 'Install Mono 5.18' @@ -56,7 +59,7 @@ jobs: inputs: script: | export PATH="`pwd`/sdk:$PATH" - cd src/tools/MicroComGenerator; dotnet run -i ../../Avalonia.Native/avn.idl --cpp ../../../native/Avalonia.Native/inc/avalonia-native.h + cd src/tools/MicroComGenerator; dotnet run -f net6.0 -i ../../Avalonia.Native/avn.idl --cpp ../../../native/Avalonia.Native/inc/avalonia-native.h - task: Xcode@5 inputs: @@ -110,9 +113,9 @@ jobs: version: 3.1.414 - task: UseDotNet@2 - displayName: 'Use .NET Core SDK 5.0.402' + displayName: 'Use .NET Core SDK 6.0.100' inputs: - version: 5.0.402 + version: 6.0.100 - task: CmdLine@2 displayName: 'Install Nuke' diff --git a/build/HarfBuzzSharp.props b/build/HarfBuzzSharp.props index 13419eb173..16aab3911e 100644 --- a/build/HarfBuzzSharp.props +++ b/build/HarfBuzzSharp.props @@ -1,6 +1,6 @@  - - + + diff --git a/build/MicroCom.targets b/build/MicroCom.targets index 49d2cdce72..1ed388f689 100644 --- a/build/MicroCom.targets +++ b/build/MicroCom.targets @@ -15,7 +15,7 @@ Inputs="@(AvnComIdl);$(MSBuildThisFileDirectory)../src/tools/MicroComGenerator/**/*.cs" Outputs="%(AvnComIdl.OutputFile)"> - diff --git a/build/SharedVersion.props b/build/SharedVersion.props index 75bada4bfc..7d75901288 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -17,7 +17,6 @@ git $(MSBuildThisFileDirectory)\avalonia.snk true - $(DefineConstants);SIGNED_BUILD diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props index f2e7df36cd..97b29a192d 100644 --- a/build/SkiaSharp.props +++ b/build/SkiaSharp.props @@ -1,6 +1,6 @@  - - + + diff --git a/build/SourceLink.props b/build/SourceLink.props index 1e007e01eb..0f77c2a613 100644 --- a/build/SourceLink.props +++ b/build/SourceLink.props @@ -3,7 +3,7 @@ true false true - embedded + full $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb diff --git a/global.json b/global.json index 9f83c1ea1e..e3e652761c 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { - "sdk": { - "version": "5.0.402" - }, + "sdk": { + "version": "6.0.100" + }, "msbuild-sdks": { "Microsoft.Build.Traversal": "1.0.43", "MSBuild.Sdk.Extras": "2.0.54", diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 094c1f7c93..2073e130cb 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -2398,11 +2398,18 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent { case NSEventTypeLeftMouseDown: { - auto avnPoint = [AvnView toAvnPoint:[event locationInWindow]]; - auto point = [self translateLocalPoint:avnPoint]; - AvnVector delta; + AvnView* view = _parent->View; + NSPoint windowPoint = [event locationInWindow]; + NSPoint viewPoint = [view convertPoint:windowPoint fromView:nil]; - _parent->BaseEvents->RawMouseEvent(NonClientLeftButtonDown, [event timestamp] * 1000, AvnInputModifiersNone, point, delta); + if (!NSPointInRect(viewPoint, view.bounds)) + { + auto avnPoint = [AvnView toAvnPoint:windowPoint]; + auto point = [self translateLocalPoint:avnPoint]; + AvnVector delta; + + _parent->BaseEvents->RawMouseEvent(NonClientLeftButtonDown, [event timestamp] * 1000, AvnInputModifiersNone, point, delta); + } } break; diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj index e08ffd0413..b28d3eb700 100644 --- a/nukebuild/_build.csproj +++ b/nukebuild/_build.csproj @@ -15,6 +15,7 @@ + @@ -36,10 +37,10 @@ - - - - + + MicroComGenerator\%(Filename)%(Extension) + + diff --git a/readme.md b/readme.md index ef8c116728..a1cdb6fe9d 100644 --- a/readme.md +++ b/readme.md @@ -93,7 +93,8 @@ Support this project by becoming a sponsor. Your logo will show up here with a l - + + ## .NET Foundation diff --git a/samples/BindingDemo/BindingDemo.csproj b/samples/BindingDemo/BindingDemo.csproj index d898b737a9..2c6ff74e5e 100644 --- a/samples/BindingDemo/BindingDemo.csproj +++ b/samples/BindingDemo/BindingDemo.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1 + net6.0 diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj index 3c2d2ee359..2d4fc45171 100644 --- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj +++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj @@ -2,7 +2,7 @@ WinExe - netcoreapp3.1 + net6.0 true diff --git a/samples/PlatformSanityChecks/PlatformSanityChecks.csproj b/samples/PlatformSanityChecks/PlatformSanityChecks.csproj index 86d762a5bc..9660d2a90d 100644 --- a/samples/PlatformSanityChecks/PlatformSanityChecks.csproj +++ b/samples/PlatformSanityChecks/PlatformSanityChecks.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net6.0 diff --git a/samples/Previewer/Previewer.csproj b/samples/Previewer/Previewer.csproj index cfedb7ad9e..c1d14cba26 100644 --- a/samples/Previewer/Previewer.csproj +++ b/samples/Previewer/Previewer.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1 + net6.0 diff --git a/samples/RemoteDemo/RemoteDemo.csproj b/samples/RemoteDemo/RemoteDemo.csproj index 530cad805f..607222c2e2 100644 --- a/samples/RemoteDemo/RemoteDemo.csproj +++ b/samples/RemoteDemo/RemoteDemo.csproj @@ -1,7 +1,7 @@ Exe - netcoreapp3.1 + net6.0 diff --git a/samples/RenderDemo/RenderDemo.csproj b/samples/RenderDemo/RenderDemo.csproj index 0d33b4c111..eed6fa9e89 100644 --- a/samples/RenderDemo/RenderDemo.csproj +++ b/samples/RenderDemo/RenderDemo.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1 + net6.0 diff --git a/samples/Sandbox/Sandbox.csproj b/samples/Sandbox/Sandbox.csproj index 0c19440a1e..8f2812e048 100644 --- a/samples/Sandbox/Sandbox.csproj +++ b/samples/Sandbox/Sandbox.csproj @@ -2,7 +2,7 @@ WinExe - netcoreapp3.1 + net6.0 true diff --git a/samples/VirtualizationDemo/VirtualizationDemo.csproj b/samples/VirtualizationDemo/VirtualizationDemo.csproj index d898b737a9..2c6ff74e5e 100644 --- a/samples/VirtualizationDemo/VirtualizationDemo.csproj +++ b/samples/VirtualizationDemo/VirtualizationDemo.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1 + net6.0 diff --git a/src/Avalonia.Animation/Animators/Animator`1.cs b/src/Avalonia.Animation/Animators/Animator`1.cs index d784227620..23afa76bf6 100644 --- a/src/Avalonia.Animation/Animators/Animator`1.cs +++ b/src/Avalonia.Animation/Animators/Animator`1.cs @@ -79,15 +79,15 @@ namespace Avalonia.Animation.Animators T oldValue, newValue; - if (firstKeyframe.isNeutral) - oldValue = neutralValue; + if (!firstKeyframe.isNeutral && firstKeyframe.Value is T firstKeyframeValue) + oldValue = firstKeyframeValue; else - oldValue = (T)firstKeyframe.Value; + oldValue = neutralValue; - if (lastKeyframe.isNeutral) - newValue = neutralValue; + if (!lastKeyframe.isNeutral && lastKeyframe.Value is T lastKeyframeValue) + newValue = lastKeyframeValue; else - newValue = (T)lastKeyframe.Value; + newValue = neutralValue; if (lastKeyframe.KeySpline != null) progress = lastKeyframe.KeySpline.GetSplineProgress(progress); diff --git a/src/Avalonia.Animation/Properties/AssemblyInfo.cs b/src/Avalonia.Animation/Properties/AssemblyInfo.cs index 221b51e95a..6b539b075b 100644 --- a/src/Avalonia.Animation/Properties/AssemblyInfo.cs +++ b/src/Avalonia.Animation/Properties/AssemblyInfo.cs @@ -1,15 +1,9 @@ using Avalonia.Metadata; -using System.Reflection; using System.Runtime.CompilerServices; [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation.Easings")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation.Animators")] -#if SIGNED_BUILD [assembly: InternalsVisibleTo("Avalonia.LeakTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] [assembly: InternalsVisibleTo("Avalonia.Animation.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] -#else -[assembly: InternalsVisibleTo("Avalonia.LeakTests")] -[assembly: InternalsVisibleTo("Avalonia.Animation.UnitTests")] -#endif diff --git a/src/Avalonia.Base/Properties/AssemblyInfo.cs b/src/Avalonia.Base/Properties/AssemblyInfo.cs index b054c186ae..053c7a7547 100644 --- a/src/Avalonia.Base/Properties/AssemblyInfo.cs +++ b/src/Avalonia.Base/Properties/AssemblyInfo.cs @@ -5,18 +5,10 @@ using System.Runtime.CompilerServices; using Avalonia.Metadata; [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Data.Converters")] -#if SIGNED_BUILD [assembly: InternalsVisibleTo("Avalonia.Base.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] [assembly: InternalsVisibleTo("Avalonia.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] [assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] [assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] [assembly: InternalsVisibleTo("Avalonia.Visuals, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] -#else -[assembly: InternalsVisibleTo("Avalonia.Base.UnitTests")] -[assembly: InternalsVisibleTo("Avalonia.UnitTests")] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] -[assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid")] -[assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests")] -[assembly: InternalsVisibleTo("Avalonia.Visuals")] -#endif + diff --git a/src/Avalonia.Controls.DataGrid/Properties/AssemblyInfo.cs b/src/Avalonia.Controls.DataGrid/Properties/AssemblyInfo.cs index 1b122996d2..d61c05ab6e 100644 --- a/src/Avalonia.Controls.DataGrid/Properties/AssemblyInfo.cs +++ b/src/Avalonia.Controls.DataGrid/Properties/AssemblyInfo.cs @@ -1,13 +1,9 @@ -using System.Reflection; using System.Runtime.CompilerServices; using Avalonia.Metadata; -#if SIGNED_BUILD + [assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] [assembly: InternalsVisibleTo("Avalonia.DesignerSupport, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] -#else -[assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid.UnitTests")] -[assembly: InternalsVisibleTo("Avalonia.DesignerSupport")] -#endif + [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Collections")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Primitives")] diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs index 7b06d3c868..0bead04982 100644 --- a/src/Avalonia.Controls/MenuItem.cs +++ b/src/Avalonia.Controls/MenuItem.cs @@ -387,7 +387,7 @@ namespace Avalonia.Controls parent = parent.Parent; } - _isEmbeddedInMenu = parent is IMenu; + _isEmbeddedInMenu = parent.FindLogicalAncestorOfType(true) != null; } protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs index e361e7b736..5f82e28722 100644 --- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs +++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs @@ -1,4 +1,5 @@ using System; +using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.Interactivity; @@ -376,7 +377,10 @@ namespace Avalonia.Controls.Platform { if (item.IsSubMenuOpen) { - if (item.IsTopLevel) + // PointerPressed events may bubble from disabled items in sub-menus. In this case, + // keep the sub-menu open. + var popup = (e.Source as ILogical)?.FindLogicalAncestorOfType(); + if (item.IsTopLevel && popup == null) { CloseMenu(item); } diff --git a/src/Avalonia.Controls/Platform/PlatformManager.cs b/src/Avalonia.Controls/Platform/PlatformManager.cs index e39f0b1e99..acd45ad29a 100644 --- a/src/Avalonia.Controls/Platform/PlatformManager.cs +++ b/src/Avalonia.Controls/Platform/PlatformManager.cs @@ -29,7 +29,7 @@ namespace Avalonia.Controls.Platform if (platform == null) { - throw new Exception("Could not CreateWindow(): IWindowingPlatform is not registered."); + throw new Exception("Could not CreateTrayIcon(): IWindowingPlatform is not registered."); } return s_designerMode ? null : platform.CreateTrayIcon(); @@ -45,7 +45,7 @@ namespace Avalonia.Controls.Platform throw new Exception("Could not CreateWindow(): IWindowingPlatform is not registered."); } - return s_designerMode ? (IWindowImpl)platform.CreateEmbeddableWindow() : platform.CreateWindow(); + return s_designerMode ? platform.CreateEmbeddableWindow() : platform.CreateWindow(); } public static IWindowImpl CreateEmbeddableWindow() diff --git a/src/Avalonia.Controls/Properties/AssemblyInfo.cs b/src/Avalonia.Controls/Properties/AssemblyInfo.cs index 5c9017f127..d1743611cd 100644 --- a/src/Avalonia.Controls/Properties/AssemblyInfo.cs +++ b/src/Avalonia.Controls/Properties/AssemblyInfo.cs @@ -1,13 +1,9 @@ -using System.Reflection; using System.Runtime.CompilerServices; using Avalonia.Metadata; -#if SIGNED_BUILD + [assembly: InternalsVisibleTo("Avalonia.Controls.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] [assembly: InternalsVisibleTo("Avalonia.DesignerSupport, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] -#else -[assembly: InternalsVisibleTo("Avalonia.Controls.UnitTests")] -[assembly: InternalsVisibleTo("Avalonia.DesignerSupport")] -#endif + [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Embedding")] diff --git a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs index 804bb09510..6b1934ed06 100644 --- a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs +++ b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs @@ -25,7 +25,6 @@ namespace Avalonia.DesignerSupport.Remote.HtmlTransport private AutoResetEvent _wakeup = new AutoResetEvent(false); private FrameMessage _lastFrameMessage = null; private FrameMessage _lastSentFrameMessage = null; - private RequestViewportResizeMessage _lastViewportRequest; private Action _onMessage; private Action _onException; @@ -177,6 +176,7 @@ namespace Avalonia.DesignerSupport.Remote.HtmlTransport public void Dispose() { + _disposed = true; _pendingSocket?.Dispose(); _simpleServer.Dispose(); } diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/AvaloniaPropertyViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/AvaloniaPropertyViewModel.cs index e4c4ca6115..8ce99d5375 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/AvaloniaPropertyViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/AvaloniaPropertyViewModel.cs @@ -19,7 +19,7 @@ namespace Avalonia.Diagnostics.ViewModels Name = property.IsAttached ? $"[{property.OwnerType.Name}.{property.Name}]" : property.Name; - + DeclaringType = property.OwnerType; Update(); } @@ -50,6 +50,8 @@ namespace Avalonia.Diagnostics.ViewModels public override string Group => _group; + public override System.Type? DeclaringType { get; } + // [MemberNotNull(nameof(_type), nameof(_group), nameof(_priority))] public override void Update() { diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ClrPropertyViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ClrPropertyViewModel.cs index 65626aeea5..0a851f4a19 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ClrPropertyViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ClrPropertyViewModel.cs @@ -24,7 +24,7 @@ namespace Avalonia.Diagnostics.ViewModels { Name = property.DeclaringType.Name + '.' + property.Name; } - + DeclaringType = property.DeclaringType; Update(); } @@ -55,6 +55,8 @@ namespace Avalonia.Diagnostics.ViewModels public override bool? IsAttached => default; + public override System.Type? DeclaringType { get; } + // [MemberNotNull(nameof(_type))] public override void Update() { diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs index 3790951b0c..9905aa4afc 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs @@ -17,42 +17,26 @@ namespace Avalonia.Diagnostics.ViewModels internal class ControlDetailsViewModel : ViewModelBase, IDisposable { private readonly IVisual _control; - private readonly IDictionary> _propertyIndex; + private IDictionary>? _propertyIndex; private PropertyViewModel? _selectedProperty; + private DataGridCollectionView? _propertiesView; private bool _snapshotStyles; private bool _showInactiveStyles; private string? _styleStatus; + private object? _selectedEntity; + private readonly Stack<(string Name,object Entry)> _selectedEntitiesStack = new(); + private string? _selectedEntityName; + private string? _selectedEntityType; public ControlDetailsViewModel(TreePageViewModel treePage, IVisual control) { _control = control; TreePage = treePage; - - var properties = GetAvaloniaProperties(control) - .Concat(GetClrProperties(control)) - .OrderBy(x => x, PropertyComparer.Instance) - .ThenBy(x => x.Name) - .ToList(); - - _propertyIndex = properties.GroupBy(x => x.Key).ToDictionary(x => x.Key, x => x.ToList()); - - var view = new DataGridCollectionView(properties); - view.GroupDescriptions.Add(new DataGridPathGroupDescription(nameof(AvaloniaPropertyViewModel.Group))); - view.Filter = FilterProperty; - PropertiesView = view; - + Layout = new ControlLayoutViewModel(control); - if (control is INotifyPropertyChanged inpc) - { - inpc.PropertyChanged += ControlPropertyChanged; - } - - if (control is AvaloniaObject ao) - { - ao.PropertyChanged += ControlPropertyChanged; - } + NavigateToProperty(control, (control as IControl)?.Name ?? control.ToString()); AppliedStyles = new ObservableCollection(); PseudoClasses = new ObservableCollection(); @@ -133,12 +117,46 @@ namespace Avalonia.Diagnostics.ViewModels public TreePageViewModel TreePage { get; } - public DataGridCollectionView PropertiesView { get; } + public DataGridCollectionView? PropertiesView + { + get => _propertiesView; + private set => RaiseAndSetIfChanged(ref _propertiesView, value); + } public ObservableCollection AppliedStyles { get; } public ObservableCollection PseudoClasses { get; } + public object? SelectedEntity + { + get => _selectedEntity; + set + { + RaiseAndSetIfChanged(ref _selectedEntity, value); + + } + } + + public string? SelectedEntityName + { + get => _selectedEntityName; + set + { + RaiseAndSetIfChanged(ref _selectedEntityName, value); + + } + } + + public string? SelectedEntityType + { + get => _selectedEntityType; + set + { + RaiseAndSetIfChanged(ref _selectedEntityType, value); + + } + } + public PropertyViewModel? SelectedProperty { get => _selectedProperty; @@ -252,7 +270,7 @@ namespace Avalonia.Diagnostics.ViewModels private void ControlPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) { - if (_propertyIndex.TryGetValue(e.Property, out var properties)) + if (_propertyIndex is { } && _propertyIndex.TryGetValue(e.Property, out var properties)) { foreach (var property in properties) { @@ -266,6 +284,7 @@ namespace Avalonia.Diagnostics.ViewModels private void ControlPropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName != null + && _propertyIndex is { } && _propertyIndex.TryGetValue(e.PropertyName, out var properties)) { foreach (var property in properties) @@ -378,5 +397,78 @@ namespace Avalonia.Diagnostics.ViewModels } } } + + public void ApplySelectedProperty() + { + var selectedProperty = SelectedProperty; + var selectedEntity = SelectedEntity; + var selectedEntityName = SelectedEntityName; + if (selectedEntity == null || selectedProperty == null) + return; + + object? property; + if (selectedProperty.Key is AvaloniaProperty avaloniaProperty) + { + property = (_selectedEntity as IControl)?.GetValue(avaloniaProperty); + } + else + { + property = selectedEntity.GetType().GetProperties() + .FirstOrDefault(pi => pi.Name == selectedProperty.Name + && pi.DeclaringType == selectedProperty.DeclaringType + && pi.PropertyType.Name == selectedProperty.Type) + ?.GetValue(selectedEntity); + } + if (property == null) return; + _selectedEntitiesStack.Push((Name:selectedEntityName!,Entry:selectedEntity)); + NavigateToProperty(property, selectedProperty.Name); + } + + public void ApplyParentProperty() + { + if (_selectedEntitiesStack.Any()) + { + var property = _selectedEntitiesStack.Pop(); + NavigateToProperty(property.Entry, property.Name); + } + } + + protected void NavigateToProperty(object o, string entityName) + { + var oldSelectedEntity = SelectedEntity; + if (oldSelectedEntity is IAvaloniaObject ao1) + { + ao1.PropertyChanged -= ControlPropertyChanged; + } + else if (oldSelectedEntity is INotifyPropertyChanged inpc1) + { + inpc1.PropertyChanged -= ControlPropertyChanged; + } + + SelectedEntity = o; + SelectedEntityName = entityName; + SelectedEntityType = o.ToString(); + var properties = GetAvaloniaProperties(o) + .Concat(GetClrProperties(o)) + .OrderBy(x => x, PropertyComparer.Instance) + .ThenBy(x => x.Name) + .ToList(); + + _propertyIndex = properties.GroupBy(x => x.Key).ToDictionary(x => x.Key, x => x.ToList()); + + var view = new DataGridCollectionView(properties); + view.GroupDescriptions.Add(new DataGridPathGroupDescription(nameof(AvaloniaPropertyViewModel.Group))); + view.Filter = FilterProperty; + PropertiesView = view; + + if (o is IAvaloniaObject ao2) + { + ao2.PropertyChanged += ControlPropertyChanged; + } + else if (o is INotifyPropertyChanged inpc2) + { + inpc2.PropertyChanged += ControlPropertyChanged; + } + } } } diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/EventTreeNode.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/EventTreeNode.cs index a79816390d..e8de22710a 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/EventTreeNode.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/EventTreeNode.cs @@ -117,6 +117,11 @@ namespace Avalonia.Diagnostics.ViewModels _currentEvent.HandledBy = link; } } + + if (!Dispatcher.UIThread.CheckAccess()) + Dispatcher.UIThread.Post(handler); + else + handler(); } private static bool BelongsToDevTool(IVisual v) diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/FiredEvent.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/FiredEvent.cs index 8069300922..a9f3182bef 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/FiredEvent.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/FiredEvent.cs @@ -64,7 +64,7 @@ namespace Avalonia.Diagnostics.ViewModels if (EventChain.Count > 0) { var prevLink = EventChain[EventChain.Count - 1]; - + if (prevLink.Route != link.Route) { link.BeginsNewRoute = true; diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs index fdbd8c1aa3..173dcd165a 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/PropertyViewModel.cs @@ -15,6 +15,7 @@ namespace Avalonia.Diagnostics.ViewModels public abstract string Name { get; } public abstract string Group { get; } public abstract string Type { get; } + public abstract Type? DeclaringType { get; } public abstract string Value { get; set; } public abstract string Priority { get; } public abstract bool? IsAttached { get; } diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs index 4b18cf414a..27b28f35fc 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs @@ -15,7 +15,7 @@ namespace Avalonia.Diagnostics.ViewModels Nodes = nodes; PropertiesFilter = new FilterViewModel(); - PropertiesFilter.RefreshFilter += (s, e) => Details?.PropertiesView.Refresh(); + PropertiesFilter.RefreshFilter += (s, e) => Details?.PropertiesView?.Refresh(); SettersFilter = new FilterViewModel(); SettersFilter.RefreshFilter += (s, e) => Details?.UpdateStyleFilters(); diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml b/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml index 4b37438993..0d81127c21 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml +++ b/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml @@ -13,23 +13,30 @@ - + - +