diff --git a/.travis.yml b/.travis.yml index af7d5dbebf..a3c02eea58 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,14 @@ language: csharp os: - linux - osx +dist: trusty +env: + global: + - DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 + - DOTNET_CLI_TELEMETRY_OPTOUT=1 mono: - latest +dotnet: 1.0.1 script: - ./build.sh --target "Travis" --platform "Mono" --configuration "Release" notifications: diff --git a/Avalonia.sln b/Avalonia.sln index 78da02164e..4cc0da735a 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.4 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Base", "src\Avalonia.Base\Avalonia.Base.csproj", "{B09B78D8-9B26-48B0-9149-D64A2F120F3F}" EndProject @@ -15,9 +15,6 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Direct2D1", "src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj", "{3E908F67-5543-4879-A1DC-08EACE79B3CD}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Designer", "src\Windows\Avalonia.Designer\Avalonia.Designer.csproj", "{EC42600F-049B-43FF-AED1-8314D61B2749}" - ProjectSection(ProjectDependencies) = postProject - {2B888490-D14A-4BCA-AB4B-48676FA93C9B} = {2B888490-D14A-4BCA-AB4B-48676FA93C9B} - EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Input", "src\Avalonia.Input\Avalonia.Input.csproj", "{62024B2D-53EB-4638-B26B-85EEAA54866E}" EndProject @@ -85,9 +82,6 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BindingTest", "samples\BindingTest\BindingTest.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}" - ProjectSection(ProjectDependencies) = postProject - {B61B66A3-B82D-4875-8001-89D3394FE0C9} = {B61B66A3-B82D-4875-8001-89D3394FE0C9} - EndProjectSection EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "RenderHelpers", "src\Shared\RenderHelpers\RenderHelpers.shproj", "{3C4C0CB4-0C0F-4450-A37B-148C84FF905F}" EndProject @@ -126,9 +120,6 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog", "samples\ControlCatalog\ControlCatalog.csproj", "{D0A739B9-3C68-4BA6-A328-41606954B6BD}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Desktop", "samples\ControlCatalog.Desktop\ControlCatalog.Desktop.csproj", "{2B888490-D14A-4BCA-AB4B-48676FA93C9B}" - ProjectSection(ProjectDependencies) = postProject - {BB1F7BB5-6AD4-4776-94D9-C09D0A972658} = {BB1F7BB5-6AD4-4776-94D9-C09D0A972658} - EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{57E0455D-D565-44BB-B069-EE1AA20F8337}" EndProject @@ -165,6 +156,41 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Gtk3", "src\Gtk\Avalonia.Gtk3\Avalonia.Gtk3.csproj", "{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Portable.Xaml-pcl259", "src\Markup\Portable.Xaml\src\Portable.Xaml\Portable.Xaml-pcl259.csproj", "{179484EC-DB00-451A-AD2D-2E2AB20DE519}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.NetCore", "samples\ControlCatalog.NetCore\ControlCatalog.NetCore.csproj", "{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{74487168-7D91-487E-BF93-055F2251461E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}" + ProjectSection(SolutionItems) = preProject + build\JetBrains.Annotations.props = build\JetBrains.Annotations.props + build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props + build\Magick.NET-Q16-AnyCPU.props = build\Magick.NET-Q16-AnyCPU.props + build\Markup.props = build\Markup.props + build\Microsoft.CSharp.props = build\Microsoft.CSharp.props + build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props + build\Moq.props = build\Moq.props + build\NetCore.props = build\NetCore.props + build\Rx.props = build\Rx.props + build\Serilog.props = build\Serilog.props + build\Serilog.Sinks.Trace.props = build\Serilog.Sinks.Trace.props + build\SharpDX.props = build\SharpDX.props + build\SkiaSharp.Desktop.props = build\SkiaSharp.Desktop.props + build\SkiaSharp.props = build\SkiaSharp.props + build\Splat.props = build\Splat.props + build\Sprache.props = build\Sprache.props + build\XUnit.props = build\XUnit.props + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{4D6FAF79-58B4-482F-9122-0668C346364C}" + ProjectSection(SolutionItems) = preProject + build\UnitTests.NetCore.targets = build\UnitTests.NetCore.targets + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.LinuxFramebuffer", "src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj", "{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Direct3DInteropSample", "samples\interop\Direct3DInteropSample\Direct3DInteropSample.csproj", "{638580B0-7910-40EF-B674-DCB34DA308CD}" EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution @@ -3044,6 +3070,126 @@ Global {179484EC-DB00-451A-AD2D-2E2AB20DE519}.Release|Mono.Build.0 = Release|Any CPU {179484EC-DB00-451A-AD2D-2E2AB20DE519}.Release|x86.ActiveCfg = Release|Any CPU {179484EC-DB00-451A-AD2D-2E2AB20DE519}.Release|x86.Build.0 = Release|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|Mono.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.AppStore|iPhone.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.AppStore|Mono.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.AppStore|Mono.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.AppStore|x86.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.AppStore|x86.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|iPhone.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|Mono.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|Mono.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|x86.ActiveCfg = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|x86.Build.0 = Debug|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|Any CPU.Build.0 = Release|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|iPhone.ActiveCfg = Release|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|iPhone.Build.0 = Release|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|Mono.ActiveCfg = Release|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|Mono.Build.0 = Release|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|x86.ActiveCfg = Release|Any CPU + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|x86.Build.0 = Release|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|Mono.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|iPhone.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|Mono.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|Mono.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|x86.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|x86.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|iPhone.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Mono.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Mono.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|x86.ActiveCfg = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|x86.Build.0 = Debug|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Any CPU.Build.0 = Release|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|iPhone.ActiveCfg = Release|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|iPhone.Build.0 = Release|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Mono.ActiveCfg = Release|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Mono.Build.0 = Release|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|x86.ActiveCfg = Release|Any CPU + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|x86.Build.0 = Release|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Ad-Hoc|Mono.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.AppStore|iPhone.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.AppStore|Mono.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.AppStore|Mono.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.AppStore|x86.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.AppStore|x86.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|iPhone.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|Mono.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|Mono.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|x86.ActiveCfg = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|x86.Build.0 = Debug|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Release|Any CPU.Build.0 = Release|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Release|iPhone.ActiveCfg = Release|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Release|iPhone.Build.0 = Release|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Release|Mono.ActiveCfg = Release|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Release|Mono.Build.0 = Release|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Release|x86.ActiveCfg = Release|Any CPU + {638580B0-7910-40EF-B674-DCB34DA308CD}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3100,5 +3246,10 @@ Global {7D2D3083-71DD-4CC9-8907-39A0D86FB322} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {BB1F7BB5-6AD4-4776-94D9-C09D0A972658} = {B9894058-278A-46B5-B6ED-AD613FCC03B3} {179484EC-DB00-451A-AD2D-2E2AB20DE519} = {8B6A8209-894F-4BA1-B880-965FD453982C} + {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3} = {9B9E3891-2366-4253-A952-D08BCEB71098} + {F3AC8BC1-27F5-4255-9AFC-04ABFD11683A} = {74487168-7D91-487E-BF93-055F2251461E} + {4D6FAF79-58B4-482F-9122-0668C346364C} = {74487168-7D91-487E-BF93-055F2251461E} + {854568D5-13D1-4B4F-B50D-534DC7EFD3C9} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B} + {638580B0-7910-40EF-B674-DCB34DA308CD} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9} EndGlobalSection EndGlobal diff --git a/Avalonia.v3.ncrunchsolution b/Avalonia.v3.ncrunchsolution index c2c454eae1..1b5b0c8930 100644 --- a/Avalonia.v3.ncrunchsolution +++ b/Avalonia.v3.ncrunchsolution @@ -3,7 +3,7 @@ tests\TestFiles\**.* - False + True .ncrunch True diff --git a/appveyor.yml b/appveyor.yml index db7d129dd1..4bf7f7f157 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,26 +1,32 @@ -os: Visual Studio 2015 +os: Visual Studio 2017 platform: - Any CPU +skip_branch_with_pr: true configuration: - Release environment: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 + DOTNET_CLI_TELEMETRY_OPTOUT: 1 NUGET_API_KEY: secure: Xv89dlP2MSBZKhl1nrWSxqcDgCXB0HRhOd4SWQ+jRJ7QoLxQel5mLTipXM++J3G5 NUGET_API_URL: https://www.nuget.org/api/v2/package MYGET_API_KEY: secure: OtVfyN3ErqQrDTnWH2HDfJDlCiu/i4/X4wFmK3ZXXP7HmCiXYPSbTjMPwwdOxRaK MYGET_API_URL: https://www.myget.org/F/avalonia-ci/api/v2/package +init: +- ps: (New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/appveyor/ci/master/scripts/xamarin-vs2017-151-fixed.targets', "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Microsoft.Common.Targets\ImportAfter\Xamarin.Common.targets") install: - if not exist gtk-sharp-2.12.26.msi appveyor DownloadFile http://download.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.26.msi - - msiexec /i gtk-sharp-2.12.26.msi /qn /norestart + - if not exist dotnet-1.0.1.exe appveyor DownloadFile https://go.microsoft.com/fwlink/?linkid=843448 -FileName "dotnet-1.0.1.exe" + - ps: Start-Process -FilePath "msiexec" -ArgumentList "/i gtk-sharp-2.12.26.msi /quiet /qn /norestart" -Wait + - ps: Start-Process -FilePath "dotnet-1.0.1.exe" -ArgumentList "/quiet" -Wait - cmd: set PATH=%programfiles(x86)%\GtkSharp\2.12\bin\;%PATH% before_build: - git submodule update --init build_script: - ps: .\build.ps1 -Target "AppVeyor" -Platform "$env:platform" -Configuration "$env:configuration" after_build: -- .\packages\JetBrains.dotMemoryUnit.2.1.20150828.125449\tools\dotMemoryUnit.exe -targetExecutable="%xunit20%\xunit.console.x86.exe" -returnTargetExitCode --"tests\Avalonia.LeakTests\bin\Release\Avalonia.LeakTests.dll" - +- tools\JetBrains.dotMemoryUnit\tools\dotMemoryUnit.exe -targetExecutable="%xunit20%\xunit.console.x86.exe" -returnTargetExitCode --"tests\Avalonia.LeakTests\bin\Release\Avalonia.LeakTests.dll" - "SET PATH=C:\\Python34;C:\\Python34\\Scripts;%PATH%" - pip install codecov - codecov -f "./artifacts/coverage.xml" @@ -31,3 +37,4 @@ artifacts: - path: artifacts\zip\*.zip cache: - gtk-sharp-2.12.26.msi + - dotnet-1.0.1.exe diff --git a/build.cake b/build.cake index ee68c74bb3..1e29b33fc1 100644 --- a/build.cake +++ b/build.cake @@ -4,7 +4,8 @@ #addin "nuget:?package=Polly&version=4.2.0" #addin "nuget:?package=NuGet.Core&version=2.12.0" - +#tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease" +#tool "nuget:?package=JetBrains.dotMemoryUnit&version=2.1.20150828.125449" /////////////////////////////////////////////////////////////////////////////// // TOOLS /////////////////////////////////////////////////////////////////////////////// @@ -96,46 +97,10 @@ Task("Clean") CleanDirectory(parameters.TestsRoot); }); -Task("Prepare-XBuild-Solution") - .Does(() => -{ - var blacklistedProjects = new[] - { - "Avalonia.Win32.NetStandard", - "Avalonia.DotNetCoreRuntime", - "Avalonia.Skia.Desktop.NetStandard", - "Avalonia.Gtk3" - }; - var blacklistedGuids = System.IO.File.ReadAllLines(parameters.MSBuildSolution) - .Where(l=>l.StartsWith("Project") && blacklistedProjects.Any(p=>l.Contains(p))) - .Select(l => l.Split(',').Select(part => part.Trim()).FirstOrDefault(part => part.StartsWith("\"{"))) - .Where(g=>g!=null) - .Select(l=>l.Trim(new[]{'"', '}', '{'}).ToLower()).ToArray(); - - Console.WriteLine("Blacklisted guids are: " + string.Join(",", blacklistedGuids)); - var removeUntilEndProject = false; - - System.IO.File.WriteAllLines(parameters.XBuildSolution, System.IO.File.ReadAllLines(parameters.MSBuildSolution) - .Where(l => - { - if(removeUntilEndProject) - { - if(l.StartsWith("EndProject")) - removeUntilEndProject = false; - return false; - } - - var blacklist = blacklistedGuids.Any(g => l.ToLower().Contains(g)); - if(blacklist && l.StartsWith("Project")) - removeUntilEndProject = true; - - return !blacklist; - })); -}); Task("Restore-NuGet-Packages") .IsDependentOn("Clean") - .IsDependentOn("Prepare-XBuild-Solution") + .WithCriteria(parameters.IsRunningOnWindows) .Does(() => { var maxRetryCount = 5; @@ -153,21 +118,23 @@ Task("Restore-NuGet-Packages") toolTimeout+=0.5; }}) .Execute(()=> { - if(parameters.IsRunningOnWindows) - { NuGetRestore(parameters.MSBuildSolution, new NuGetRestoreSettings { + ToolPath = "./tools/NuGet.CommandLine/tools/NuGet.exe", ToolTimeout = TimeSpan.FromMinutes(toolTimeout) }); - } - else - { - NuGetRestore(parameters.XBuildSolution, new NuGetRestoreSettings { - ToolTimeout = TimeSpan.FromMinutes(toolTimeout) - }); - } }); }); +void DotNetCoreBuild() +{ + DotNetCoreRestore("samples\\ControlCatalog.NetCore"); + DotNetBuild("samples\\ControlCatalog.NetCore"); +} + +Task("DotNetCoreBuild") + .IsDependentOn("Clean") + .Does(() => DotNetCoreBuild()); + Task("Build") .IsDependentOn("Restore-NuGet-Packages") .Does(() => @@ -177,27 +144,60 @@ Task("Build") MSBuild(parameters.MSBuildSolution, settings => { settings.SetConfiguration(parameters.Configuration); settings.WithProperty("Platform", "\"" + parameters.Platform + "\""); + settings.WithProperty("UseRoslynPathHack", "true"); settings.SetVerbosity(Verbosity.Minimal); settings.WithProperty("Windows", "True"); - settings.UseToolVersion(MSBuildToolVersion.VS2015); + settings.UseToolVersion(MSBuildToolVersion.VS2017); settings.SetNodeReuse(false); }); } else { - XBuild(parameters.XBuildSolution, settings => { - settings.SetConfiguration(parameters.Configuration); - settings.WithProperty("Platform", "\"" + parameters.Platform + "\""); - settings.SetVerbosity(Verbosity.Minimal); - }); + DotNetCoreBuild(); } }); +void RunCoreTest(string dir, Parameters parameters, bool net461Only) +{ + Information("Running tests from " + dir); + DotNetCoreRestore(dir); + var frameworks = new List(){"netcoreapp1.1"}; + if(parameters.IsRunningOnWindows) + frameworks.Add("net461"); + foreach(var fw in frameworks) + { + if(fw != "net461" && net461Only) + continue; + Information("Running for " + fw); + DotNetCoreTest(System.IO.Path.Combine(dir, System.IO.Path.GetFileName(dir)+".csproj"), + new DotNetCoreTestSettings{Framework = fw}); + } +} + + +Task("Run-Net-Core-Unit-Tests") + .IsDependentOn("Clean") + .Does(() => { + RunCoreTest("./tests/Avalonia.Base.UnitTests", parameters, false); + RunCoreTest("./tests/Avalonia.Controls.UnitTests", parameters, true); + RunCoreTest("./tests/Avalonia.Input.UnitTests", parameters, true); + RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", parameters, true); + RunCoreTest("./tests/Avalonia.Layout.UnitTests", parameters, true); + //RunCoreTest("./tests/Avalonia.Markup.UnitTests", parameters, true); + //RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", parameters, true); + RunCoreTest("./tests/Avalonia.Styling.UnitTests", parameters, true); + RunCoreTest("./tests/Avalonia.Visuals.UnitTests", parameters, true); + }); + Task("Run-Unit-Tests") + .IsDependentOn("Run-Net-Core-Unit-Tests") .IsDependentOn("Build") .WithCriteria(() => !parameters.SkipTests) .Does(() => { + if(!parameters.IsRunningOnWindows) + return; + var unitTests = GetDirectories("./tests/Avalonia.*.UnitTests") .Select(dir => System.IO.Path.GetFileName(dir.FullPath)) .Where(name => parameters.IsRunningOnWindows ? true : !(name.IndexOf("Direct2D", StringComparison.OrdinalIgnoreCase) >= 0)) @@ -236,7 +236,11 @@ Task("Run-Unit-Tests") { CopyDirectory(test.GetDirectory(), parameters.TestsRoot); } - + + CopyFile(System.IO.Path.Combine(packages.NugetPackagesDir, "SkiaSharp", packages.SkiaSharpVersion, + "runtimes", "win7-x86", "native", "libSkiaSharp.dll"), + System.IO.Path.Combine(parameters.TestsRoot.ToString(), "libSkiaSharp.dll")); + var testsInDirectoryToRun = new List(); if(parameters.IsRunningOnWindows) { @@ -363,16 +367,20 @@ Task("Publish-NuGet") Task("Package") .IsDependentOn("Create-NuGet-Packages"); -Task("Default") - .IsDependentOn("Package"); - +Task("Default").Does(() => +{ + if(parameters.IsRunningOnWindows) + RunTarget("Package"); + else + RunTarget("Run-Net-Core-Unit-Tests"); +}); Task("AppVeyor") .IsDependentOn("Zip-Files") .IsDependentOn("Publish-MyGet") .IsDependentOn("Publish-NuGet"); Task("Travis") - .IsDependentOn("Run-Unit-Tests"); + .IsDependentOn("Run-Net-Core-Unit-Tests"); /////////////////////////////////////////////////////////////////////////////// // EXECUTE diff --git a/build/JetBrains.Annotations.props b/build/JetBrains.Annotations.props new file mode 100644 index 0000000000..7bc12cbd84 --- /dev/null +++ b/build/JetBrains.Annotations.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/JetBrains.dotMemoryUnit.props b/build/JetBrains.dotMemoryUnit.props new file mode 100644 index 0000000000..b4cf4def5b --- /dev/null +++ b/build/JetBrains.dotMemoryUnit.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/Magick.NET-Q16-AnyCPU.props b/build/Magick.NET-Q16-AnyCPU.props new file mode 100644 index 0000000000..ec747a17d8 --- /dev/null +++ b/build/Magick.NET-Q16-AnyCPU.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/Markup.props b/build/Markup.props new file mode 100644 index 0000000000..36c4cb28d8 --- /dev/null +++ b/build/Markup.props @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/build/Microsoft.CSharp.props b/build/Microsoft.CSharp.props new file mode 100644 index 0000000000..d0fa63bc3e --- /dev/null +++ b/build/Microsoft.CSharp.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/Microsoft.Reactive.Testing.props b/build/Microsoft.Reactive.Testing.props new file mode 100644 index 0000000000..5ee6df708e --- /dev/null +++ b/build/Microsoft.Reactive.Testing.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/Moq.props b/build/Moq.props new file mode 100644 index 0000000000..c8544b8309 --- /dev/null +++ b/build/Moq.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/NetCore.props b/build/NetCore.props new file mode 100644 index 0000000000..cebb02c7f5 --- /dev/null +++ b/build/NetCore.props @@ -0,0 +1,6 @@ + + + + + + diff --git a/build/Rx.props b/build/Rx.props new file mode 100644 index 0000000000..5d74a6b214 --- /dev/null +++ b/build/Rx.props @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/build/Serilog.Sinks.Trace.props b/build/Serilog.Sinks.Trace.props new file mode 100644 index 0000000000..ef79fd7669 --- /dev/null +++ b/build/Serilog.Sinks.Trace.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/Serilog.props b/build/Serilog.props new file mode 100644 index 0000000000..e9bd39f6af --- /dev/null +++ b/build/Serilog.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/SharpDX.props b/build/SharpDX.props new file mode 100644 index 0000000000..e381bc03e6 --- /dev/null +++ b/build/SharpDX.props @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/build/SkiaSharp.Desktop.props b/build/SkiaSharp.Desktop.props new file mode 100644 index 0000000000..bb6b29cfa6 --- /dev/null +++ b/build/SkiaSharp.Desktop.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props new file mode 100644 index 0000000000..bd6b4ebc53 --- /dev/null +++ b/build/SkiaSharp.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/Splat.props b/build/Splat.props new file mode 100644 index 0000000000..bc3367be01 --- /dev/null +++ b/build/Splat.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/Sprache.props b/build/Sprache.props new file mode 100644 index 0000000000..8ea84de163 --- /dev/null +++ b/build/Sprache.props @@ -0,0 +1,5 @@ + + + + + diff --git a/build/UnitTests.NetCore.targets b/build/UnitTests.NetCore.targets new file mode 100644 index 0000000000..a8886fe028 --- /dev/null +++ b/build/UnitTests.NetCore.targets @@ -0,0 +1,29 @@ + + + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + MinimumRecommendedRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + MinimumRecommendedRules.ruleset + + + + + + \ No newline at end of file diff --git a/build/XUnit.props b/build/XUnit.props new file mode 100644 index 0000000000..58df7e8d3c --- /dev/null +++ b/build/XUnit.props @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/build/readme.md b/build/readme.md new file mode 100644 index 0000000000..aed508a508 --- /dev/null +++ b/build/readme.md @@ -0,0 +1,27 @@ +### MSBuild Props + +```XML + + + + + + + + + + + + + + + + + +``` + +### MSBuild Targets + +```XML + +``` \ No newline at end of file diff --git a/docs/guidelines/build.md b/docs/guidelines/build.md index 12047ff357..822496814b 100644 --- a/docs/guidelines/build.md +++ b/docs/guidelines/build.md @@ -2,7 +2,7 @@ ## Windows -Avalonia requires at least Visual Studio 2015 to build on Windows. +Avalonia requires at least Visual Studio 2017 to build on Windows. ### Install GTK Sharp diff --git a/packages.cake b/packages.cake index 67483c4579..f030c73a06 100644 --- a/packages.cake +++ b/packages.cake @@ -1,9 +1,12 @@ +using System.Xml.Linq; + public class Packages { public List NuspecNuGetSettings { get; private set; } public FilePath[] NugetPackages { get; private set; } public FilePath[] BinFiles { get; private set; } - + public string NugetPackagesDir {get; private set;} + public string SkiaSharpVersion {get; private set; } public Packages(ICakeContext context, Parameters parameters) { // NUGET NUSPECS @@ -20,24 +23,30 @@ public class Packages path => path.Replace(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar).ToUpperInvariant()); // Key: Package Id - // Value is Tuple where Item1: Package Version, Item2: The packages.config file path. + // Value is Tuple where Item1: Package Version, Item2: The *.csproj/*.props file path. var packageVersions = new Dictionary>>(); - System.IO.Directory.EnumerateFiles(((DirectoryPath)context.Directory("./src")).FullPath, "packages.config", SearchOption.AllDirectories).ToList().ForEach(fileName => + System.IO.Directory.EnumerateFiles(((DirectoryPath)context.Directory("./build")).FullPath, + "*.props", SearchOption.AllDirectories).ToList().ForEach(fileName => { if (!ignoredSubModulesPaths.Any(i => normalizePath(fileName).Contains(normalizePath(i)))) { - var file = new PackageReferenceFile(fileName); - foreach (PackageReference packageReference in file.GetPackageReferences()) + var xdoc = XDocument.Load(fileName); + foreach (var reference in xdoc.Descendants().Where(x => x.Name.LocalName == "PackageReference")) { + var name = reference.Attribute("Include").Value; + var versionAttribute = reference.Attribute("Version"); + var version = versionAttribute != null + ? versionAttribute.Value + : reference.Elements().First(x=>x.Name.LocalName == "Version").Value; IList> versions; - packageVersions.TryGetValue(packageReference.Id, out versions); + packageVersions.TryGetValue(name, out versions); if (versions == null) { versions = new List>(); - packageVersions[packageReference.Id] = versions; + packageVersions[name] = versions; } - versions.Add(Tuple.Create(packageReference.Version.ToString(), fileName)); + versions.Add(Tuple.Create(version, fileName)); } } }); @@ -65,7 +74,7 @@ public class Packages var SplatVersion = packageVersions["Splat"].FirstOrDefault().Item1; var SpracheVersion = packageVersions["Sprache"].FirstOrDefault().Item1; var SystemReactiveVersion = packageVersions["System.Reactive"].FirstOrDefault().Item1; - var SkiaSharpVersion = packageVersions["SkiaSharp"].FirstOrDefault().Item1; + SkiaSharpVersion = packageVersions["SkiaSharp"].FirstOrDefault().Item1; var SharpDXVersion = packageVersions["SharpDX"].FirstOrDefault().Item1; var SharpDXDirect2D1Version = packageVersions["SharpDX.Direct2D1"].FirstOrDefault().Item1; var SharpDXDirect3D11Version = packageVersions["SharpDX.Direct3D11"].FirstOrDefault().Item1; @@ -81,6 +90,11 @@ public class Packages context.Information("Package: SharpDX.Direct3D11, version: {0}", SharpDXDirect3D11Version); context.Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion); + var nugetPackagesDir = System.Environment.GetEnvironmentVariable("NUGET_HOME") + ?? System.IO.Path.Combine(System.Environment.GetEnvironmentVariable("USERPROFILE") ?? System.Environment.GetEnvironmentVariable("HOME"), ".nuget"); + + NugetPackagesDir = System.IO.Path.Combine(nugetPackagesDir, "packages"); + var SetNuGetNuspecCommonProperties = new Action ((nuspec) => { nuspec.Version = parameters.Version; nuspec.Authors = new [] { "Avalonia Team" }; @@ -129,12 +143,12 @@ public class Packages }; var coreLibrariesFiles = coreLibraries.Select((lib) => { - return (FilePath)context.File(lib[0] + lib[1] + "/bin/" + parameters.DirSuffix + "/" + lib[1] + lib[2]); + return (FilePath)context.File(lib[0] + lib[1] + "/bin/" + parameters.DirSuffix + "/netstandard1.1/" + lib[1] + lib[2]); }).ToList(); var coreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => { return new NuSpecContent { - Source = file.FullPath, Target = "lib/portable-windows8+net45" + Source = file.FullPath, Target = "lib/netstandard1.1" }; }); @@ -161,7 +175,7 @@ public class Packages var netCoreRuntimePlatformExtensions = new [] {".xml", ".dll"}; var netCoreRuntimePlatform = netCoreRuntimePlatformExtensions.Select(libSuffix => { return new NuSpecContent { - Source = ((FilePath)context.File("./src/Avalonia.DotNetCoreRuntime/bin/" + parameters.DirSuffix + "/Avalonia.DotNetCoreRuntime" + libSuffix)).FullPath, + Source = ((FilePath)context.File("./src/Avalonia.DotNetCoreRuntime/bin/" + parameters.DirSuffix + "/netcoreapp1.0/Avalonia.DotNetCoreRuntime" + libSuffix)).FullPath, Target = "lib/netcoreapp1.0" }; }); @@ -180,12 +194,12 @@ public class Packages new NuSpecDependency() { Id = "Splat", Version = SplatVersion }, new NuSpecDependency() { Id = "Sprache", Version = SpracheVersion }, new NuSpecDependency() { Id = "System.Reactive", Version = SystemReactiveVersion }, - new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp1.0", Version = "4.3.0" }, //.NET Core + new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp1.0", Version = "4.3.0" }, + new NuSpecDependency() { Id = "Microsoft.Extensions.DependencyModel", TargetFramework = "netcoreapp1.0", Version = "1.1.0" }, new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp1.0", Version = "1.6.0" }, - new NuSpecDependency() { Id = "Microsoft.NETCore.Portable.Compatibility", TargetFramework = "netcoreapp1.0", Version = "1.0.1" }, - new NuSpecDependency() { Id = "Splat", TargetFramework = "netcoreapp1.0", Version = "2.0.0" }, - new NuSpecDependency() { Id = "Serilog", TargetFramework = "netcoreapp1.0", Version = "2.3.0" }, + new NuSpecDependency() { Id = "Splat", TargetFramework = "netcoreapp1.0", Version = SplatVersion }, + new NuSpecDependency() { Id = "Serilog", TargetFramework = "netcoreapp1.0", Version = SerilogVersion }, new NuSpecDependency() { Id = "Sprache", TargetFramework = "netcoreapp1.0", Version = SpracheVersion }, new NuSpecDependency() { Id = "System.Reactive", TargetFramework = "netcoreapp1.0", Version = SystemReactiveVersion } }, @@ -208,9 +222,9 @@ public class Packages }, Files = new [] { - new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/portable-windows8+net45" } + new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/netstandard1.1" } }, - BasePath = context.Directory("./src/Avalonia.HtmlRenderer/bin/" + parameters.DirSuffix), + BasePath = context.Directory("./src/Avalonia.HtmlRenderer/bin/" + parameters.DirSuffix + "/netstandard1.1"), OutputDirectory = parameters.NugetRoot } }; @@ -324,7 +338,7 @@ public class Packages Files = new [] { new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/Avalonia.Win32.dll", Target = "lib/net45" }, - new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/Avalonia.Win32.dll", Target = "lib/netstandard1.1" } + new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/netstandard1.1/Avalonia.Win32.dll", Target = "lib/netstandard1.1" } }, BasePath = context.Directory("./src/Windows"), OutputDirectory = parameters.NugetRoot @@ -381,7 +395,7 @@ public class Packages { new NuSpecContent { Source = "Avalonia.Gtk3.dll", Target = "lib/netstandard1.1" } }, - BasePath = context.Directory("./src/Gtk/Avalonia.Gtk3/bin/" + parameters.DirSuffix), + BasePath = context.Directory("./src/Gtk/Avalonia.Gtk3/bin/" + parameters.DirSuffix + "/netstandard1.1"), OutputDirectory = parameters.NugetRoot }, /////////////////////////////////////////////////////////////////////////////// @@ -411,16 +425,15 @@ public class Packages { new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version }, new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }, - //.NET Core - new NuSpecDependency() { Id = "Avalonia", TargetFramework = "netcoreapp1.0", Version = parameters.Version }, - new NuSpecDependency() { Id = "SkiaSharp", TargetFramework = "netcoreapp1.0", Version = SkiaSharpVersion }, - new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp1.0", Version = "1.6.0" }, - new NuSpecDependency() { Id = "Microsoft.NETCore.Portable.Compatibility", TargetFramework = "netcoreapp1.0", Version = "1.0.1" } + //netstandard1.3 + new NuSpecDependency() { Id = "Avalonia", TargetFramework = "netstandard1.3", Version = parameters.Version }, + new NuSpecDependency() { Id = "SkiaSharp", TargetFramework = "netstandard1.3", Version = SkiaSharpVersion }, + new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netstandard1.3", Version = "1.6.0" } }, Files = new [] { new NuSpecContent { Source = "Avalonia.Skia.Desktop/bin/" + parameters.DirSuffixSkia + "/Avalonia.Skia.Desktop.dll", Target = "lib/net45" }, - new NuSpecContent { Source = "Avalonia.Skia.Desktop.NetStandard/bin/" + parameters.DirSuffix + "/Avalonia.Skia.Desktop.dll", Target = "lib/netcoreapp1.0" } + new NuSpecContent { Source = "Avalonia.Skia.Desktop.NetStandard/bin/" + parameters.DirSuffix + "/netstandard1.3/Avalonia.Skia.Desktop.dll", Target = "lib/netstandard1.3" } }, BasePath = context.Directory("./src/Skia/"), OutputDirectory = parameters.NugetRoot @@ -445,6 +458,24 @@ public class Packages }, BasePath = context.Directory("./"), OutputDirectory = parameters.NugetRoot + }, + /////////////////////////////////////////////////////////////////////////////// + // Avalonia.LinuxFramebuffer + /////////////////////////////////////////////////////////////////////////////// + new NuGetPackSettings() + { + Id = "Avalonia.LinuxFramebuffer", + Dependencies = new [] + { + new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version }, + new NuSpecDependency() { Id = "Avalonia.Skia.Desktop", Version = parameters.Version } + }, + Files = new [] + { + new NuSpecContent { Source = "Avalonia.LinuxFramebuffer/bin/" + parameters.DirSuffix + "/netstandard1.3/Avalonia.LinuxFramebuffer.dll", Target = "lib/netstandard1.3" } + }, + BasePath = context.Directory("./src/Linux/"), + OutputDirectory = parameters.NugetRoot } }; diff --git a/readme.md b/readme.md index 0cc2b05e9d..2149aff386 100644 --- a/readme.md +++ b/readme.md @@ -3,7 +3,7 @@ | Gitter Chat | Windows Build Status | Linux/Mac Build Status | Code Coverage | |---|---|---|---| -| [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Build Status](https://travis-ci.org/AvaloniaUI/Avalonia.svg?branch=master)](https://travis-ci.org/AvaloniaUI/Avalonia) | [![codecov](https://codecov.io/gh/AvaloniaUI/Avalonia/branch/master/graph/badge.svg)](https://codecov.io/gh/AvaloniaUI/Avalonia) | +| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Build Status](https://travis-ci.org/AvaloniaUI/Avalonia.svg?branch=master)](https://travis-ci.org/AvaloniaUI/Avalonia) | [![codecov](https://codecov.io/gh/AvaloniaUI/Avalonia/branch/master/graph/badge.svg)](https://codecov.io/gh/AvaloniaUI/Avalonia) | A multi-platform .NET UI framework. It can run on Windows, Linux, Mac OS X, iOS and Android. diff --git a/samples/BindingTest/App.config b/samples/BindingTest/App.config index 98b10dfce2..d9f870f27b 100644 --- a/samples/BindingTest/App.config +++ b/samples/BindingTest/App.config @@ -7,11 +7,11 @@ - + - + diff --git a/samples/BindingTest/BindingTest.csproj b/samples/BindingTest/BindingTest.csproj index 75ae306c75..f8964f9fb4 100644 --- a/samples/BindingTest/BindingTest.csproj +++ b/samples/BindingTest/BindingTest.csproj @@ -1,5 +1,5 @@  - + Debug @@ -13,6 +13,7 @@ 512 true + PackageReference AnyCPU @@ -37,18 +38,6 @@ - - ..\..\packages\Serilog.1.5.14\lib\net45\Serilog.dll - True - - - ..\..\packages\Serilog.1.5.14\lib\net45\Serilog.FullNetFx.dll - True - - - ..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll - True - @@ -96,7 +85,6 @@ Designer - @@ -182,11 +170,9 @@ - + + + + + \ No newline at end of file diff --git a/samples/BindingTest/packages.config b/samples/BindingTest/packages.config deleted file mode 100644 index 8b267c8cbd..0000000000 --- a/samples/BindingTest/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj index 41d6329d26..4db67a8b60 100644 --- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj +++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj @@ -73,7 +73,6 @@ - @@ -157,12 +156,7 @@ ControlCatalog + - + \ No newline at end of file diff --git a/samples/ControlCatalog.Android/GettingStarted.Xamarin b/samples/ControlCatalog.Android/GettingStarted.Xamarin deleted file mode 100644 index e9d4f6a411..0000000000 --- a/samples/ControlCatalog.Android/GettingStarted.Xamarin +++ /dev/null @@ -1,4 +0,0 @@ - - GS\Android\CS\AndroidApp\GettingStarted.html - false - \ No newline at end of file diff --git a/samples/ControlCatalog.Android/Resources/Resource.Designer.cs b/samples/ControlCatalog.Android/Resources/Resource.Designer.cs index 96f0e76fd8..cee3331ba8 100644 --- a/samples/ControlCatalog.Android/Resources/Resource.Designer.cs +++ b/samples/ControlCatalog.Android/Resources/Resource.Designer.cs @@ -28,6 +28,8 @@ namespace ControlCatalog.Android { global::Avalonia.Android.Resource.String.ApplicationName = global::ControlCatalog.Android.Resource.String.ApplicationName; global::Avalonia.Android.Resource.String.Hello = global::ControlCatalog.Android.Resource.String.Hello; + global::Avalonia.Android.Resource.String.library_name = global::ControlCatalog.Android.Resource.String.library_name; + global::Splat.Resource.String.library_name = global::ControlCatalog.Android.Resource.String.library_name; } public partial class Attribute @@ -94,11 +96,14 @@ namespace ControlCatalog.Android public partial class String { + // aapt resource value: 0x7f040002 + public const int ApplicationName = 2130968578; + // aapt resource value: 0x7f040001 - public const int ApplicationName = 2130968577; + public const int Hello = 2130968577; // aapt resource value: 0x7f040000 - public const int Hello = 2130968576; + public const int library_name = 2130968576; static String() { diff --git a/samples/ControlCatalog.Desktop/App.config b/samples/ControlCatalog.Desktop/App.config index 2231c71e63..10a06d8258 100644 --- a/samples/ControlCatalog.Desktop/App.config +++ b/samples/ControlCatalog.Desktop/App.config @@ -9,6 +9,14 @@ + + + + + + + + diff --git a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj index ca5743dd5c..3ca8640d40 100644 --- a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj +++ b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj @@ -1,5 +1,5 @@  - + Debug @@ -13,6 +13,7 @@ 512 true + PackageReference AnyCPU @@ -37,14 +38,6 @@ - - ..\..\packages\Serilog.1.5.14\lib\net45\Serilog.dll - True - - - ..\..\packages\Serilog.1.5.14\lib\net45\Serilog.FullNetFx.dll - True - @@ -57,7 +50,6 @@ - @@ -149,11 +141,7 @@ - + + + \ No newline at end of file diff --git a/samples/ControlCatalog.Desktop/packages.config b/samples/ControlCatalog.Desktop/packages.config deleted file mode 100644 index b3abe6f487..0000000000 --- a/samples/ControlCatalog.Desktop/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj new file mode 100644 index 0000000000..e0e848b91b --- /dev/null +++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj @@ -0,0 +1,14 @@ + + + + Exe + netcoreapp1.1 + + + + + + + + + \ No newline at end of file diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs new file mode 100644 index 0000000000..7c67a239e6 --- /dev/null +++ b/samples/ControlCatalog.NetCore/Program.cs @@ -0,0 +1,29 @@ +using System; +using System.Linq; +using Avalonia; + +namespace ControlCatalog.NetCore +{ + class Program + { + static void Main(string[] args) + { + if (args.Contains("--fbdev")) AppBuilder.Configure().InitializeWithLinuxFramebuffer(tl => + { + tl.Content = new MainView(); + System.Threading.ThreadPool.QueueUserWorkItem(_ => ConsoleSilencer()); + }); + else + AppBuilder.Configure() + .UsePlatformDetect() + .Start(); + } + + static void ConsoleSilencer() + { + Console.CursorVisible = false; + while (true) + Console.ReadKey(true); + } + } +} \ No newline at end of file diff --git a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj index d0c73b2553..01d287ea83 100644 --- a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj +++ b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj @@ -181,4 +181,5 @@ + \ No newline at end of file diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj index f4a0915dd1..2a9f8f70de 100644 --- a/samples/ControlCatalog/ControlCatalog.csproj +++ b/samples/ControlCatalog/ControlCatalog.csproj @@ -1,20 +1,8 @@ - - - + - 10.0 - Debug - AnyCPU - {D0A739B9-3C68-4BA6-A328-41606954B6BD} - Library - Properties - ControlCatalog - ControlCatalog - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 + netstandard1.1 + False + false true @@ -153,62 +141,20 @@ - - {3E53A01A-B331-47F3-B828-4A5717E77A24} - Avalonia.Markup.Xaml - - - {6417E941-21BC-467B-A771-0DE389353CE6} - Avalonia.Markup - - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {D2221C82-4A25-4583-9B43-D791E3F6820C} - Avalonia.Controls - - - {7062AE20-5DCC-4442-9645-8195BDECE63E} - Avalonia.Diagnostics - - - {5FB2B005-0A7F-4DAD-ADD4-3ED01444E63D} - Avalonia.HtmlRenderer - - - {62024B2D-53EB-4638-B26B-85EEAA54866E} - Avalonia.Input - - - {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B} - Avalonia.Interactivity - - - {42472427-4774-4C81-8AFF-9F27B8E31721} - Avalonia.Layout - - - {6417B24E-49C2-4985-8DB2-3AB9D898EC91} - Avalonia.ReactiveUI - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - - - {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F} - Avalonia.Styling - - - {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F} - Avalonia.Themes.Default - + + + + + + + + + + + + + + @@ -225,12 +171,5 @@ - - + \ No newline at end of file diff --git a/samples/ControlCatalog/packages.config b/samples/ControlCatalog/packages.config deleted file mode 100644 index 44ff0f0628..0000000000 --- a/samples/ControlCatalog/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/samples/RenderTest/MainWindow.xaml.cs b/samples/RenderTest/MainWindow.xaml.cs index c6c0eafd25..76a8e81aca 100644 --- a/samples/RenderTest/MainWindow.xaml.cs +++ b/samples/RenderTest/MainWindow.xaml.cs @@ -7,7 +7,6 @@ using Avalonia.Controls; using Avalonia.Markup.Xaml; using RenderTest.ViewModels; using ReactiveUI; -using Avalonia.Rendering; namespace RenderTest { @@ -19,7 +18,8 @@ namespace RenderTest this.AttachDevTools(); var vm = new MainWindowViewModel(); - vm.WhenAnyValue(x => x.DrawFps).Subscribe(x => RendererMixin.DrawFpsCounter = x); + vm.WhenAnyValue(x => x.DrawDirtyRects).Subscribe(x => Renderer.DrawDirtyRects = x); + vm.WhenAnyValue(x => x.DrawFps).Subscribe(x => Renderer.DrawFps = x); this.DataContext = vm; } diff --git a/samples/RenderTest/RenderTest.csproj b/samples/RenderTest/RenderTest.csproj index a14114ddc8..cf32316086 100644 --- a/samples/RenderTest/RenderTest.csproj +++ b/samples/RenderTest/RenderTest.csproj @@ -1,5 +1,5 @@  - + Debug @@ -37,40 +37,8 @@ - - ..\..\packages\Serilog.1.5.14\lib\net45\Serilog.dll - True - - - ..\..\packages\Serilog.1.5.14\lib\net45\Serilog.FullNetFx.dll - True - - - ..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll - True - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\net45\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\net45\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\net45\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\net45\System.Reactive.PlatformServices.dll - True - - - ..\..\packages\System.Reactive.Windows.Threading.3.0.0\lib\net45\System.Reactive.Windows.Threading.dll - True - @@ -98,7 +66,6 @@ - @@ -212,11 +179,9 @@ - + + + + + \ No newline at end of file diff --git a/samples/RenderTest/packages.config b/samples/RenderTest/packages.config deleted file mode 100644 index 7ba5166073..0000000000 --- a/samples/RenderTest/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/samples/VirtualizationTest/App.config b/samples/VirtualizationTest/App.config index 2231c71e63..10a06d8258 100644 --- a/samples/VirtualizationTest/App.config +++ b/samples/VirtualizationTest/App.config @@ -9,6 +9,14 @@ + + + + + + + + diff --git a/samples/VirtualizationTest/VirtualizationTest.csproj b/samples/VirtualizationTest/VirtualizationTest.csproj index 9e80dfdc8f..9b9d8a94c6 100644 --- a/samples/VirtualizationTest/VirtualizationTest.csproj +++ b/samples/VirtualizationTest/VirtualizationTest.csproj @@ -1,5 +1,5 @@  - + Debug @@ -37,28 +37,8 @@ - - ..\..\packages\Serilog.1.5.14\lib\net45\Serilog.dll - True - - - ..\..\packages\Serilog.1.5.14\lib\net45\Serilog.FullNetFx.dll - True - - - ..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll - True - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\net45\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\net45\System.Reactive.Interfaces.dll - True - @@ -80,7 +60,6 @@ - @@ -175,11 +154,9 @@ - + + + + + \ No newline at end of file diff --git a/samples/VirtualizationTest/packages.config b/samples/VirtualizationTest/packages.config deleted file mode 100644 index f2da2367fa..0000000000 --- a/samples/VirtualizationTest/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/samples/interop/Direct3DInteropSample/App.paml b/samples/interop/Direct3DInteropSample/App.paml new file mode 100644 index 0000000000..d9630eef58 --- /dev/null +++ b/samples/interop/Direct3DInteropSample/App.paml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/samples/interop/Direct3DInteropSample/App.paml.cs b/samples/interop/Direct3DInteropSample/App.paml.cs new file mode 100644 index 0000000000..1b6d5fd39c --- /dev/null +++ b/samples/interop/Direct3DInteropSample/App.paml.cs @@ -0,0 +1,13 @@ +using Avalonia; +using Avalonia.Markup.Xaml; + +namespace Direct3DInteropSample +{ + public class App : Application + { + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj b/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj new file mode 100644 index 0000000000..54a816b0a9 --- /dev/null +++ b/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj @@ -0,0 +1,34 @@ + + + Exe + net461 + + + + + + %(Filename) + + + Designer + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/interop/Direct3DInteropSample/MainWindow.cs b/samples/interop/Direct3DInteropSample/MainWindow.cs new file mode 100644 index 0000000000..1ff1e1938b --- /dev/null +++ b/samples/interop/Direct3DInteropSample/MainWindow.cs @@ -0,0 +1,264 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Direct2D1.Media; +using Avalonia.Markup.Xaml; +using Avalonia.Platform; +using Avalonia.Rendering; +using SharpDX; +using SharpDX.D3DCompiler; +using SharpDX.Direct2D1; +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using SharpDX.WIC; +using SharpDX.Mathematics; +using AlphaMode = SharpDX.Direct2D1.AlphaMode; +using Buffer = SharpDX.Direct3D11.Buffer; +using DeviceContext = SharpDX.Direct3D11.DeviceContext; +using Factory1 = SharpDX.DXGI.Factory1; +using InputElement = SharpDX.Direct3D11.InputElement; +using Matrix = SharpDX.Matrix; +using PixelFormat = SharpDX.Direct2D1.PixelFormat; + +namespace Direct3DInteropSample +{ + class MainWindow : Window + { + private SharpDX.Direct3D11.Device _d3dDevice; + private SharpDX.DXGI.Device _dxgiDevice; + Texture2D backBuffer = null; + RenderTargetView renderView = null; + Texture2D depthBuffer = null; + DepthStencilView depthView = null; + private readonly SwapChain _swapChain; + private SwapChainDescription _desc; + private Matrix _proj = Matrix.Identity; + private Matrix _view; + private Buffer _contantBuffer; + private SharpDX.Direct2D1.Device _d2dDevice; + private SharpDX.Direct2D1.DeviceContext _d2dContext; + private RenderTarget _d2dRenderTarget; + private MainWindowViewModel _model; + + public MainWindow() + { + _dxgiDevice = AvaloniaLocator.Current.GetService(); + _d3dDevice = _dxgiDevice.QueryInterface(); + _d2dDevice = AvaloniaLocator.Current.GetService(); + DataContext = _model = new MainWindowViewModel(); + _desc = new SwapChainDescription() + { + BufferCount = 1, + ModeDescription = + new ModeDescription((int)ClientSize.Width, (int)ClientSize.Height, + new Rational(60, 1), Format.R8G8B8A8_UNorm), + IsWindowed = true, + OutputHandle = PlatformImpl.Handle.Handle, + SampleDescription = new SampleDescription(1, 0), + SwapEffect = SwapEffect.Discard, + Usage = Usage.RenderTargetOutput + }; + + _swapChain = new SwapChain(new Factory1(), _d3dDevice, _desc); + + _d2dContext = new SharpDX.Direct2D1.DeviceContext(_d2dDevice, DeviceContextOptions.None) + { + DotsPerInch = new Size2F(96, 96) + }; + + CreateMesh(); + _view = Matrix.LookAtLH(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY); + this.GetObservable(ClientSizeProperty).Subscribe(Resize); + Resize(ClientSize); + AvaloniaXamlLoader.Load(this); + Background = Avalonia.Media.Brushes.Transparent; + } + + + protected override void HandlePaint(Rect rect) + { + var viewProj = Matrix.Multiply(_view, _proj); + var context = _d3dDevice.ImmediateContext; + // Clear views + context.ClearDepthStencilView(depthView, DepthStencilClearFlags.Depth, 1.0f, 0); + context.ClearRenderTargetView(renderView, Color.White); + + var time = 50; + // Update WorldViewProj Matrix + var worldViewProj = Matrix.RotationX((float) _model.RotationX) * Matrix.RotationY((float) _model.RotationY) * + Matrix.RotationZ((float) _model.RotationZ) + * Matrix.Scaling((float) _model.Zoom) * viewProj; + worldViewProj.Transpose(); + context.UpdateSubresource(ref worldViewProj, _contantBuffer); + + // Draw the cube + context.Draw(36, 0); + base.HandlePaint(rect); + // Present! + _swapChain.Present(0, PresentFlags.None); + } + + + void CreateMesh() + { + var device = _d3dDevice; + // Compile Vertex and Pixel shaders + var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.fx", "VS", "vs_4_0"); + var vertexShader = new VertexShader(device, vertexShaderByteCode); + + var pixelShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.fx", "PS", "ps_4_0"); + var pixelShader = new PixelShader(device, pixelShaderByteCode); + + var signature = ShaderSignature.GetInputSignature(vertexShaderByteCode); + // Layout from VertexShader input signature + var layout = new InputLayout(device, signature, new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0) + }); + + // Instantiate Vertex buiffer from vertex data + var vertices = Buffer.Create(device, BindFlags.VertexBuffer, new[] + { + new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front + new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + + new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + + new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top + new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), + new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), + new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), + + new Vector4(-1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom + new Vector4( 1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + new Vector4(-1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + new Vector4(-1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + new Vector4( 1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + new Vector4( 1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + + new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left + new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), + new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), + new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), + new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), + new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), + + new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), + new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), + new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), + new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), + }); + + // Create Constant Buffer + _contantBuffer = new Buffer(device, Utilities.SizeOf(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); + + var context = _d3dDevice.ImmediateContext; + + // Prepare All the stages + context.InputAssembler.InputLayout = layout; + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, Utilities.SizeOf() * 2, 0)); + context.VertexShader.SetConstantBuffer(0, _contantBuffer); + context.VertexShader.Set(vertexShader); + context.PixelShader.Set(pixelShader); + } + + void Resize(Size size) + { + Utilities.Dispose(ref _d2dRenderTarget); + Utilities.Dispose(ref backBuffer); + Utilities.Dispose(ref renderView); + Utilities.Dispose(ref depthBuffer); + Utilities.Dispose(ref depthView); + var context = _d3dDevice.ImmediateContext; + // Resize the backbuffer + _swapChain.ResizeBuffers(_desc.BufferCount, (int)size.Width, (int)size.Height, Format.Unknown, SwapChainFlags.None); + + // Get the backbuffer from the swapchain + backBuffer = Texture2D.FromSwapChain(_swapChain, 0); + + // Renderview on the backbuffer + renderView = new RenderTargetView(_d3dDevice, backBuffer); + + // Create the depth buffer + depthBuffer = new Texture2D(_d3dDevice, new Texture2DDescription() + { + Format = Format.D32_Float_S8X24_UInt, + ArraySize = 1, + MipLevels = 1, + Width = (int)size.Width, + Height = (int)size.Height, + SampleDescription = new SampleDescription(1, 0), + Usage = ResourceUsage.Default, + BindFlags = BindFlags.DepthStencil, + CpuAccessFlags = CpuAccessFlags.None, + OptionFlags = ResourceOptionFlags.None + }); + + // Create the depth buffer view + depthView = new DepthStencilView(_d3dDevice, depthBuffer); + + // Setup targets and viewport for rendering + context.Rasterizer.SetViewport(new Viewport(0, 0, (int)size.Width, (int)size.Height, 0.0f, 1.0f)); + context.OutputMerger.SetTargets(depthView, renderView); + + // Setup new projection matrix with correct aspect ratio + _proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, (float)(size.Width / size.Height), 0.1f, 100.0f); + + using (var dxgiBackBuffer = _swapChain.GetBackBuffer(0)) + { + _d2dRenderTarget = new RenderTarget(AvaloniaLocator.Current.GetService() + , dxgiBackBuffer, new RenderTargetProperties + { + DpiX = 96, + DpiY = 96, + Type = RenderTargetType.Default, + PixelFormat = new PixelFormat(Format.Unknown, AlphaMode.Premultiplied) + }); + } + + } + + class D3DRenderTarget: IRenderTarget + { + private readonly MainWindow _window; + + public D3DRenderTarget(MainWindow window) + { + _window = window; + } + public void Dispose() + { + + } + + public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) + { + return new DrawingContextImpl(visualBrushRenderer, _window._d2dRenderTarget, + AvaloniaLocator.Current.GetService()); + } + } + + + protected override IRenderTarget CreateRenderTarget() => new D3DRenderTarget(this); + } +} diff --git a/samples/interop/Direct3DInteropSample/MainWindow.paml b/samples/interop/Direct3DInteropSample/MainWindow.paml new file mode 100644 index 0000000000..37c6265836 --- /dev/null +++ b/samples/interop/Direct3DInteropSample/MainWindow.paml @@ -0,0 +1,14 @@ + + + + Rotation X + + Rotation Y + + Rotation Z + + Zoom + + + + \ No newline at end of file diff --git a/samples/interop/Direct3DInteropSample/MainWindowViewModel.cs b/samples/interop/Direct3DInteropSample/MainWindowViewModel.cs new file mode 100644 index 0000000000..d39a21cd07 --- /dev/null +++ b/samples/interop/Direct3DInteropSample/MainWindowViewModel.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ReactiveUI; + +namespace Direct3DInteropSample +{ + public class MainWindowViewModel : ReactiveObject + { + private double _rotationX; + + public double RotationX + { + get { return _rotationX; } + set { this.RaiseAndSetIfChanged(ref _rotationX, value); } + } + + private double _rotationY = 1; + + public double RotationY + { + get { return _rotationY; } + set { this.RaiseAndSetIfChanged(ref _rotationY, value); } + } + + private double _rotationZ = 2; + + public double RotationZ + { + get { return _rotationZ; } + set { this.RaiseAndSetIfChanged(ref _rotationZ, value); } + } + + + private double _zoom = 1; + + public double Zoom + { + get { return _zoom; } + set { this.RaiseAndSetIfChanged(ref _zoom, value); } + } + } +} diff --git a/samples/interop/Direct3DInteropSample/MiniCube.fx b/samples/interop/Direct3DInteropSample/MiniCube.fx new file mode 100644 index 0000000000..f246421f2d --- /dev/null +++ b/samples/interop/Direct3DInteropSample/MiniCube.fx @@ -0,0 +1,47 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +struct VS_IN +{ + float4 pos : POSITION; + float4 col : COLOR; +}; + +struct PS_IN +{ + float4 pos : SV_POSITION; + float4 col : COLOR; +}; + +float4x4 worldViewProj; + +PS_IN VS( VS_IN input ) +{ + PS_IN output = (PS_IN)0; + + output.pos = mul(input.pos, worldViewProj); + output.col = input.col; + + return output; +} + +float4 PS( PS_IN input ) : SV_Target +{ + return input.col; +} \ No newline at end of file diff --git a/samples/interop/Direct3DInteropSample/Program.cs b/samples/interop/Direct3DInteropSample/Program.cs new file mode 100644 index 0000000000..7fb650a7a8 --- /dev/null +++ b/samples/interop/Direct3DInteropSample/Program.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Avalonia; + +namespace Direct3DInteropSample +{ + class Program + { + static void Main(string[] args) + { + AppBuilder.Configure().UseWin32().UseDirect2D1().Start(); + } + } +} diff --git a/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj b/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj index 738a1e776c..044b96c865 100644 --- a/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj +++ b/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj @@ -150,11 +150,5 @@ - + \ No newline at end of file diff --git a/samples/interop/WindowsInteropTest/App.config b/samples/interop/WindowsInteropTest/App.config index 8324aa6ff1..4fe7131d2a 100644 --- a/samples/interop/WindowsInteropTest/App.config +++ b/samples/interop/WindowsInteropTest/App.config @@ -3,4 +3,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj index 671ebd0020..c787ab76ee 100644 --- a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj +++ b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj @@ -180,11 +180,5 @@ - + \ No newline at end of file diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs index 2089359c26..c779031e6c 100644 --- a/src/Android/Avalonia.Android/AndroidPlatform.cs +++ b/src/Android/Avalonia.Android/AndroidPlatform.cs @@ -53,6 +53,7 @@ namespace Avalonia.Android .Bind().ToSingleton() .Bind().ToSingleton() .Bind().ToConstant(Instance) + .Bind().ToConstant(ImmediateRenderer.Factory) .Bind().ToConstant(new AndroidThreadingInterface()) .Bind().ToTransient() .Bind().ToConstant(Instance) diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj index 3ee2f5af64..4babdc8bff 100644 --- a/src/Android/Avalonia.Android/Avalonia.Android.csproj +++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -41,18 +41,6 @@ - - ..\..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.3\System.Reactive.Core.dll - True - - - ..\..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.3\System.Reactive.PlatformServices.dll - True - @@ -86,7 +74,6 @@ - @@ -145,11 +132,9 @@ - + + + + $(MSBuildToolsPath)\Roslyn + \ No newline at end of file diff --git a/src/Android/Avalonia.Android/Resources/Resource.Designer.cs b/src/Android/Avalonia.Android/Resources/Resource.Designer.cs index 80cbbc51ec..e66c2800d3 100644 --- a/src/Android/Avalonia.Android/Resources/Resource.Designer.cs +++ b/src/Android/Avalonia.Android/Resources/Resource.Designer.cs @@ -40,11 +40,14 @@ namespace Avalonia.Android public partial class String { + // aapt resource value: 0x7f020002 + public static int ApplicationName = 2130837506; + // aapt resource value: 0x7f020001 - public static int ApplicationName = 2130837505; + public static int Hello = 2130837505; // aapt resource value: 0x7f020000 - public static int Hello = 2130837504; + public static int library_name = 2130837504; static String() { diff --git a/src/Android/Avalonia.Android/packages.config b/src/Android/Avalonia.Android/packages.config deleted file mode 100644 index 057d0855b8..0000000000 --- a/src/Android/Avalonia.Android/packages.config +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj index d09f162150..826f1f0132 100644 --- a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj +++ b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -64,35 +64,8 @@ - - ..\..\..\packages\Serilog.1.5.14\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+MonoTouch10\Serilog.dll - True - - - ..\..\..\packages\Splat.1.6.2\lib\monoandroid\Splat.dll - True - - - ..\..\..\packages\Sprache.2.1.0\lib\netstandard1.0\Sprache.dll - - - ..\..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.3\System.Reactive.Core.dll - True - - - ..\..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.3\System.Reactive.Linq.dll - True - - - ..\..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.3\System.Reactive.PlatformServices.dll - True - @@ -103,7 +76,6 @@ - @@ -181,11 +153,9 @@ - + + + + + \ No newline at end of file diff --git a/src/Android/Avalonia.AndroidTestApplication/Resources/Resource.Designer.cs b/src/Android/Avalonia.AndroidTestApplication/Resources/Resource.Designer.cs index 3fa0707176..91327cf941 100644 --- a/src/Android/Avalonia.AndroidTestApplication/Resources/Resource.Designer.cs +++ b/src/Android/Avalonia.AndroidTestApplication/Resources/Resource.Designer.cs @@ -28,6 +28,7 @@ namespace Avalonia.AndroidTestApplication { global::Avalonia.Android.Resource.String.ApplicationName = global::Avalonia.AndroidTestApplication.Resource.String.ApplicationName; global::Avalonia.Android.Resource.String.Hello = global::Avalonia.AndroidTestApplication.Resource.String.Hello; + global::Avalonia.Android.Resource.String.library_name = global::Avalonia.AndroidTestApplication.Resource.String.library_name; global::Splat.Resource.String.library_name = global::Avalonia.AndroidTestApplication.Resource.String.library_name; } diff --git a/src/Android/Avalonia.AndroidTestApplication/packages.config b/src/Android/Avalonia.AndroidTestApplication/packages.config deleted file mode 100644 index d353146747..0000000000 --- a/src/Android/Avalonia.AndroidTestApplication/packages.config +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Animation/Avalonia.Animation.csproj b/src/Avalonia.Animation/Avalonia.Animation.csproj index 46aac81b5a..f02ec2f31c 100644 --- a/src/Avalonia.Animation/Avalonia.Animation.csproj +++ b/src/Avalonia.Animation/Avalonia.Animation.csproj @@ -1,20 +1,7 @@ - - - + - 11.0 - Debug - AnyCPU - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Library - Properties - Avalonia.Animation - Avalonia.Animation - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 + netstandard1.1 + false true @@ -38,57 +25,13 @@ CS1591 true - - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.1\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.0\System.Reactive.PlatformServices.dll - True - - + - - + \ No newline at end of file diff --git a/src/Avalonia.Animation/packages.config b/src/Avalonia.Animation/packages.config deleted file mode 100644 index 9f732f1bcb..0000000000 --- a/src/Avalonia.Animation/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj index 7cfb6e2123..91978d4ae7 100644 --- a/src/Avalonia.Base/Avalonia.Base.csproj +++ b/src/Avalonia.Base/Avalonia.Base.csproj @@ -1,22 +1,7 @@ - - - + - 11.0 - Debug - AnyCPU - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Library - Properties - Avalonia - Avalonia.Base - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 - - + netstandard1.1 + false true @@ -127,37 +112,6 @@ - - - ..\..\packages\JetBrains.Annotations.10.0.0\lib\portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\JetBrains.Annotations.PCL328.dll - True - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.1\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.0\System.Reactive.PlatformServices.dll - True - - - - - - - + + \ No newline at end of file diff --git a/src/Avalonia.Base/AvaloniaDisposable.cs b/src/Avalonia.Base/AvaloniaDisposable.cs deleted file mode 100644 index 9e43a65f26..0000000000 --- a/src/Avalonia.Base/AvaloniaDisposable.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Platform; - -namespace Avalonia -{ - public abstract class AvaloniaDisposable : IDisposable - { -#if DEBUG_DISPOSE - public string DisposedAt { get; private set; } -#endif - - - public bool IsDisposed { get; private set; } - - public void Dispose() - { - IsDisposed = true; -#if DEBUG_DISPOSE - DisposedAt = AvaloniaLocator.Current.GetService().GetStackTrace(); -#endif - DoDispose(); - } - - protected void CheckDisposed() - { - if (IsDisposed) - throw new ObjectDisposedException(GetType().FullName -#if DEBUG_DISPOSE - , "Disposed at: \n" + DisposedAt -#endif - - ); - } - - protected abstract void DoDispose(); - } -} diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs index 409abfe8fa..1492c14c5f 100644 --- a/src/Avalonia.Base/AvaloniaObject.cs +++ b/src/Avalonia.Base/AvaloniaObject.cs @@ -181,6 +181,7 @@ namespace Avalonia public void ClearValue(AvaloniaProperty property) { Contract.Requires(property != null); + VerifyAccess(); SetValue(property, AvaloniaProperty.UnsetValue); } @@ -193,6 +194,7 @@ namespace Avalonia public object GetValue(AvaloniaProperty property) { Contract.Requires(property != null); + VerifyAccess(); if (property.IsDirect) { @@ -234,7 +236,8 @@ namespace Avalonia public bool IsSet(AvaloniaProperty property) { Contract.Requires(property != null); - + VerifyAccess(); + PriorityValue value; if (_values.TryGetValue(property, out value)) @@ -575,13 +578,13 @@ namespace Avalonia if (notification == null) { - return TypeUtilities.CastOrDefault(value, type); + return TypeUtilities.ConvertImplicitOrDefault(value, type); } else { if (notification.HasValue) { - notification.SetValue(TypeUtilities.CastOrDefault(notification.Value, type)); + notification.SetValue(TypeUtilities.ConvertImplicitOrDefault(notification.Value, type)); } return notification; @@ -732,7 +735,7 @@ namespace Avalonia ThrowNotRegistered(property); } - if (!TypeUtilities.TryCast(property.PropertyType, value, out value)) + if (!TypeUtilities.TryConvertImplicit(property.PropertyType, value, out value)) { throw new ArgumentException(string.Format( "Invalid value for Property '{0}': '{1}' ({2})", diff --git a/src/Avalonia.Base/AvaloniaProperty.cs b/src/Avalonia.Base/AvaloniaProperty.cs index 61006b1173..fb78e3b2a0 100644 --- a/src/Avalonia.Base/AvaloniaProperty.cs +++ b/src/Avalonia.Base/AvaloniaProperty.cs @@ -476,7 +476,7 @@ namespace Avalonia /// True if the value is valid, otherwise false. public bool IsValidValue(object value) { - return TypeUtilities.TryCast(PropertyType, value, out value); + return TypeUtilities.TryConvertImplicit(PropertyType, value, out value); } /// diff --git a/src/Avalonia.Base/IPriorityValueOwner.cs b/src/Avalonia.Base/IPriorityValueOwner.cs index 57f98c0717..aeec720920 100644 --- a/src/Avalonia.Base/IPriorityValueOwner.cs +++ b/src/Avalonia.Base/IPriorityValueOwner.cs @@ -25,5 +25,10 @@ namespace Avalonia /// The source of the change. /// The notification. void BindingNotificationReceived(PriorityValue sender, BindingNotification notification); + + /// + /// Ensures that the current thread is the UI thread. + /// + void VerifyAccess(); } } diff --git a/src/Avalonia.Base/PriorityBindingEntry.cs b/src/Avalonia.Base/PriorityBindingEntry.cs index 25b7bede7e..eb7cf5414c 100644 --- a/src/Avalonia.Base/PriorityBindingEntry.cs +++ b/src/Avalonia.Base/PriorityBindingEntry.cs @@ -92,6 +92,8 @@ namespace Avalonia private void ValueChanged(object value) { + _owner.Owner.Owner?.VerifyAccess(); + var notification = value as BindingNotification; if (notification != null) diff --git a/src/Avalonia.Base/PriorityLevel.cs b/src/Avalonia.Base/PriorityLevel.cs index 122a6df821..b25247deaf 100644 --- a/src/Avalonia.Base/PriorityLevel.cs +++ b/src/Avalonia.Base/PriorityLevel.cs @@ -33,7 +33,6 @@ namespace Avalonia /// internal class PriorityLevel { - private PriorityValue _owner; private object _directValue; private int _nextIndex; @@ -48,13 +47,18 @@ namespace Avalonia { Contract.Requires(owner != null); - _owner = owner; + Owner = owner; Priority = priority; Value = _directValue = AvaloniaProperty.UnsetValue; ActiveBindingIndex = -1; Bindings = new LinkedList(); } + /// + /// Gets the owner of the level. + /// + public PriorityValue Owner { get; } + /// /// Gets the priority of this level. /// @@ -73,7 +77,7 @@ namespace Avalonia set { Value = _directValue = value; - _owner.LevelValueChanged(this); + Owner.LevelValueChanged(this); } } @@ -131,7 +135,7 @@ namespace Avalonia { Value = entry.Value; ActiveBindingIndex = entry.Index; - _owner.LevelValueChanged(this); + Owner.LevelValueChanged(this); } else { @@ -161,7 +165,7 @@ namespace Avalonia /// The error. public void Error(PriorityBindingEntry entry, BindingNotification error) { - _owner.LevelError(this, error); + Owner.LevelError(this, error); } /// @@ -175,14 +179,14 @@ namespace Avalonia { Value = binding.Value; ActiveBindingIndex = binding.Index; - _owner.LevelValueChanged(this); + Owner.LevelValueChanged(this); return; } } Value = DirectValue; ActiveBindingIndex = -1; - _owner.LevelValueChanged(this); + Owner.LevelValueChanged(this); } } } diff --git a/src/Avalonia.Base/PriorityValue.cs b/src/Avalonia.Base/PriorityValue.cs index 3f4b405de9..21467f3962 100644 --- a/src/Avalonia.Base/PriorityValue.cs +++ b/src/Avalonia.Base/PriorityValue.cs @@ -26,7 +26,6 @@ namespace Avalonia /// internal class PriorityValue { - private readonly IPriorityValueOwner _owner; private readonly Type _valueType; private readonly SingleOrDictionary _levels = new SingleOrDictionary(); private object _value; @@ -45,7 +44,7 @@ namespace Avalonia Type valueType, Func validate = null) { - _owner = owner; + Owner = owner; Property = property; _valueType = valueType; _value = AvaloniaProperty.UnsetValue; @@ -53,6 +52,11 @@ namespace Avalonia _validate = validate; } + /// + /// Gets the owner of the value. + /// + public IPriorityValueOwner Owner { get; } + /// /// Gets the property that the value represents. /// @@ -188,9 +192,9 @@ namespace Avalonia Logger.Log( LogEventLevel.Error, LogArea.Binding, - _owner, + Owner, "Error in binding to {Target}.{Property}: {Message}", - _owner, + Owner, Property, error.Error.Message); } @@ -245,7 +249,7 @@ namespace Avalonia value = (notification.HasValue) ? notification.Value : null; } - if (TypeUtilities.TryCast(_valueType, value, out castValue)) + if (TypeUtilities.TryConvertImplicit(_valueType, value, out castValue)) { var old = _value; @@ -264,19 +268,19 @@ namespace Avalonia if (notification == null || notification.HasValue) { - _owner?.Changed(this, old, _value); + Owner?.Changed(this, old, _value); } if (notification != null) { - _owner?.BindingNotificationReceived(this, notification); + Owner?.BindingNotificationReceived(this, notification); } } else { Logger.Error( LogArea.Binding, - _owner, + Owner, "Binding produced invalid value for {$Property} ({$PropertyType}): {$Value} ({$ValueType})", Property.Name, _valueType, diff --git a/src/Avalonia.Base/Properties/AssemblyInfo.cs b/src/Avalonia.Base/Properties/AssemblyInfo.cs index f57afcdd70..2ee7378413 100644 --- a/src/Avalonia.Base/Properties/AssemblyInfo.cs +++ b/src/Avalonia.Base/Properties/AssemblyInfo.cs @@ -6,4 +6,5 @@ using System.Runtime.CompilerServices; [assembly: AssemblyTitle("Avalonia.Base")] [assembly: InternalsVisibleTo("Avalonia.Base.UnitTests")] +[assembly: InternalsVisibleTo("Avalonia.UnitTests")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] \ No newline at end of file diff --git a/src/Avalonia.Base/Threading/Dispatcher.cs b/src/Avalonia.Base/Threading/Dispatcher.cs index aee6a02e73..d46b7142f4 100644 --- a/src/Avalonia.Base/Threading/Dispatcher.cs +++ b/src/Avalonia.Base/Threading/Dispatcher.cs @@ -15,10 +15,10 @@ namespace Avalonia.Threading /// In Avalonia, there is usually only a single in the application - /// the one for the UI thread, retrieved via the property. /// - public class Dispatcher + public class Dispatcher : IDispatcher { - private readonly IPlatformThreadingInterface _platform; private readonly JobRunner _jobRunner; + private IPlatformThreadingInterface _platform; public static Dispatcher UIThread { get; } = new Dispatcher(AvaloniaLocator.Current.GetService()); @@ -26,22 +26,31 @@ namespace Avalonia.Threading public Dispatcher(IPlatformThreadingInterface platform) { _platform = platform; - if(_platform == null) - //TODO: Unit test mode, fix that somehow - return; _jobRunner = new JobRunner(platform); - _platform.Signaled += _jobRunner.RunJobs; + + if (_platform != null) + { + _platform.Signaled += _jobRunner.RunJobs; + } } + /// + /// Checks that the current thread is the UI thread. + /// public bool CheckAccess() => _platform?.CurrentThreadIsLoopThread ?? true; + /// + /// Checks that the current thread is the UI thread and throws if not. + /// + /// + /// The current thread is not the UI thread. + /// public void VerifyAccess() { if (!CheckAccess()) throw new InvalidOperationException("Call from invalid thread"); } - /// /// Runs the dispatcher's main loop. /// @@ -63,25 +72,35 @@ namespace Avalonia.Threading _jobRunner?.RunJobs(); } - /// - /// Invokes a method on the dispatcher thread. - /// - /// The method. - /// The priority with which to invoke the method. - /// A task that can be used to track the method's execution. + /// public Task InvokeTaskAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal) { return _jobRunner?.InvokeAsync(action, priority); } - /// - /// Post action that will be invoked on main thread - /// - /// The method. - /// The priority with which to invoke the method. + /// public void InvokeAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal) { _jobRunner?.Post(action, priority); } + + /// + /// Allows unit tests to change the platform threading interface. + /// + internal void UpdateServices() + { + if (_platform != null) + { + _platform.Signaled -= _jobRunner.RunJobs; + } + + _platform = AvaloniaLocator.Current.GetService(); + _jobRunner.UpdateServices(); + + if (_platform != null) + { + _platform.Signaled += _jobRunner.RunJobs; + } + } } } \ No newline at end of file diff --git a/src/Avalonia.Base/Threading/IDispatcher.cs b/src/Avalonia.Base/Threading/IDispatcher.cs new file mode 100644 index 0000000000..6301015a9a --- /dev/null +++ b/src/Avalonia.Base/Threading/IDispatcher.cs @@ -0,0 +1,39 @@ +using System; +using System.Threading.Tasks; + +namespace Avalonia.Threading +{ + /// + /// Dispatches jobs to a thread. + /// + public interface IDispatcher + { + /// + /// Determines whether the calling thread is the thread associated with this . + /// + /// True if he calling thread is the thread associated with the dispatched, otherwise false. + bool CheckAccess(); + + /// + /// Throws an exception if the calling thread is not the thread associated with this . + /// + void VerifyAccess(); + + /// + /// Invokes a method on the dispatcher thread. + /// + /// The method. + /// The priority with which to invoke the method. + /// A task that can be used to track the method's execution. + void InvokeAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal); + + /// + /// Post action that will be invoked on main thread + /// + /// The method. + /// The priority with which to invoke the method. + // TODO: The naming of this method is confusing: the Async suffix usually means return a task. + // Remove this and rename InvokeTaskAsync as InvokeAsync. See #816. + Task InvokeTaskAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal); + } +} \ No newline at end of file diff --git a/src/Avalonia.Base/Threading/JobRunner.cs b/src/Avalonia.Base/Threading/JobRunner.cs index 655ef34288..e212cd9a2e 100644 --- a/src/Avalonia.Base/Threading/JobRunner.cs +++ b/src/Avalonia.Base/Threading/JobRunner.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using Avalonia.Platform; @@ -14,8 +13,8 @@ namespace Avalonia.Threading /// internal class JobRunner { - private readonly IPlatformThreadingInterface _platform; private readonly Queue _queue = new Queue(); + private IPlatformThreadingInterface _platform; public JobRunner(IPlatformThreadingInterface platform) { @@ -82,6 +81,14 @@ namespace Avalonia.Threading AddJob(new Job(action, priority, true)); } + /// + /// Allows unit tests to change the platform threading interface. + /// + internal void UpdateServices() + { + _platform = AvaloniaLocator.Current.GetService(); + } + private void AddJob(Job job) { var needWake = false; @@ -91,7 +98,7 @@ namespace Avalonia.Threading _queue.Enqueue(job); } if (needWake) - _platform.Signal(); + _platform?.Signal(); } /// diff --git a/src/Avalonia.Base/Utilities/TypeUtilities.cs b/src/Avalonia.Base/Utilities/TypeUtilities.cs index 7295bfa7ab..dd93811498 100644 --- a/src/Avalonia.Base/Utilities/TypeUtilities.cs +++ b/src/Avalonia.Base/Utilities/TypeUtilities.cs @@ -14,17 +14,61 @@ namespace Avalonia.Utilities /// public static class TypeUtilities { - private static readonly Dictionary> Conversions = new Dictionary>() + private static int[] Conversions = { - { typeof(decimal), new List { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(char) } }, - { typeof(double), new List { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(char), typeof(float) } }, - { typeof(float), new List { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(char), typeof(float) } }, - { typeof(ulong), new List { typeof(byte), typeof(ushort), typeof(uint), typeof(char) } }, - { typeof(long), new List { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(char) } }, - { typeof(uint), new List { typeof(byte), typeof(ushort), typeof(char) } }, - { typeof(int), new List { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(char) } }, - { typeof(ushort), new List { typeof(byte), typeof(char) } }, - { typeof(short), new List { typeof(byte) } } + 0b101111111111101, // Boolean + 0b100001111111110, // Char + 0b101111111111111, // SByte + 0b101111111111111, // Byte + 0b101111111111111, // Int16 + 0b101111111111111, // UInt16 + 0b101111111111111, // Int32 + 0b101111111111111, // UInt32 + 0b101111111111111, // Int64 + 0b101111111111111, // UInt64 + 0b101111111111101, // Single + 0b101111111111101, // Double + 0b101111111111101, // Decimal + 0b110000000000000, // DateTime + 0b111111111111111, // String + }; + + private static int[] ImplicitConversions = + { + 0b000000000000001, // Boolean + 0b001110111100010, // Char + 0b001110101010100, // SByte + 0b001111111111000, // Byte + 0b001110101010000, // Int16 + 0b001111111100000, // UInt16 + 0b001110101000000, // Int32 + 0b001111110000000, // UInt32 + 0b001110100000000, // Int64 + 0b001111000000000, // UInt64 + 0b000110000000000, // Single + 0b000100000000000, // Double + 0b001000000000000, // Decimal + 0b010000000000000, // DateTime + 0b100000000000000, // String + }; + + private static Type[] InbuiltTypes = + { + typeof(Boolean), + typeof(Char), + typeof(SByte), + typeof(Byte), + typeof(Int16), + typeof(UInt16), + typeof(Int32), + typeof(UInt32), + typeof(Int64), + typeof(UInt64), + typeof(Single), + typeof(Double), + typeof(Decimal), + typeof(DateTime), + typeof(String), }; private static readonly Type[] NumericTypes = new[] @@ -54,49 +98,104 @@ namespace Avalonia.Utilities } /// - /// Try to cast a value to a type, using implicit conversions if possible. + /// Try to convert a value to a type by any means possible. /// /// The type to cast to. /// The value to cast. + /// The culture to use. /// If sucessful, contains the cast value. /// True if the cast was sucessful, otherwise false. - public static bool TryCast(Type to, object value, out object result) + public static bool TryConvert(Type to, object value, CultureInfo culture, out object result) { - Contract.Requires(to != null); - if (value == null) { result = null; return AcceptsNull(to); } - var from = value.GetType(); - if (value == AvaloniaProperty.UnsetValue) { result = value; return true; } - else if (to.GetTypeInfo().IsAssignableFrom(from.GetTypeInfo())) + + var from = value.GetType(); + var fromTypeInfo = from.GetTypeInfo(); + var toTypeInfo = to.GetTypeInfo(); + + if (toTypeInfo.IsAssignableFrom(fromTypeInfo)) { result = value; return true; } - else if (Conversions.ContainsKey(to) && Conversions[to].Contains(from)) + + if (to == typeof(string)) { - result = Convert.ChangeType(value, to); + result = Convert.ToString(value); return true; } - else + + if (toTypeInfo.IsEnum && from == typeof(string)) + { + if (Enum.IsDefined(to, (string)value)) + { + result = Enum.Parse(to, (string)value); + return true; + } + } + + if (!fromTypeInfo.IsEnum && toTypeInfo.IsEnum) { - var cast = from.GetRuntimeMethods() - .FirstOrDefault(m => m.Name == "op_Implicit" && m.ReturnType == to); + result = null; + + if (TryConvert(Enum.GetUnderlyingType(to), value, culture, out object enumValue)) + { + result = Enum.ToObject(to, enumValue); + return true; + } + } - if (cast != null) + if (fromTypeInfo.IsEnum && IsNumeric(to)) + { + try { - result = cast.Invoke(null, new[] { value }); + result = Convert.ChangeType((int)value, to, culture); return true; } + catch + { + result = null; + return false; + } + } + + var convertableFrom = Array.IndexOf(InbuiltTypes, from); + var convertableTo = Array.IndexOf(InbuiltTypes, to); + + if (convertableFrom != -1 && convertableTo != -1) + { + if ((Conversions[convertableFrom] & 1 << convertableTo) != 0) + { + try + { + result = Convert.ChangeType(value, to, culture); + return true; + } + catch + { + result = null; + return false; + } + } + } + + var cast = from.GetRuntimeMethods() + .FirstOrDefault(m => (m.Name == "op_Implicit" || m.Name == "op_Explicit") && m.ReturnType == to); + + if (cast != null) + { + result = cast.Invoke(null, new[] { value }); + return true; } result = null; @@ -104,15 +203,14 @@ namespace Avalonia.Utilities } /// - /// Try to convert a value to a type, using if possible, - /// otherwise using . + /// Try to convert a value to a type using the implicit conversions allowed by the C# + /// language. /// /// The type to cast to. /// The value to cast. - /// The culture to use. /// If sucessful, contains the cast value. /// True if the cast was sucessful, otherwise false. - public static bool TryConvert(Type to, object value, CultureInfo culture, out object result) + public static bool TryConvertImplicit(Type to, object value, out object result) { if (value == null) { @@ -120,54 +218,44 @@ namespace Avalonia.Utilities return AcceptsNull(to); } - var from = value.GetType(); - if (value == AvaloniaProperty.UnsetValue) { result = value; return true; } - if (to.GetTypeInfo().IsAssignableFrom(from.GetTypeInfo())) - { - result = value; - return true; - } + var from = value.GetType(); + var fromTypeInfo = from.GetTypeInfo(); + var toTypeInfo = to.GetTypeInfo(); - if (to == typeof(string)) + if (toTypeInfo.IsAssignableFrom(fromTypeInfo)) { - result = Convert.ToString(value); + result = value; return true; } - if (to.GetTypeInfo().IsEnum && from == typeof(string)) - { - if (Enum.IsDefined(to, (string)value)) - { - result = Enum.Parse(to, (string)value); - return true; - } - } - - bool containsFrom = Conversions.ContainsKey(from); - bool containsTo = Conversions.ContainsKey(to); + var convertableFrom = Array.IndexOf(InbuiltTypes, from); + var convertableTo = Array.IndexOf(InbuiltTypes, to); - if ((containsFrom && containsTo) || (from == typeof(string) && containsTo)) + if (convertableFrom != -1 && convertableTo != -1) { - try - { - result = Convert.ChangeType(value, to, culture); - return true; - } - catch + if ((ImplicitConversions[convertableFrom] & 1 << convertableTo) != 0) { - result = null; - return false; + try + { + result = Convert.ChangeType(value, to, CultureInfo.InvariantCulture); + return true; + } + catch + { + result = null; + return false; + } } } var cast = from.GetRuntimeMethods() - .FirstOrDefault(m => (m.Name == "op_Implicit" || m.Name == "op_Explicit") && m.ReturnType == to); + .FirstOrDefault(m => m.Name == "op_Implicit" && m.ReturnType == to); if (cast != null) { @@ -180,29 +268,28 @@ namespace Avalonia.Utilities } /// - /// Casts a value to a type, returning the default for that type if the value could not be - /// cast. + /// Convert a value to a type by any means possible, returning the default for that type + /// if the value could not be converted. /// /// The value to cast. /// The type to cast to.. + /// The culture to use. /// A value of . - public static object CastOrDefault(object value, Type type) + public static object ConvertOrDefault(object value, Type type, CultureInfo culture) { - var typeInfo = type.GetTypeInfo(); - object result; + return TryConvert(type, value, culture, out object result) ? result : Default(type); + } - if (TypeUtilities.TryCast(type, value, out result)) - { - return result; - } - else if (typeInfo.IsValueType) - { - return Activator.CreateInstance(type); - } - else - { - return null; - } + /// + /// Convert a value to a type using the implicit conversions allowed by the C# language or + /// return the default for the type if the value could not be converted. + /// + /// The value to cast. + /// The type to cast to.. + /// A value of . + public static object ConvertImplicitOrDefault(object value, Type type) + { + return TryConvertImplicit(type, value, out object result) ? result : Default(type); } /// diff --git a/src/Avalonia.Base/packages.config b/src/Avalonia.Base/packages.config deleted file mode 100644 index c372c92f3f..0000000000 --- a/src/Avalonia.Base/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index f12f07070e..37f348340c 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -1,22 +1,7 @@ - - - + - 11.0 - Debug - AnyCPU - {D2221C82-4A25-4583-9B43-D791E3F6820C} - Library - Properties - Avalonia.Controls - Avalonia.Controls - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 - - + netstandard1.1 + false true @@ -44,237 +29,16 @@ Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ..\..\packages\JetBrains.Annotations.10.0.0\lib\portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\JetBrains.Annotations.PCL328.dll - True - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.1\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.0\System.Reactive.PlatformServices.dll - True - + + + + + + + - - - - - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {62024B2D-53EB-4638-B26B-85EEAA54866E} - Avalonia.Input - - - {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B} - Avalonia.Interactivity - - - {42472427-4774-4C81-8AFF-9F27B8E31721} - Avalonia.Layout - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - - - {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F} - Avalonia.Styling - - - - - + + \ No newline at end of file diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index 8f617466ed..24daa545ba 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -226,7 +226,7 @@ namespace Avalonia.Controls } /// - protected override void OnPointerReleased(PointerEventArgs e) + protected override void OnPointerReleased(PointerReleasedEventArgs e) { base.OnPointerReleased(e); diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs index cc23c187bc..6815988288 100644 --- a/src/Avalonia.Controls/Control.cs +++ b/src/Avalonia.Controls/Control.cs @@ -17,7 +17,9 @@ using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Logging; using Avalonia.LogicalTree; +using Avalonia.Rendering; using Avalonia.Styling; +using Avalonia.VisualTree; namespace Avalonia.Controls { @@ -33,7 +35,7 @@ namespace Avalonia.Controls /// - Implements to allow styling to work on the control. /// - Implements to form part of a logical tree. /// - public class Control : InputElement, IControl, INamed, ISetInheritanceParent, ISetLogicalParent, ISupportInitialize + public class Control : InputElement, IControl, INamed, ISetInheritanceParent, ISetLogicalParent, ISupportInitialize, IVisualBrushInitialize { /// /// Defines the property. @@ -470,6 +472,38 @@ namespace Avalonia.Controls InheritanceParent = parent; } + /// + void IVisualBrushInitialize.EnsureInitialized() + { + if (VisualRoot == null) + { + if (!IsInitialized) + { + foreach (var i in this.GetSelfAndVisualDescendents()) + { + var c = i as IControl; + + if (c?.IsInitialized == false) + { + var init = c as ISupportInitialize; + + if (init != null) + { + init.BeginInit(); + init.EndInit(); + } + } + } + } + + if (!IsArrangeValid) + { + Measure(Size.Infinity); + Arrange(new Rect(DesiredSize)); + } + } + } + /// /// Adds a pseudo-class to be set when a property is true. /// diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index 39759f78f1..a2b5f3f8b4 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -127,11 +127,11 @@ namespace Avalonia.Controls.Presenters base.Render(context); if (selectionStart == selectionEnd) - { + { var backgroundColor = (((Control)TemplatedParent).GetValue(BackgroundProperty) as SolidColorBrush)?.Color; var caretBrush = Brushes.Black; - if(backgroundColor.HasValue) + if (backgroundColor.HasValue) { byte red = (byte)~(backgroundColor.Value.R); byte green = (byte)~(backgroundColor.Value.G); @@ -139,7 +139,7 @@ namespace Avalonia.Controls.Presenters caretBrush = new SolidColorBrush(Color.FromRgb(red, green, blue)); } - + if (_caretBlink) { var charPos = FormattedText.HitTestTextPosition(CaretIndex); @@ -212,7 +212,10 @@ namespace Avalonia.Controls.Presenters if (length > 0) { - result.SetForegroundBrush(Brushes.White, start, length); + result.Spans = new[] + { + new FormattedTextStyleSpan(start, length, foregroundBrush: Brushes.White), + }; } return result; @@ -228,17 +231,13 @@ namespace Avalonia.Controls.Presenters } else { - // TODO: Pretty sure that measuring "X" isn't the right way to do this... - using (var formattedText = new FormattedText( - "X", - FontFamily, - FontSize, - FontStyle, - TextAlignment, - FontWeight)) + return new FormattedText { - return formattedText.Measure(); - } + Text = "X", + Typeface = new Typeface(FontFamily, FontSize, FontStyle, FontWeight), + TextAlignment = TextAlignment, + Constraint = availableSize, + }.Measure(); } } diff --git a/src/Avalonia.Controls/Primitives/AccessText.cs b/src/Avalonia.Controls/Primitives/AccessText.cs index 42a6f9123b..4bb80e6d3f 100644 --- a/src/Avalonia.Controls/Primitives/AccessText.cs +++ b/src/Avalonia.Controls/Primitives/AccessText.cs @@ -85,15 +85,14 @@ namespace Avalonia.Controls.Primitives /// A object. protected override FormattedText CreateFormattedText(Size constraint) { - var result = new FormattedText( - StripAccessKey(Text), - FontFamily, - FontSize, - FontStyle, - TextAlignment, - FontWeight); - result.Constraint = constraint; - return result; + return new FormattedText + { + Constraint = constraint, + Typeface = new Typeface(FontFamily, FontSize, FontStyle, FontWeight), + Text = StripAccessKey(Text), + TextAlignment = TextAlignment, + Wrapping = TextWrapping, + }; } /// diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs index 5e5177b29d..86c1b47521 100644 --- a/src/Avalonia.Controls/Primitives/PopupRoot.cs +++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs @@ -70,32 +70,12 @@ namespace Avalonia.Controls.Primitives this.PlatformImpl.Dispose(); } - /// - /// Hides the popup. - /// - public void Hide() - { - PlatformImpl.Hide(); - IsVisible = false; - } - - /// - /// Shows the popup. - /// - public void Show() - { - EnsureInitialized(); - PlatformImpl.Show(); - LayoutManager.Instance.ExecuteInitialLayoutPass(this); - IsVisible = true; - } - /// protected override void OnTemplateApplied(TemplateAppliedEventArgs e) { base.OnTemplateApplied(e); - if (Parent.TemplatedParent != null) + if (Parent?.TemplatedParent != null) { if (_presenterSubscription != null) { @@ -109,16 +89,6 @@ namespace Avalonia.Controls.Primitives } } - private void EnsureInitialized() - { - if (!this.IsInitialized) - { - var init = (ISupportInitialize)this; - init.BeginInit(); - init.EndInit(); - } - } - private void SetTemplatedParentAndApplyChildTemplates(IControl control) { var templatedParent = Parent.TemplatedParent; diff --git a/src/Avalonia.Controls/Primitives/Thumb.cs b/src/Avalonia.Controls/Primitives/Thumb.cs index 1fef48f55b..065b1aedbe 100644 --- a/src/Avalonia.Controls/Primitives/Thumb.cs +++ b/src/Avalonia.Controls/Primitives/Thumb.cs @@ -86,7 +86,7 @@ namespace Avalonia.Controls.Primitives RaiseEvent(ev); } - protected override void OnPointerReleased(PointerEventArgs e) + protected override void OnPointerReleased(PointerReleasedEventArgs e) { if (_lastPoint.HasValue) { diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs index 028df729a5..c7a77bdf0e 100644 --- a/src/Avalonia.Controls/TextBlock.cs +++ b/src/Avalonia.Controls/TextBlock.cs @@ -116,7 +116,7 @@ namespace Avalonia.Controls this.GetObservable(TextAlignmentProperty).Select(_ => Unit.Default), this.GetObservable(FontSizeProperty).Select(_ => Unit.Default), this.GetObservable(FontStyleProperty).Select(_ => Unit.Default), - this.GetObservable(FontWeightProperty).Select(_=>Unit.Default)) + this.GetObservable(FontWeightProperty).Select(_ => Unit.Default)) .Subscribe(_ => { InvalidateFormattedText(); @@ -350,16 +350,14 @@ namespace Avalonia.Controls /// A object. protected virtual FormattedText CreateFormattedText(Size constraint) { - var result = new FormattedText( - Text ?? string.Empty, - FontFamily, - FontSize, - FontStyle, - TextAlignment, - FontWeight, - TextWrapping); - result.Constraint = constraint; - return result; + return new FormattedText + { + Constraint = constraint, + Typeface = new Typeface(FontFamily, FontSize, FontStyle, FontWeight), + Text = Text ?? string.Empty, + TextAlignment = TextAlignment, + Wrapping = TextWrapping, + }; } /// @@ -370,7 +368,6 @@ namespace Avalonia.Controls if (_formattedText != null) { _constraint = _formattedText.Constraint; - _formattedText.Dispose(); _formattedText = null; } diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 719e888dd4..9748e5e772 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -522,7 +522,7 @@ namespace Avalonia.Controls } } - protected override void OnPointerReleased(PointerEventArgs e) + protected override void OnPointerReleased(PointerReleasedEventArgs e) { if (_presenter != null && e.Device.Captured == _presenter) { diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 4de0256a7d..f3a6ab92d0 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -96,10 +96,10 @@ namespace Avalonia.Controls PlatformImpl.Closed = HandleClosed; PlatformImpl.Input = HandleInput; - PlatformImpl.Paint = Renderer != null ? (Action)Renderer.Render : null; + PlatformImpl.Paint = HandlePaint; PlatformImpl.Resized = HandleResized; PlatformImpl.ScalingChanged = HandleScalingChanged; - + _keyboardNavigationHandler?.SetOwner(this); _accessKeyHandler?.SetOwner(this); @@ -184,8 +184,10 @@ namespace Avalonia.Controls get { return AvaloniaLocator.Current.GetService(); } } + IRenderTarget IRenderRoot.CreateRenderTarget() => CreateRenderTarget(); + /// - IRenderTarget IRenderRoot.CreateRenderTarget() + protected virtual IRenderTarget CreateRenderTarget() { return _renderInterface.CreateRenderTarget(PlatformImpl.Surfaces); } @@ -208,6 +210,25 @@ namespace Avalonia.Controls return PlatformImpl.PointToScreen(p); } + /// + /// Handles a paint notification from . + /// + /// The dirty area. + protected virtual void HandlePaint(Rect rect) + { + Renderer?.Paint(rect); + } + + /// + /// Handles a closed notification from . + /// + protected virtual void HandleClosed() + { + Closed?.Invoke(this, EventArgs.Empty); + Renderer?.Dispose(); + Renderer = null; + _applicationLifecycle.OnExit -= OnApplicationExiting; + } /// /// Handles a resize notification from . @@ -219,7 +240,7 @@ namespace Avalonia.Controls Width = clientSize.Width; Height = clientSize.Height; LayoutManager.Instance.ExecuteLayoutPass(); - PlatformImpl.Invalidate(new Rect(clientSize)); + Renderer?.Resized(clientSize); } /// @@ -267,17 +288,6 @@ namespace Avalonia.Controls return result; } - /// - /// Handles a closed notification from . - /// - private void HandleClosed() - { - Closed?.Invoke(this, EventArgs.Empty); - Renderer?.Dispose(); - Renderer = null; - _applicationLifecycle.OnExit -= OnApplicationExiting; - } - private void OnApplicationExiting(object sender, EventArgs args) { HandleApplicationExiting(); diff --git a/src/Avalonia.Controls/Utils/UndoRedoHelper.cs b/src/Avalonia.Controls/Utils/UndoRedoHelper.cs index 71ba3793d1..be4c1aa6c4 100644 --- a/src/Avalonia.Controls/Utils/UndoRedoHelper.cs +++ b/src/Avalonia.Controls/Utils/UndoRedoHelper.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using JetBrains.Annotations; using Avalonia.Utilities; namespace Avalonia.Controls.Utils diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 992279d981..75587dcaec 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -11,6 +11,7 @@ using Avalonia.Media; using Avalonia.Platform; using Avalonia.Styling; using System.Collections.Generic; +using System.Linq; namespace Avalonia.Controls { @@ -189,6 +190,7 @@ namespace Avalonia.Controls { s_windows.Remove(this); PlatformImpl.Dispose(); + IsVisible = false; } protected override void HandleApplicationExiting() @@ -215,22 +217,25 @@ namespace Avalonia.Controls /// /// Hides the window but does not close it. /// - public void Hide() + public override void Hide() { using (BeginAutoSizing()) { PlatformImpl.Hide(); } + + IsVisible = false; } /// /// Shows the window. /// - public void Show() + public override void Show() { s_windows.Add(this); EnsureInitialized(); + IsVisible = true; LayoutManager.Instance.ExecuteInitialLayoutPass(this); using (BeginAutoSizing()) @@ -264,18 +269,27 @@ namespace Avalonia.Controls s_windows.Add(this); EnsureInitialized(); + IsVisible = true; LayoutManager.Instance.ExecuteInitialLayoutPass(this); using (BeginAutoSizing()) { + var affectedWindows = s_windows.Where(w => w.IsEnabled && w != this).ToList(); + var activated = affectedWindows.Where(w => w.IsActive).FirstOrDefault(); + SetIsEnabled(affectedWindows, false); + var modal = PlatformImpl.ShowDialog(); var result = new TaskCompletionSource(); - Observable.FromEventPattern(this, nameof(Closed)) + Observable.FromEventPattern( + x => this.Closed += x, + x => this.Closed -= x) .Take(1) .Subscribe(_ => { modal.Dispose(); + SetIsEnabled(affectedWindows, true); + activated?.Activate(); result.SetResult((TResult)_dialogResult); }); @@ -283,6 +297,14 @@ namespace Avalonia.Controls } } + void SetIsEnabled(IEnumerable windows, bool isEnabled) + { + foreach (var window in windows) + { + window.IsEnabled = isEnabled; + } + } + /// void INameScope.Register(string name, object element) { @@ -329,6 +351,12 @@ namespace Avalonia.Controls return size; } + protected override void HandleClosed() + { + IsVisible = false; + base.HandleClosed(); + } + /// protected override void HandleResized(Size clientSize) { @@ -339,16 +367,6 @@ namespace Avalonia.Controls base.HandleResized(clientSize); } - - private void EnsureInitialized() - { - if (!this.IsInitialized) - { - var init = (ISupportInitialize)this; - init.BeginInit(); - init.EndInit(); - } - } } } diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index ac6eea8641..21c248db0c 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -29,6 +29,13 @@ namespace Avalonia.Controls AvaloniaProperty.RegisterDirect(nameof(IsActive), o => o.IsActive); private bool _isActive; + private bool _ignoreVisibilityChange; + + static WindowBase() + { + IsVisibleProperty.OverrideDefaultValue(false); + IsVisibleProperty.Changed.AddClassHandler(x => x.IsVisibleChanged); + } public WindowBase(IWindowBaseImpl impl) : this(impl, AvaloniaLocator.Current) { @@ -59,7 +66,6 @@ namespace Avalonia.Controls public new IWindowBaseImpl PlatformImpl => (IWindowBaseImpl) base.PlatformImpl; - /// /// Gets a value that indicates whether the window is active. /// @@ -95,6 +101,43 @@ namespace Avalonia.Controls PlatformImpl.Activate(); } + /// + /// Hides the popup. + /// + public virtual void Hide() + { + _ignoreVisibilityChange = true; + + try + { + PlatformImpl.Hide(); + IsVisible = false; + } + finally + { + _ignoreVisibilityChange = false; + } + } + + /// + /// Shows the popup. + /// + public virtual void Show() + { + _ignoreVisibilityChange = true; + + try + { + EnsureInitialized(); + IsVisible = true; + LayoutManager.Instance.ExecuteInitialLayoutPass(this); + PlatformImpl.Show(); + } + finally + { + _ignoreVisibilityChange = false; + } + } /// /// Begins an auto-resize operation. @@ -126,6 +169,34 @@ namespace Avalonia.Controls return base.ArrangeOverride(PlatformImpl.ClientSize); } + /// + /// Ensures that the window is initialized. + /// + protected void EnsureInitialized() + { + if (!this.IsInitialized) + { + var init = (ISupportInitialize)this; + init.BeginInit(); + init.EndInit(); + } + } + + protected override void HandleClosed() + { + _ignoreVisibilityChange = true; + + try + { + IsVisible = false; + base.HandleClosed(); + } + finally + { + _ignoreVisibilityChange = false; + } + } + /// /// Handles a resize notification from . /// @@ -139,8 +210,7 @@ namespace Avalonia.Controls } ClientSize = clientSize; LayoutManager.Instance.ExecuteLayoutPass(); - PlatformImpl.Invalidate(new Rect(clientSize)); - + Renderer?.Resized(clientSize); } /// @@ -180,6 +250,21 @@ namespace Avalonia.Controls Deactivated?.Invoke(this, EventArgs.Empty); } + private void IsVisibleChanged(AvaloniaPropertyChangedEventArgs e) + { + if (!_ignoreVisibilityChange) + { + if ((bool)e.NewValue) + { + Show(); + } + else + { + Hide(); + } + } + } + /// /// Starts moving a window with left button being held. Should be called from left mouse button press event handler /// diff --git a/src/Avalonia.Controls/packages.config b/src/Avalonia.Controls/packages.config deleted file mode 100644 index c372c92f3f..0000000000 --- a/src/Avalonia.Controls/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj b/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj index d9174d6f36..be0b98b24c 100644 --- a/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj +++ b/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj @@ -1,22 +1,7 @@ - - - + - 11.0 - Debug - AnyCPU - {799A7BB5-3C2C-48B6-85A7-406A12C420DA} - Library - Properties - Avalonia - Avalonia.DesignerSupport - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 - - + netstandard1.1 + false true @@ -40,87 +25,23 @@ CS1591 - - - {3e53a01a-b331-47f3-b828-4a5717e77a24} - Avalonia.Markup.Xaml - - - {6417e941-21bc-467b-a771-0de389353ce6} - Avalonia.Markup - - - {d211e587-d8bc-45b9-95a4-f297c8fa5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {D2221C82-4A25-4583-9B43-D791E3F6820C} - Avalonia.Controls - - - {62024B2D-53EB-4638-B26B-85EEAA54866E} - Avalonia.Input - - - {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B} - Avalonia.Interactivity - - - {42472427-4774-4C81-8AFF-9F27B8E31721} - Avalonia.Layout - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - - - {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F} - Avalonia.Styling - - - {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F} - Avalonia.Themes.Default - + + + + + + + + + + + Properties\SharedAssemblyInfo.cs - - - - - - - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.1\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.0\System.Reactive.PlatformServices.dll - True - - - - + + \ No newline at end of file diff --git a/src/Avalonia.DesignerSupport/packages.config b/src/Avalonia.DesignerSupport/packages.config deleted file mode 100644 index 9f732f1bcb..0000000000 --- a/src/Avalonia.DesignerSupport/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj index a56575dab7..a060827f27 100644 --- a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj +++ b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj @@ -1,22 +1,7 @@ - - - + - 11.0 - Debug - AnyCPU - {7062AE20-5DCC-4442-9645-8195BDECE63E} - Library - Properties - Avalonia.Diagnostics - Avalonia.Diagnostics - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 - - + netstandard1.1 + false true @@ -41,117 +26,30 @@ true - - - {3e53a01a-b331-47f3-b828-4a5717e77a24} - Avalonia.Markup.Xaml - - - {6417e941-21bc-467b-a771-0de389353ce6} - Avalonia.Markup - - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {D2221C82-4A25-4583-9B43-D791E3F6820C} - Avalonia.Controls - - - {62024B2D-53EB-4638-B26B-85EEAA54866E} - Avalonia.Input - - - {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B} - Avalonia.Interactivity - - - {42472427-4774-4C81-8AFF-9F27B8E31721} - Avalonia.Layout - - - {6417B24E-49C2-4985-8DB2-3AB9D898EC91} - Avalonia.ReactiveUI - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - - - {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F} - Avalonia.Styling - - - {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f} - Avalonia.Themes.Default - + + + + + + + + + + + + Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - - TreePageView.xaml + + %(Filename) - - DevTools.xaml - - - - - - - ..\..\packages\Splat.1.6.2\lib\Portable-net45+win+wpa81+wp80\Splat.dll - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.1\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.0\System.Reactive.PlatformServices.dll - True - - - - - - Designer - - + Designer - - + + \ No newline at end of file diff --git a/src/Avalonia.Diagnostics/ViewModels/ControlDetailsViewModel.cs b/src/Avalonia.Diagnostics/ViewModels/ControlDetailsViewModel.cs index 34cc32972c..0339d724f7 100644 --- a/src/Avalonia.Diagnostics/ViewModels/ControlDetailsViewModel.cs +++ b/src/Avalonia.Diagnostics/ViewModels/ControlDetailsViewModel.cs @@ -3,19 +3,19 @@ using System.Collections.Generic; using System.Linq; -using Avalonia.Controls; +using Avalonia.VisualTree; using ReactiveUI; namespace Avalonia.Diagnostics.ViewModels { internal class ControlDetailsViewModel : ReactiveObject { - public ControlDetailsViewModel(Control control) + public ControlDetailsViewModel(IVisual control) { - if (control != null) + if (control is AvaloniaObject avaloniaObject) { - Properties = AvaloniaPropertyRegistry.Instance.GetRegistered(control) - .Select(x => new PropertyDetails(control, x)) + Properties = AvaloniaPropertyRegistry.Instance.GetRegistered(avaloniaObject) + .Select(x => new PropertyDetails(avaloniaObject, x)) .OrderBy(x => x.IsAttached) .ThenBy(x => x.Name); } diff --git a/src/Avalonia.Diagnostics/ViewModels/TreeNode.cs b/src/Avalonia.Diagnostics/ViewModels/TreeNode.cs index f186304f7b..0b0b7a94fe 100644 --- a/src/Avalonia.Diagnostics/ViewModels/TreeNode.cs +++ b/src/Avalonia.Diagnostics/ViewModels/TreeNode.cs @@ -5,8 +5,8 @@ using System; using System.Collections.Specialized; using System.Reactive; using System.Reactive.Linq; -using Avalonia.Controls; using Avalonia.Styling; +using Avalonia.VisualTree; using ReactiveUI; namespace Avalonia.Diagnostics.ViewModels @@ -16,32 +16,35 @@ namespace Avalonia.Diagnostics.ViewModels private string _classes; private bool _isExpanded; - public TreeNode(Control control, TreeNode parent) + public TreeNode(IVisual visual, TreeNode parent) { - Control = control; Parent = parent; - Type = control.GetType().Name; + Type = visual.GetType().Name; + Visual = visual; - var classesChanged = Observable.FromEventPattern< - NotifyCollectionChangedEventHandler, - NotifyCollectionChangedEventArgs>( - x => control.Classes.CollectionChanged += x, - x => control.Classes.CollectionChanged -= x) - .TakeUntil(((IStyleable)control).StyleDetach); + if (visual is IStyleable styleable) + { + var classesChanged = Observable.FromEventPattern< + NotifyCollectionChangedEventHandler, + NotifyCollectionChangedEventArgs>( + x => styleable.Classes.CollectionChanged += x, + x => styleable.Classes.CollectionChanged -= x) + .TakeUntil(((IStyleable)styleable).StyleDetach); - classesChanged.Select(_ => Unit.Default) - .StartWith(Unit.Default) - .Subscribe(_ => - { - if (control.Classes.Count > 0) + classesChanged.Select(_ => Unit.Default) + .StartWith(Unit.Default) + .Subscribe(_ => { - Classes = "(" + string.Join(" ", control.Classes) + ")"; - } - else - { - Classes = string.Empty; - } - }); + if (styleable.Classes.Count > 0) + { + Classes = "(" + string.Join(" ", styleable.Classes) + ")"; + } + else + { + Classes = string.Empty; + } + }); + } } public IReadOnlyReactiveList Children @@ -56,7 +59,7 @@ namespace Avalonia.Diagnostics.ViewModels private set { this.RaiseAndSetIfChanged(ref _classes, value); } } - public Control Control + public IVisual Visual { get; } diff --git a/src/Avalonia.Diagnostics/ViewModels/TreePageViewModel.cs b/src/Avalonia.Diagnostics/ViewModels/TreePageViewModel.cs index 92be04a056..97bd971e74 100644 --- a/src/Avalonia.Diagnostics/ViewModels/TreePageViewModel.cs +++ b/src/Avalonia.Diagnostics/ViewModels/TreePageViewModel.cs @@ -18,7 +18,7 @@ namespace Avalonia.Diagnostics.ViewModels { Nodes = nodes; _details = this.WhenAnyValue(x => x.SelectedNode) - .Select(x => x != null ? new ControlDetailsViewModel(x.Control) : null) + .Select(x => x != null ? new ControlDetailsViewModel(x.Visual) : null) .ToProperty(this, x => x.Details); } @@ -79,7 +79,7 @@ namespace Avalonia.Diagnostics.ViewModels private TreeNode FindNode(TreeNode node, IControl control) { - if (node.Control == control) + if (node.Visual == control) { return node; } diff --git a/src/Avalonia.Diagnostics/ViewModels/VisualTreeNode.cs b/src/Avalonia.Diagnostics/ViewModels/VisualTreeNode.cs index d155572c14..f1b02a61c9 100644 --- a/src/Avalonia.Diagnostics/ViewModels/VisualTreeNode.cs +++ b/src/Avalonia.Diagnostics/ViewModels/VisualTreeNode.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using Avalonia.Controls; +using Avalonia.Styling; using Avalonia.VisualTree; using ReactiveUI; @@ -10,7 +11,7 @@ namespace Avalonia.Diagnostics.ViewModels internal class VisualTreeNode : TreeNode { public VisualTreeNode(IVisual visual, TreeNode parent) - : base((Control)visual, parent) + : base(visual, parent) { var host = visual as IVisualTreeHost; @@ -23,9 +24,9 @@ namespace Avalonia.Diagnostics.ViewModels Children = new ReactiveList(new[] { new VisualTreeNode(host.Root, this) }); } - if (Control != null) + if ((Visual is IStyleable styleable)) { - IsInTemplate = Control.TemplatedParent != null; + IsInTemplate = styleable.TemplatedParent != null; } } diff --git a/src/Avalonia.Diagnostics/Views/TreePage.xaml.cs b/src/Avalonia.Diagnostics/Views/TreePage.xaml.cs index 0a79aa90d7..7e4e5a8564 100644 --- a/src/Avalonia.Diagnostics/Views/TreePage.xaml.cs +++ b/src/Avalonia.Diagnostics/Views/TreePage.xaml.cs @@ -23,14 +23,14 @@ namespace Avalonia.Diagnostics.Views protected void AddAdorner(object sender, PointerEventArgs e) { var node = (TreeNode)((Control)sender).DataContext; - var layer = AdornerLayer.GetAdornerLayer(node.Control); + var layer = AdornerLayer.GetAdornerLayer(node.Visual); if (layer != null) { _adorner = new Rectangle { Fill = new SolidColorBrush(0x80a0c5e8), - [AdornerLayer.AdornedElementProperty] = node.Control, + [AdornerLayer.AdornedElementProperty] = node.Visual, }; layer.Children.Add(_adorner); diff --git a/src/Avalonia.Diagnostics/packages.config b/src/Avalonia.Diagnostics/packages.config deleted file mode 100644 index df107dc625..0000000000 --- a/src/Avalonia.Diagnostics/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj index 8a60d5d9c7..9d5436b2b9 100644 --- a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj +++ b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj @@ -1,21 +1,7 @@ - - - + - 14.0 - Debug - AnyCPU - {7863EA94-F0FB-4386-BF8C-E5BFA761560A} - Library - Properties - Avalonia.DotNetCoreRuntime - Avalonia.DotNetCoreRuntime - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - v5.0 + netcoreapp1.0 + false true @@ -36,54 +22,19 @@ 4 bin\Release\Avalonia.DotNetCoreRuntime.XML - - - - - SharedAssemblyInfo.cs + Properties\SharedAssemblyInfo.cs - - - - - - - {b09b78d8-9b26-48b0-9149-d64a2f120f3f} - Avalonia.Base - - - {d2221c82-4a25-4583-9b43-d791e3f6820c} - Avalonia.Controls - - - {eb582467-6abb-43a1-b052-e981ba910e3a} - Avalonia.Visuals - - - {bb1f7bb5-6ad4-4776-94d9-c09d0a972658} - Avalonia.Gtk3 - - - {7d2d3083-71dd-4cc9-8907-39a0d86fb322} - Avalonia.Skia.Desktop.NetStandard - - - {40759a76-d0f2-464e-8000-6ff0f5c4bd7c} - Avalonia.Win32.NetStandard - - + + + + + + + - - \ No newline at end of file diff --git a/src/Avalonia.DotNetCoreRuntime/NetCoreRuntimePlatform.cs b/src/Avalonia.DotNetCoreRuntime/NetCoreRuntimePlatform.cs index b131488109..6aab8e0243 100644 --- a/src/Avalonia.DotNetCoreRuntime/NetCoreRuntimePlatform.cs +++ b/src/Avalonia.DotNetCoreRuntime/NetCoreRuntimePlatform.cs @@ -5,6 +5,8 @@ using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; +using Microsoft.DotNet.PlatformAbstractions; +using Microsoft.Extensions.DependencyModel; namespace Avalonia.Shared.PlatformSupport { @@ -15,33 +17,26 @@ namespace Avalonia.Shared.PlatformSupport static Assembly[] LoadAssemblies() { + var assemblies = new List(); + // Mostly copy-pasted from (MIT): + // https://github.com/StefH/System.AppDomain.Core/blob/0b35e676c2721aa367b96e62eb52c97ee0b43a70/src/System.AppDomain.NetCoreApp/AppDomain.cs - var rv = new List(); - var entry = Assembly.GetEntryAssembly(); - rv.Add(entry); - var queue = new Queue(entry.GetReferencedAssemblies()); - var aset = new HashSet(queue.Select(r => r.ToString())); - - while (queue.Count > 0) + foreach (var assemblyName in + DependencyContext.Default.GetRuntimeAssemblyNames(RuntimeEnvironment.GetRuntimeIdentifier())) { - Assembly asm; try { - asm = Assembly.Load(queue.Dequeue()); - } - catch (Exception e) - { - Debug.Write(e.ToString()); - continue; + var assembly = Assembly.Load(assemblyName); + // just load all types and skip this assembly if one or more types cannot be resolved + assembly.DefinedTypes.ToArray(); + assemblies.Add(assembly); } - rv.Add(asm); - foreach (var r in asm.GetReferencedAssemblies()) + catch (Exception ex) { - if (aset.Add(r.ToString())) - queue.Enqueue(r); + Debug.Write(ex.Message); } } - return rv.Distinct().ToArray(); + return assemblies.ToArray(); } } } diff --git a/src/Avalonia.DotNetCoreRuntime/Properties/AssemblyInfo.cs b/src/Avalonia.DotNetCoreRuntime/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..51ec3975c9 --- /dev/null +++ b/src/Avalonia.DotNetCoreRuntime/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System.Reflection; + +[assembly: AssemblyTitle("Avalonia.DotNetCoreRuntime")] diff --git a/src/Avalonia.DotNetCoreRuntime/project.json b/src/Avalonia.DotNetCoreRuntime/project.json deleted file mode 100644 index d6ae90b33b..0000000000 --- a/src/Avalonia.DotNetCoreRuntime/project.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "supports": {}, - "dependencies": { - "Microsoft.NETCore.Portable.Compatibility": "1.0.1", - "NETStandard.Library": "1.6.0", - "System.Threading.ThreadPool": "4.3.0" - }, - "frameworks": { - "netstandard1.5": {} - } -} \ No newline at end of file diff --git a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj index e87ec0b5a7..b475c4b3ff 100644 --- a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj +++ b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj @@ -1,5 +1,5 @@  - + Debug @@ -36,14 +36,6 @@ - - ..\..\packages\System.Reactive.Core.3.0.0\lib\net45\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\net45\System.Reactive.Interfaces.dll - True - @@ -74,16 +66,8 @@ Avalonia.Styling - - - - + + \ No newline at end of file diff --git a/src/Avalonia.DotNetFrameworkRuntime/packages.config b/src/Avalonia.DotNetFrameworkRuntime/packages.config deleted file mode 100644 index 1e93a8c9e7..0000000000 --- a/src/Avalonia.DotNetFrameworkRuntime/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/Avalonia.HtmlRenderer/Adapters/GraphicsAdapter.cs b/src/Avalonia.HtmlRenderer/Adapters/GraphicsAdapter.cs index c9dd2a786c..93f8790741 100644 --- a/src/Avalonia.HtmlRenderer/Adapters/GraphicsAdapter.cs +++ b/src/Avalonia.HtmlRenderer/Adapters/GraphicsAdapter.cs @@ -117,7 +117,11 @@ namespace TheArtOfDev.HtmlRenderer.Avalonia.Adapters FormattedText GetText(string str, RFont font) { var f = ((FontAdapter)font); - return new FormattedText(str, f.Name, font.Size, f.FontStyle, TextAlignment.Left, f.Weight); + return new FormattedText + { + Text = str, + Typeface = new Typeface(f.Name, font.Size, f.FontStyle, f.Weight), + }; } public override void MeasureString(string str, RFont font, double maxWidth, out int charFit, out double charFitWidth) diff --git a/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj b/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj index 8f16bad64a..b1fc7a4278 100644 --- a/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj +++ b/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj @@ -1,22 +1,9 @@ - - - + - 10.0 - Debug - AnyCPU - {5FB2B005-0A7F-4DAD-ADD4-3ED01444E63D} - Library - Properties - Avalonia.HtmlRenderer - Avalonia.HtmlRenderer - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 - - + netstandard1.1 + False + False + false true @@ -36,7 +23,6 @@ 4 - @@ -51,6 +37,7 @@ + @@ -137,65 +124,14 @@ - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {D2221C82-4A25-4583-9B43-D791E3F6820C} - Avalonia.Controls - - - {62024B2D-53EB-4638-B26B-85EEAA54866E} - Avalonia.Input - - - {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B} - Avalonia.Interactivity - - - {42472427-4774-4C81-8AFF-9F27B8E31721} - Avalonia.Layout - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - - - {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F} - Avalonia.Styling - + + + + + + + + - - - - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + \ No newline at end of file diff --git a/src/Avalonia.HtmlRenderer/Compat/Api.cs b/src/Avalonia.HtmlRenderer/Compat/Api.cs new file mode 100644 index 0000000000..798b697277 --- /dev/null +++ b/src/Avalonia.HtmlRenderer/Compat/Api.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Net +{ + internal class AsyncCompletedEventArgs + { + public object UserState { get; set; } + public Exception Error { get; set; } + public bool Cancelled { get; set; } + + public AsyncCompletedEventArgs(Exception error, bool cancelled, object userState) + { + + } + } + + class WebException : Exception + { + public object Response { get; set; } + } + + class HttpWebResponse + { + public HttpStatusCode StatusCode { get; set; } + } +} diff --git a/src/Avalonia.HtmlRenderer/HtmlControl.cs b/src/Avalonia.HtmlRenderer/HtmlControl.cs index ca8dcec2e1..88a6e5fda4 100644 --- a/src/Avalonia.HtmlRenderer/HtmlControl.cs +++ b/src/Avalonia.HtmlRenderer/HtmlControl.cs @@ -413,7 +413,7 @@ namespace Avalonia.Controls.Html /// /// Handle mouse up to handle selection and link click. /// - protected override void OnPointerReleased(PointerEventArgs e) + protected override void OnPointerReleased(PointerReleasedEventArgs e) { base.OnPointerReleased(e); LeftMouseButton = false; diff --git a/src/Avalonia.HtmlRenderer/packages.config b/src/Avalonia.HtmlRenderer/packages.config deleted file mode 100644 index b6a9c7823c..0000000000 --- a/src/Avalonia.HtmlRenderer/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Input/Avalonia.Input.csproj b/src/Avalonia.Input/Avalonia.Input.csproj index c1ed34c1c7..e9e74e24fe 100644 --- a/src/Avalonia.Input/Avalonia.Input.csproj +++ b/src/Avalonia.Input/Avalonia.Input.csproj @@ -1,22 +1,7 @@ - - - + - 11.0 - Debug - AnyCPU - {62024B2D-53EB-4638-B26B-85EEAA54866E} - Library - Properties - Avalonia.Input - Avalonia.Input - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 - - + netstandard1.1 + false true @@ -41,109 +26,16 @@ true - - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B} - Avalonia.Interactivity - - - {42472427-4774-4C81-8AFF-9F27B8E31721} - Avalonia.Layout - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - + + + + + Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.1\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.0\System.Reactive.PlatformServices.dll - True - - - - + \ No newline at end of file diff --git a/src/Avalonia.Input/IInputElement.cs b/src/Avalonia.Input/IInputElement.cs index 72f03d3ae5..5acb6aa777 100644 --- a/src/Avalonia.Input/IInputElement.cs +++ b/src/Avalonia.Input/IInputElement.cs @@ -1,7 +1,5 @@ // Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System.Diagnostics.Contracts; using System; using System.Collections.Generic; using Avalonia.Interactivity; @@ -95,17 +93,17 @@ namespace Avalonia.Input bool IsEnabledCore { get; } /// - /// Gets or sets a value indicating whether the control is focused. + /// Gets a value indicating whether the control is focused. /// bool IsFocused { get; } /// - /// Gets or sets a value indicating whether the control is considered for hit testing. + /// Gets a value indicating whether the control is considered for hit testing. /// bool IsHitTestVisible { get; } /// - /// Gets or sets a value indicating whether the pointer is currently over the control. + /// Gets a value indicating whether the pointer is currently over the control. /// bool IsPointerOver { get; } diff --git a/src/Avalonia.Input/InputElement.cs b/src/Avalonia.Input/InputElement.cs index 652b58f0b5..6385f7197b 100644 --- a/src/Avalonia.Input/InputElement.cs +++ b/src/Avalonia.Input/InputElement.cs @@ -473,7 +473,7 @@ namespace Avalonia.Input /// Called before the event occurs. /// /// The event args. - protected virtual void OnPointerReleased(PointerEventArgs e) + protected virtual void OnPointerReleased(PointerReleasedEventArgs e) { } diff --git a/src/Avalonia.Input/MouseDevice.cs b/src/Avalonia.Input/MouseDevice.cs index 2c0cb8656c..cbcb4382ec 100644 --- a/src/Avalonia.Input/MouseDevice.cs +++ b/src/Avalonia.Input/MouseDevice.cs @@ -20,7 +20,6 @@ namespace Avalonia.Input private int _clickCount; private Rect _lastClickRect; private uint _lastClickTime; - private readonly List _pointerOvers = new List(); /// /// Intializes a new instance of . @@ -87,6 +86,8 @@ namespace Avalonia.Input /// The mouse position in the control's coordinates. public Point GetPosition(IVisual relativeTo) { + Contract.Requires(relativeTo != null); + Point p = default(Point); IVisual v = relativeTo; IVisual root = null; @@ -103,6 +104,8 @@ namespace Avalonia.Input private void ProcessRawEvent(RawMouseEventArgs e) { + Contract.Requires(e != null); + var mouse = (IMouseDevice)e.Device; Position = e.Root.PointToScreen(e.Position); @@ -141,11 +144,17 @@ namespace Avalonia.Input private void LeaveWindow(IMouseDevice device, IInputRoot root) { + Contract.Requires(device != null); + Contract.Requires(root != null); + ClearPointerOver(this, root); } private bool MouseDown(IMouseDevice device, uint timestamp, IInputElement root, Point p, MouseButton button, InputModifiers inputModifiers) { + Contract.Requires(device != null); + Contract.Requires(root != null); + var hit = HitTest(root, p); if (hit != null) @@ -187,6 +196,9 @@ namespace Avalonia.Input private bool MouseMove(IMouseDevice device, IInputRoot root, Point p, InputModifiers inputModifiers) { + Contract.Requires(device != null); + Contract.Requires(root != null); + IInputElement source; if (Captured == null) @@ -195,8 +207,7 @@ namespace Avalonia.Input } else { - var elements = Captured.GetSelfAndVisualAncestors().OfType().ToList(); - SetPointerOver(this, root, elements); + SetPointerOver(this, root, Captured); source = Captured; } @@ -208,12 +219,15 @@ namespace Avalonia.Input InputModifiers = inputModifiers }; - source.RaiseEvent(e); + source?.RaiseEvent(e); return e.Handled; } private bool MouseUp(IMouseDevice device, IInputRoot root, Point p, MouseButton button, InputModifiers inputModifiers) { + Contract.Requires(device != null); + Contract.Requires(root != null); + var hit = HitTest(root, p); if (hit != null) @@ -237,6 +251,9 @@ namespace Avalonia.Input private bool MouseWheel(IMouseDevice device, IInputRoot root, Point p, Vector delta, InputModifiers inputModifiers) { + Contract.Requires(device != null); + Contract.Requires(root != null); + var hit = HitTest(root, p); if (hit != null) @@ -260,6 +277,8 @@ namespace Avalonia.Input private IInteractive GetSource(IVisual hit) { + Contract.Requires(hit != null); + return Captured ?? (hit as IInteractive) ?? hit.GetSelfAndVisualAncestors().OfType().FirstOrDefault(); @@ -267,22 +286,28 @@ namespace Avalonia.Input private IInputElement HitTest(IInputElement root, Point p) { + Contract.Requires(root != null); + return Captured ?? root.InputHitTest(p); } private void ClearPointerOver(IPointerDevice device, IInputRoot root) { - foreach (var control in _pointerOvers.ToList()) + Contract.Requires(device != null); + Contract.Requires(root != null); + + var element = root.PointerOverElement; + var e = new PointerEventArgs { - PointerEventArgs e = new PointerEventArgs - { - RoutedEvent = InputElement.PointerLeaveEvent, - Device = device, - Source = control, - }; + RoutedEvent = InputElement.PointerLeaveEvent, + Device = device, + }; - _pointerOvers.Remove(control); - control.RaiseEvent(e); + while (element != null) + { + e.Source = element; + element.RaiseEvent(e); + element = (IInputElement)element.VisualParent; } root.PointerOverElement = null; @@ -290,40 +315,66 @@ namespace Avalonia.Input private IInputElement SetPointerOver(IPointerDevice device, IInputRoot root, Point p) { - var elements = root.GetInputElementsAt(p).ToList(); - return SetPointerOver(device, root, elements); + Contract.Requires(device != null); + Contract.Requires(root != null); + + var element = root.InputHitTest(p); + + if (element != root.PointerOverElement) + { + if (element != null) + { + SetPointerOver(device, root, element); + } + else + { + ClearPointerOver(device, root); + } + } + + return element; } - private IInputElement SetPointerOver(IPointerDevice device, IInputRoot root, IList elements) + private void SetPointerOver(IPointerDevice device, IInputRoot root, IInputElement element) { - foreach (var control in _pointerOvers.Except(elements).ToList()) + Contract.Requires(device != null); + Contract.Requires(root != null); + Contract.Requires(element != null); + + IInputElement branch = null; + + var e = new PointerEventArgs { - PointerEventArgs e = new PointerEventArgs - { - RoutedEvent = InputElement.PointerLeaveEvent, - Device = device, - Source = control, - }; + RoutedEvent = InputElement.PointerEnterEvent, + Device = device, + }; - _pointerOvers.Remove(control); - control.RaiseEvent(e); - } + var el = element; - foreach (var control in elements.Except(_pointerOvers)) + while (el != null) { - PointerEventArgs e = new PointerEventArgs + if (el.IsPointerOver) { - RoutedEvent = InputElement.PointerEnterEvent, - Device = device, - Source = control, - }; + branch = el; + break; + } - _pointerOvers.Add(control); - control.RaiseEvent(e); + e.Source = el; + el.RaiseEvent(e); + el = (IInputElement)el.VisualParent; + } + + el = root.PointerOverElement; + e.RoutedEvent = InputElement.PointerLeaveEvent; + + while (el != null && el != branch) + { + e.Source = el; + el.RaiseEvent(e); + el = (IInputElement)el.VisualParent; } - root.PointerOverElement = elements.FirstOrDefault() ?? root; - return root.PointerOverElement; + root.PointerOverElement = element; } } -} +} \ No newline at end of file diff --git a/src/Avalonia.Input/packages.config b/src/Avalonia.Input/packages.config deleted file mode 100644 index 9f732f1bcb..0000000000 --- a/src/Avalonia.Input/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj index 0d81690de0..ab9ab88a37 100644 --- a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj +++ b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj @@ -1,22 +1,7 @@ - - - + - 11.0 - Debug - AnyCPU - {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B} - Library - Properties - Avalonia.Interactivity - Avalonia.Interactivity - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 - - + netstandard1.1 + false true @@ -41,63 +26,15 @@ true - - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {42472427-4774-4C81-8AFF-9F27B8E31721} - Avalonia.Layout - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - + + + + Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.1\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.0\System.Reactive.PlatformServices.dll - True - - - - + \ No newline at end of file diff --git a/src/Avalonia.Interactivity/packages.config b/src/Avalonia.Interactivity/packages.config deleted file mode 100644 index 9f732f1bcb..0000000000 --- a/src/Avalonia.Interactivity/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Layout/Avalonia.Layout.csproj b/src/Avalonia.Layout/Avalonia.Layout.csproj index 41b545b5cb..45a40d2fd4 100644 --- a/src/Avalonia.Layout/Avalonia.Layout.csproj +++ b/src/Avalonia.Layout/Avalonia.Layout.csproj @@ -1,22 +1,7 @@ - - - + - 11.0 - Debug - AnyCPU - {42472427-4774-4C81-8AFF-9F27B8E31721} - Library - Properties - Avalonia - Avalonia.Layout - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 - - + netstandard1.1 + false true @@ -41,59 +26,14 @@ true - - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - + + + Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.1\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.0\System.Reactive.PlatformServices.dll - True - - - - + \ No newline at end of file diff --git a/src/Avalonia.Layout/packages.config b/src/Avalonia.Layout/packages.config deleted file mode 100644 index 9f732f1bcb..0000000000 --- a/src/Avalonia.Layout/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj b/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj index 0fb85db795..9aa81c19f9 100644 --- a/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj +++ b/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj @@ -1,20 +1,7 @@ - - - + - 10.0 - Debug - AnyCPU - {B61B66A3-B82D-4875-8001-89D3394FE0C9} - Library - Properties - Avalonia.Logging.Serilog - Avalonia.Logging.Serilog - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 + netstandard1.1 + false true @@ -37,30 +24,7 @@ true - - + - - - ..\..\packages\Serilog.1.5.14\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+MonoTouch10\Serilog.dll - True - - - - - - - - {b09b78d8-9b26-48b0-9149-d64a2f120f3f} - Avalonia.Base - - - - + \ No newline at end of file diff --git a/src/Avalonia.Logging.Serilog/packages.config b/src/Avalonia.Logging.Serilog/packages.config deleted file mode 100644 index dbc72b5331..0000000000 --- a/src/Avalonia.Logging.Serilog/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj index 98cf115eaf..28522d8849 100644 --- a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj +++ b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj @@ -1,27 +1,15 @@ - - - + - 10.0 - Debug - AnyCPU - {6417B24E-49C2-4985-8DB2-3AB9D898EC91} - Library - Properties - Avalonia.ReactiveUI - Avalonia.ReactiveUI - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile259 - v4.5 + netstandard1.1 + False + false true full false bin\Debug\ - TRACE;DEBUG;MONO PORTABLE + TRACE;DEBUG;MONO PORTABLE;NETSTANDARD1_1 prompt 4 @@ -29,15 +17,19 @@ pdbonly true bin\Release\ - TRACE;MONO PORTABLE + TRACE;MONO PORTABLE;RELEASE;NETSTANDARD1_1 prompt 4 + + + + @@ -65,9 +57,7 @@ - - Code - + @@ -87,35 +77,15 @@ - - ..\..\packages\Splat.1.6.2\lib\Portable-net45+win+wpa81+wp80\Splat.dll - - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.0\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.0\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.0\System.Reactive.PlatformServices.dll - True - - - - + + + + + + + + - - + + \ No newline at end of file diff --git a/src/Avalonia.ReactiveUI/Shims.cs b/src/Avalonia.ReactiveUI/Shims.cs new file mode 100644 index 0000000000..2729a68d6f --- /dev/null +++ b/src/Avalonia.ReactiveUI/Shims.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Runtime.Serialization +{ + class IgnoreDataMemberAttribute : Attribute + { + } + + class DataMemberAttribute : Attribute + { + } + class OnDeserializedAttribute : Attribute + { + } + + class DataContractAttribute : Attribute + { + } + + class StreamingContext { } +} + +namespace System.Diagnostics.Contracts +{ + static class Contract + { + public static void Requires(bool condition) + { + + } + } +} diff --git a/src/Avalonia.ReactiveUI/packages.config b/src/Avalonia.ReactiveUI/packages.config deleted file mode 100644 index f10d6d8873..0000000000 --- a/src/Avalonia.ReactiveUI/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Styling/Avalonia.Styling.csproj b/src/Avalonia.Styling/Avalonia.Styling.csproj index 389a265f7e..651c7e7077 100644 --- a/src/Avalonia.Styling/Avalonia.Styling.csproj +++ b/src/Avalonia.Styling/Avalonia.Styling.csproj @@ -1,22 +1,7 @@ - - - + - 11.0 - Debug - AnyCPU - {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F} - Library - Properties - Avalonia - Avalonia.Styling - en-US - 512 - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile7 - v4.5 - - + netstandard1.1 + false true @@ -81,48 +66,9 @@ - - ..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll - True - - - ..\..\packages\System.Reactive.Interfaces.3.0.0\lib\netstandard1.0\System.Reactive.Interfaces.dll - True - - - ..\..\packages\System.Reactive.Linq.3.0.0\lib\netstandard1.1\System.Reactive.Linq.dll - True - - - ..\..\packages\System.Reactive.PlatformServices.3.0.0\lib\netstandard1.0\System.Reactive.PlatformServices.dll - True - + + + - - - - - - - - {d211e587-d8bc-45b9-95a4-f297c8fa5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - - - - + \ No newline at end of file diff --git a/src/Avalonia.Styling/packages.config b/src/Avalonia.Styling/packages.config deleted file mode 100644 index 9f732f1bcb..0000000000 --- a/src/Avalonia.Styling/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Themes.Default/Accents/BaseLight.xaml b/src/Avalonia.Themes.Default/Accents/BaseLight.xaml index 38786f54d3..cb86598a42 100644 --- a/src/Avalonia.Themes.Default/Accents/BaseLight.xaml +++ b/src/Avalonia.Themes.Default/Accents/BaseLight.xaml @@ -1,6 +1,5 @@ \ No newline at end of file diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs index afb8663a78..0c5a89b827 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs @@ -127,13 +127,12 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml { var xaml = @" @@ -142,12 +141,12 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml var loader = new AvaloniaXamlLoader(); var window = (Window)loader.Load(xaml); - var brush = (Avalonia.Media.Mutable.SolidColorBrush)window.FindStyleResource("brush"); + var brush = (ISolidColorBrush)window.FindStyleResource("brush"); var button = window.FindControl