Browse Source

Merge branch 'master' into perf/cache-ao-initialization

Steven Kirk 6 years ago
parent
commit
2d7611e7ef
100 changed files with 1993 additions and 1049 deletions
  1. 22 8
      .github/PULL_REQUEST_TEMPLATE.md
  2. 1 0
      .gitignore
  3. 3 0
      .gitmodules
  4. 5 0
      .ncrunch/Avalonia.Desktop.v3.ncrunchproject
  5. 5 0
      .ncrunch/Avalonia.net461.v3.ncrunchproject
  6. 0 0
      .nuke
  7. 0 24
      .travis.yml
  8. 162 0
      Avalonia.sln
  9. 2 1
      Avalonia.sln.DotSettings
  10. 1 0
      Avalonia.v3.ncrunchsolution
  11. 1 1
      Directory.Build.props
  12. 0 23
      appveyor.yml
  13. 26 18
      azure-pipelines.yml
  14. 0 312
      build.cake
  15. 47 179
      build.ps1
  16. 53 86
      build.sh
  17. 8 0
      build/BuildTargets.targets
  18. 1 1
      build/Magick.NET-Q16-AnyCPU.props
  19. 5 0
      build/NetFX.props
  20. 0 1
      build/ReferenceCoreLibraries.props
  21. 2 2
      build/SkiaSharp.props
  22. 8 0
      build/UnitTests.NetFX.props
  23. 1 0
      build/xunit.runner.mono.json
  24. 0 15
      cake.config
  25. 1 1
      global.json
  26. 10 4
      native/Avalonia.Native/inc/avalonia-native.h
  27. 6 0
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
  28. 14 0
      native/Avalonia.Native/src/OSX/AvnString.h
  29. 55 0
      native/Avalonia.Native/src/OSX/AvnString.mm
  30. 12 7
      native/Avalonia.Native/src/OSX/clipboard.mm
  31. 9 0
      native/Avalonia.Native/src/OSX/common.h
  32. 2 4
      native/Avalonia.Native/src/OSX/gl.mm
  33. 10 14
      native/Avalonia.Native/src/OSX/main.mm
  34. 2 0
      native/Avalonia.Native/src/OSX/window.h
  35. 103 47
      native/Avalonia.Native/src/OSX/window.mm
  36. 8 0
      nukebuild/.editorconfig
  37. 265 0
      nukebuild/Build.cs
  38. 142 0
      nukebuild/BuildParameters.cs
  39. 1 0
      nukebuild/Numerge
  40. 93 0
      nukebuild/Shims.cs
  41. 37 0
      nukebuild/_build.csproj
  42. 24 0
      nukebuild/_build.csproj.DotSettings
  43. 23 0
      nukebuild/numerge.config
  44. 14 8
      packages/Avalonia/Avalonia.csproj
  45. 3 0
      packages/Avalonia/Avalonia.props
  46. 3 0
      packages/Avalonia/Avalonia.targets
  47. 3 0
      packages/Avalonia/AvaloniaBuildTasks.props
  48. 43 0
      packages/Avalonia/AvaloniaBuildTasks.targets
  49. 0 129
      parameters.cake
  50. 3 3
      readme.md
  51. 1 1
      samples/ControlCatalog.Desktop/Program.cs
  52. 1 0
      samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
  53. 8 2
      samples/ControlCatalog.NetCore/Program.cs
  54. 6 4
      samples/ControlCatalog/App.xaml
  55. 5 3
      samples/ControlCatalog/ControlCatalog.csproj
  56. 12 5
      samples/ControlCatalog/DecoratedWindow.xaml
  57. 39 30
      samples/ControlCatalog/MainView.xaml
  58. 17 0
      samples/ControlCatalog/MainView.xaml.cs
  59. 5 3
      samples/ControlCatalog/MainWindow.xaml
  60. 3 1
      samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
  61. 3 1
      samples/ControlCatalog/Pages/BorderPage.xaml
  62. 2 1
      samples/ControlCatalog/Pages/ButtonPage.xaml
  63. 2 1
      samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml
  64. 2 1
      samples/ControlCatalog/Pages/CalendarPage.xaml
  65. 3 1
      samples/ControlCatalog/Pages/CanvasPage.xaml
  66. 6 4
      samples/ControlCatalog/Pages/CarouselPage.xaml
  67. 2 1
      samples/ControlCatalog/Pages/CheckBoxPage.xaml
  68. 4 2
      samples/ControlCatalog/Pages/ContextMenuPage.xaml
  69. 2 1
      samples/ControlCatalog/Pages/DatePickerPage.xaml
  70. 5 5
      samples/ControlCatalog/Pages/DialogsPage.xaml
  71. 14 1
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  72. 3 1
      samples/ControlCatalog/Pages/DragAndDropPage.xaml
  73. 12 1
      samples/ControlCatalog/Pages/DropDownPage.xaml
  74. 3 0
      samples/ControlCatalog/Pages/DropDownPage.xaml.cs
  75. 3 1
      samples/ControlCatalog/Pages/ExpanderPage.xaml
  76. 8 6
      samples/ControlCatalog/Pages/ImagePage.xaml
  77. 3 2
      samples/ControlCatalog/Pages/LayoutTransformControlPage.xaml
  78. 3 1
      samples/ControlCatalog/Pages/ListBoxPage.xaml
  79. 4 2
      samples/ControlCatalog/Pages/MenuPage.xaml
  80. 1 1
      samples/ControlCatalog/Pages/MenuPage.xaml.cs
  81. 10 9
      samples/ControlCatalog/Pages/NumericUpDownPage.xaml
  82. 4 2
      samples/ControlCatalog/Pages/ProgressBarPage.xaml
  83. 3 2
      samples/ControlCatalog/Pages/RadioButtonPage.xaml
  84. 3 1
      samples/ControlCatalog/Pages/ScreenPage.cs
  85. 4 2
      samples/ControlCatalog/Pages/SliderPage.xaml
  86. 100 0
      samples/ControlCatalog/Pages/TabControlPage.xaml
  87. 80 0
      samples/ControlCatalog/Pages/TabControlPage.xaml.cs
  88. 13 2
      samples/ControlCatalog/Pages/TextBoxPage.xaml
  89. 4 2
      samples/ControlCatalog/Pages/ToolTipPage.xaml
  90. 4 2
      samples/ControlCatalog/Pages/TreeViewPage.xaml
  91. 66 0
      samples/ControlCatalog/Pages/ViewboxPage.xaml
  92. 18 0
      samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
  93. 64 49
      samples/ControlCatalog/SideBar.xaml
  94. 6 0
      samples/PlatformSanityChecks/App.xaml
  95. 13 0
      samples/PlatformSanityChecks/App.xaml.cs
  96. 13 0
      samples/PlatformSanityChecks/PlatformSanityChecks.csproj
  97. 132 0
      samples/PlatformSanityChecks/Program.cs
  98. 1 4
      samples/RenderDemo/MainWindow.xaml
  99. 33 2
      samples/RenderDemo/Pages/AnimationsPage.xaml
  100. 1 1
      samples/RenderDemo/Pages/ClippingPage.xaml

+ 22 - 8
.github/PULL_REQUEST_TEMPLATE.md

@@ -1,17 +1,31 @@
-This template is not intended to be prescriptive, but to help us review pull requests it would be useful if you included as much of the following information as possible:
+## What does the pull request do?
+<!--- Give a bit of background on the PR here, together with links to with related issues etc. -->
 
-- What does the pull request do?
-- What is the current behavior?
-- What is the updated/expected behavior with this PR?
-- How was the solution implemented (if it's not obvious)?
 
-Checklist:
+## What is the current behavior?
+<!--- If the PR is a fix, describe the current incorrect behavior, otherwise delete this section. -->
+
+
+## What is the updated/expected behavior with this PR?
+<!--- Describe how to test the PR. -->
+
+
+## How was the solution implemented (if it's not obvious)?
+<!--- Include any information that might be of use to a reviewer here. -->
+
+
+## Checklist
 
 - [ ] Added unit tests (if possible)?
 - [ ] Added XML documentation to any related classes?
 - [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Avaloniaui.net with user documentation
 
-If the pull request fixes issue(s) list them like this:
+## Breaking changes
+<!--- List any breaking changes here. When the PR is merged please add an entry to https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes -->
+
 
+## Fixed issues
+<!--- If the pull request fixes issue(s) list them like this: 
 Fixes #123
-Fixes #456
+Fixes #456
+-->

+ 1 - 0
.gitignore

@@ -195,3 +195,4 @@ Logs/
 ModuleCache.noindex/
 Build/Intermediates.noindex/
 info.plist
+build-intermediate

+ 3 - 0
.gitmodules

@@ -1,3 +1,6 @@
 [submodule "src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github"]
 	path = src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github
 	url = https://github.com/AvaloniaUI/Portable.Xaml.git
+[submodule "nukebuild/Numerge"]
+	path = nukebuild/Numerge
+	url = https://github.com/kekekeks/Numerge.git

+ 5 - 0
.ncrunch/Avalonia.Desktop.v3.ncrunchproject

@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+  <Settings>
+    <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
+  </Settings>
+</ProjectConfiguration>

+ 5 - 0
.ncrunch/Avalonia.net461.v3.ncrunchproject

@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+  <Settings>
+    <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
+  </Settings>
+</ProjectConfiguration>

+ 0 - 0
.nuke


+ 0 - 24
.travis.yml

@@ -1,24 +0,0 @@
-language: csharp
-os:
-  - linux
-dist: trusty
-osx_image: xcode8.3
-env:
-  global:
-    - DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
-    - DOTNET_CLI_TELEMETRY_OPTOUT=1
-mono:
-  - 5.2.0
-dotnet: 2.1.200
-script:
-  - sudo apt-get update
-  - sudo apt-get install castxml
-  - ./build.sh --target "Travis" --configuration "Release"
-notifications:
-  email: false
-  webhooks:
-    urls:
-      - https://webhooks.gitter.im/e/98f653320ef2b7506c05
-    on_success: change
-    on_failure: always
-    on_start: never

+ 162 - 0
Avalonia.sln

@@ -1,3 +1,4 @@
+
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
 VisualStudioVersion = 15.0.27130.2027
@@ -130,6 +131,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
 	ProjectSection(SolutionItems) = preProject
 		build\Base.props = build\Base.props
 		build\Binding.props = build\Binding.props
+		build\BuildTargets.targets = build\BuildTargets.targets
 		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
@@ -188,6 +190,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia", "packages\Avalon
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Desktop", "src\Avalonia.Desktop\Avalonia.Desktop.csproj", "{3C471044-3640-45E3-B1B2-16D2FF8399EE}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Build.Tasks", "src\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj", "{BF28998D-072C-439A-AFBB-2FE5021241E0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "nukebuild\_build.csproj", "{3F00BC43-5095-477F-93D8-E65B08179A00}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Animation.UnitTests", "tests\Avalonia.Animation.UnitTests\Avalonia.Animation.UnitTests.csproj", "{AF227847-E65C-4BE9-BCE9-B551357788E0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.X11", "src\Avalonia.X11\Avalonia.X11.csproj", "{41B02319-965D-4945-8005-C1A3D1224165}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlatformSanityChecks", "samples\PlatformSanityChecks\PlatformSanityChecks.csproj", "{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI.UnitTests", "tests\Avalonia.ReactiveUI.UnitTests\Avalonia.ReactiveUI.UnitTests.csproj", "{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}"
+EndProject
 Global
 	GlobalSection(SharedMSBuildProjectFiles) = preSolution
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
@@ -1687,6 +1701,150 @@ Global
 		{3C471044-3640-45E3-B1B2-16D2FF8399EE}.Release|iPhone.Build.0 = Release|Any CPU
 		{3C471044-3640-45E3-B1B2-16D2FF8399EE}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 		{3C471044-3640-45E3-B1B2-16D2FF8399EE}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|iPhone.Build.0 = Release|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhone.Build.0 = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|iPhone.Build.0 = Release|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{AF227847-E65C-4BE9-BCE9-B551357788E0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Release|Any CPU.Build.0 = Release|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Release|iPhone.Build.0 = Release|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{41B02319-965D-4945-8005-C1A3D1224165}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhone.Build.0 = Release|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|Any CPU.Build.0 = Release|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhone.Build.0 = Release|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -1740,6 +1898,10 @@ Global
 		{E1240B49-7B4B-4371-A00E-068778C5CF0B} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
 		{D49233F8-F29C-47DD-9975-C4C9E4502720} = {E870DCD7-F46A-498D-83FC-D0FD13E0A11C}
 		{3C471044-3640-45E3-B1B2-16D2FF8399EE} = {E870DCD7-F46A-498D-83FC-D0FD13E0A11C}
+		{AF227847-E65C-4BE9-BCE9-B551357788E0} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
+		{41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
+		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

+ 2 - 1
Avalonia.sln.DotSettings

@@ -35,4 +35,5 @@
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="T" Suffix="" Style="AaBb" /&gt;</s:String>
-	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String></wpf:ResourceDictionary>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
+	<s:Boolean x:Key="/Default/UserDictionary/Words/=Avalonia/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

+ 1 - 0
Avalonia.v3.ncrunchsolution

@@ -2,6 +2,7 @@
   <Settings>
     <AdditionalFilesToIncludeForSolution>
       <Value>tests\TestFiles\**.*</Value>
+      <Value>src\Avalonia.Build.Tasks\bin\Debug\netstandard2.0\Avalonia.Build.Tasks.dll</Value>
     </AdditionalFilesToIncludeForSolution>
     <AllowParallelTestExecution>True</AllowParallelTestExecution>
     <ProjectConfigStoragePathRelativeToSolutionDir>.ncrunch</ProjectConfigStoragePathRelativeToSolutionDir>

+ 1 - 1
Directory.Build.props

@@ -1,5 +1,5 @@
 <Project>
   <PropertyGroup>
-      <PackageOutputPath Condition="'$(PackageOutputPath)' == ''">$(MSBuildThisFileDirectory)artifacts/nuget</PackageOutputPath>
+      <PackageOutputPath Condition="'$(PackageOutputPath)' == ''">$(MSBuildThisFileDirectory)build-intermediate/nuget</PackageOutputPath>
   </PropertyGroup>
 </Project>

+ 0 - 23
appveyor.yml

@@ -1,23 +0,0 @@
-os: Visual Studio 2017
-skip_branch_with_pr: true
-configuration:
-- Release
-environment:
-  DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
-  DOTNET_CLI_TELEMETRY_OPTOUT: 1
-  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: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")}
-before_build:
-- git submodule update --init
-build_script:
-- ps: .\build.ps1 -Target "AppVeyor" -Configuration "$env:configuration"
-
-test: off
-artifacts:
-  - path: artifacts\nuget\*.nupkg
-  - path: artifacts\zip\*.zip
-  - path: artifacts\inspectcode.xml

+ 26 - 18
azure-pipelines.yml

@@ -11,19 +11,18 @@ jobs:
         sudo apt-get install castxml
 
   - task: CmdLine@2
-    displayName: 'Install Cake'
+    displayName: 'Install Nuke'
     inputs:
       script: |
-        dotnet tool install -g Cake.Tool --version 0.30.0
-  
+         dotnet tool install --global Nuke.GlobalTool --version 0.12.3
   - task: CmdLine@2
-    displayName: 'Run Cake'
+    displayName: 'Run Nuke'
     inputs:
       script: |
         export PATH="$PATH:$HOME/.dotnet/tools"
         dotnet --info
         printenv
-        dotnet cake build.cake -target="Azure-Linux" -configuration="Release"
+        nuke --target CiAzureLinux --configuration=Release
 
   - task: PublishTestResults@2
     inputs:
@@ -39,6 +38,13 @@ jobs:
     inputs:
       version: '2.1.403'
 
+  - task: CmdLine@2
+    displayName: 'Install Mono 5.18'
+    inputs:
+      script: |
+        curl -o ./mono.pkg https://download.mono-project.com/archive/5.18.0/macos-10-universal/MonoFramework-MDK-5.18.0.225.macos10.xamarin.universal.pkg 
+        sudo installer -verbose -pkg ./mono.pkg -target /
+
   - task: Xcode@5
     inputs:
       actions: 'build'
@@ -52,16 +58,18 @@ jobs:
   - task: CmdLine@2
     displayName: 'Install CastXML'
     inputs:
-      script: brew install castxml
+      script: |
+        brew update
+        brew install castxml
 
   - task: CmdLine@2
-    displayName: 'Install Cake'
+    displayName: 'Install Nuke'
     inputs:
       script: |
-        dotnet tool install -g Cake.Tool --version 0.30.0
+       dotnet tool install --global Nuke.GlobalTool --version 0.12.3 
 
   - task: CmdLine@2
-    displayName: 'Run Cake'
+    displayName: 'Run Nuke'
     inputs:
       script: |
         export COREHOST_TRACE=0
@@ -72,7 +80,7 @@ jobs:
         export PATH="$PATH:$HOME/.dotnet/tools"
         dotnet --info
         printenv
-        dotnet cake build.cake -target="Azure-OSX" -configuration="Release"
+        nuke --target CiAzureOSX --configuration Release
 
   - task: PublishTestResults@2
     inputs:
@@ -84,30 +92,30 @@ jobs:
     inputs:
       pathToPublish: '$(Build.SourcesDirectory)/Build/Products/Release/'
       artifactName: 'Avalonia.Native.OSX'
-    condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
+    condition: succeeded()
     
   - task: PublishBuildArtifacts@1
     inputs:
       pathtoPublish: '$(Build.SourcesDirectory)/artifacts/nuget'
       artifactName: 'NuGetOSX'
-    condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
+    condition: succeeded()
 
 - job: Windows
   pool:
     vmImage: 'vs2017-win2016'
   steps:
   - task: CmdLine@2
-    displayName: 'Install Cake'
+    displayName: 'Install Nuke'
     inputs:
       script: |
-        dotnet tool install -g Cake.Tool --version 0.30.0
+       dotnet tool install --global Nuke.GlobalTool --version 0.12.3 
 
   - task: CmdLine@2
-    displayName: 'Run Cake'
+    displayName: 'Run Nuke'
     inputs:
       script: |
         set PATH=%PATH%;%USERPROFILE%\.dotnet\tools
-        dotnet cake build.cake -target="Azure-Windows" -configuration="Release"
+        nuke --target CiAzureWindows --configuration Release
       
   - task: PublishTestResults@2
     inputs:
@@ -119,10 +127,10 @@ jobs:
     inputs:
       pathtoPublish: '$(Build.SourcesDirectory)/artifacts/nuget'
       artifactName: 'NuGet'
-    condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
+    condition: succeeded()
 
   - task: PublishBuildArtifacts@1
     inputs:
       pathToPublish: '$(Build.SourcesDirectory)/artifacts/zip'
       artifactName: 'Samples'
-    condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
+    condition: succeeded()

+ 0 - 312
build.cake

@@ -1,312 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// TOOLS
-///////////////////////////////////////////////////////////////////////////////
-
-#tool "nuget:?package=NuGet.CommandLine&version=4.7.1"
-#tool "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.2.3"
-#tool "nuget:?package=xunit.runner.console&version=2.3.1"
-#tool "nuget:?package=JetBrains.dotMemoryUnit&version=3.0.20171219.105559"
-
-///////////////////////////////////////////////////////////////////////////////
-// USINGS
-///////////////////////////////////////////////////////////////////////////////
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-
-///////////////////////////////////////////////////////////////////////////////
-// SCRIPTS
-///////////////////////////////////////////////////////////////////////////////
-
-#load "./parameters.cake"
-
-///////////////////////////////////////////////////////////////////////////////
-// SETUP
-///////////////////////////////////////////////////////////////////////////////
-
-Setup<Parameters>(context =>
-{
-    var parameters = new Parameters(context);
-
-    Information("Building version {0} of Avalonia ({1}) using version {2} of Cake.", 
-        parameters.Version,
-        parameters.Configuration,
-        typeof(ICakeContext).Assembly.GetName().Version.ToString());
-
-    if (parameters.IsRunningOnAppVeyor)
-    {
-        Information("Repository Name: " + BuildSystem.AppVeyor.Environment.Repository.Name);
-        Information("Repository Branch: " + BuildSystem.AppVeyor.Environment.Repository.Branch);
-    }
-    Information("Target:" + context.TargetTask.Name);
-    Information("Configuration: " + parameters.Configuration);
-    Information("IsLocalBuild: " + parameters.IsLocalBuild);
-    Information("IsRunningOnUnix: " + parameters.IsRunningOnUnix);
-    Information("IsRunningOnWindows: " + parameters.IsRunningOnWindows);
-    Information("IsRunningOnAppVeyor: " + parameters.IsRunningOnAppVeyor);
-    Information("IsRunnongOnAzure:" + parameters.IsRunningOnAzure);
-    Information("IsPullRequest: " + parameters.IsPullRequest);
-    Information("IsMainRepo: " + parameters.IsMainRepo);
-    Information("IsMasterBranch: " + parameters.IsMasterBranch);
-    Information("IsReleaseBranch: " + parameters.IsReleaseBranch);
-    Information("IsTagged: " + parameters.IsTagged);
-    Information("IsReleasable: " + parameters.IsReleasable);
-    Information("IsMyGetRelease: " + parameters.IsMyGetRelease);
-    Information("IsNuGetRelease: " + parameters.IsNuGetRelease);
-
-    return parameters;
-});
-
-///////////////////////////////////////////////////////////////////////////////
-// TEARDOWN
-///////////////////////////////////////////////////////////////////////////////
-
-Teardown<Parameters>((context, buildContext) =>
-{
-    Information("Finished running tasks.");
-});
-
-///////////////////////////////////////////////////////////////////////////////
-// TASKS
-///////////////////////////////////////////////////////////////////////////////
-
-Task("Clean-Impl")
-    .Does<Parameters>(data =>
-{
-    CleanDirectories(data.BuildDirs);
-    CleanDirectory(data.ArtifactsDir);
-    CleanDirectory(data.NugetRoot);
-    CleanDirectory(data.ZipRoot);
-    CleanDirectory(data.TestResultsRoot);
-});
-
-void DotNetCoreBuild(Parameters parameters)
-{
-    var settings = new DotNetCoreBuildSettings 
-    {
-        Configuration = parameters.Configuration,
-        MSBuildSettings = new DotNetCoreMSBuildSettings
-        {
-            Properties =
-            {
-                { "PackageVersion", new [] { parameters.Version } }
-            }
-        }
-    };
-
-    DotNetCoreBuild(parameters.MSBuildSolution, settings);
-}
-
-Task("Build-Impl")
-    .Does<Parameters>(data =>
-{
-    if(data.IsRunningOnWindows)
-    {
-        MSBuild(data.MSBuildSolution, settings => {
-            settings.SetConfiguration(data.Configuration);
-            settings.SetVerbosity(Verbosity.Minimal);
-            settings.WithProperty("iOSRoslynPathHackRequired", "true");
-            settings.WithProperty("PackageVersion", data.Version);
-            settings.UseToolVersion(MSBuildToolVersion.VS2017);
-            settings.WithRestore();
-        });
-    }
-    else
-    {
-        DotNetCoreBuild(data);
-    }
-});
-
-void RunCoreTest(string project, Parameters parameters, bool coreOnly = false)
-{
-    if(!project.EndsWith(".csproj"))
-        project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj");
-    Information("Running tests from " + project);
-    var frameworks = new List<string>(){"netcoreapp2.0"};
-    foreach(var fw in frameworks)
-    {
-        if(!fw.StartsWith("netcoreapp") && coreOnly)
-            continue;
-        Information("Running for " + fw);
-        
-        var settings = new DotNetCoreTestSettings {
-            Configuration = parameters.Configuration,
-            Framework = fw,
-            NoBuild = true,
-            NoRestore = true
-        };
-
-        if (parameters.PublishTestResults)
-        {
-            settings.Logger = "trx";
-            settings.ResultsDirectory = parameters.TestResultsRoot;
-        }
-
-        DotNetCoreTest(project, settings);
-    }
-}
-
-Task("Run-Unit-Tests-Impl")
-    .WithCriteria<Parameters>((context, data) => !data.SkipTests)
-    .Does<Parameters>(data =>
-{
-    RunCoreTest("./tests/Avalonia.Base.UnitTests", data, false);
-    RunCoreTest("./tests/Avalonia.Controls.UnitTests", data, false);
-    RunCoreTest("./tests/Avalonia.Input.UnitTests", data, false);
-    RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", data, false);
-    RunCoreTest("./tests/Avalonia.Layout.UnitTests", data, false);
-    RunCoreTest("./tests/Avalonia.Markup.UnitTests", data, false);
-    RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", data, false);
-    RunCoreTest("./tests/Avalonia.Styling.UnitTests", data, false);
-    RunCoreTest("./tests/Avalonia.Visuals.UnitTests", data, false);
-    RunCoreTest("./tests/Avalonia.Skia.UnitTests", data, false);
-    RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests", data, false);
-    if (data.IsRunningOnWindows)
-    {
-        RunCoreTest("./tests/Avalonia.Direct2D1.UnitTests", data, false);
-    }
-});
-
-Task("Run-Designer-Tests-Impl")
-    .WithCriteria<Parameters>((context, data) => !data.SkipTests)
-    .Does<Parameters>(data =>
-{
-    RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", data, false);
-});
-
-Task("Run-Render-Tests-Impl")
-    .WithCriteria<Parameters>((context, data) => !data.SkipTests)
-    .WithCriteria<Parameters>((context, data) => data.IsRunningOnWindows)
-    .Does<Parameters>(data =>
-{
-    RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", data, true);
-    RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", data, true);
-});
-
-Task("Run-Leak-Tests-Impl")
-    .WithCriteria<Parameters>((context, data) => !data.SkipTests)
-    .WithCriteria<Parameters>((context, data) => data.IsRunningOnWindows)
-    .Does(() =>
-{
-    var dotMemoryUnit = Context.Tools.Resolve("dotMemoryUnit.exe");
-    var leakTestsExitCode = StartProcess(dotMemoryUnit, new ProcessSettings
-    {
-        Arguments = new ProcessArgumentBuilder()
-            .Append(Context.Tools.Resolve("xunit.console.x86.exe").FullPath)
-            .Append("--propagate-exit-code")
-            .Append("--")
-            .Append("tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"),
-        Timeout = 120000
-    });
-
-    if (leakTestsExitCode != 0)
-    {
-        throw new Exception("Leak Tests failed");
-    }
-});
-
-Task("Zip-Files-Impl")
-    .Does<Parameters>(data =>
-{
-    Zip(data.BinRoot, data.ZipCoreArtifacts);
-
-    Zip(data.NugetRoot, data.ZipNuGetArtifacts);
-
-    Zip(data.ZipSourceControlCatalogDesktopDirs, 
-        data.ZipTargetControlCatalogDesktopDirs, 
-        GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") + 
-        GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.config") + 
-        GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.so") + 
-        GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dylib") + 
-        GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe"));
-});
-
-void DotNetCorePack(Parameters parameters)
-{
-    var settings = new DotNetCorePackSettings 
-    {
-        Configuration = parameters.Configuration,
-        MSBuildSettings = new DotNetCoreMSBuildSettings
-        {
-            Properties =
-            {
-                { "PackageVersion", new [] { parameters.Version } }
-            }
-        }
-    };
-
-    DotNetCorePack(parameters.MSBuildSolution, settings);
-}
-
-Task("Create-NuGet-Packages-Impl")
-    .Does<Parameters>(data =>
-{
-    if(data.IsRunningOnWindows)
-    {
-        MSBuild(data.MSBuildSolution, settings => {
-            settings.SetConfiguration(data.Configuration);
-            settings.SetVerbosity(Verbosity.Minimal);
-            settings.WithProperty("iOSRoslynPathHackRequired", "true");
-            settings.WithProperty("PackageVersion", data.Version);
-            settings.UseToolVersion(MSBuildToolVersion.VS2017);
-            settings.WithRestore();
-            settings.WithTarget("Pack");
-        });
-    }
-    else
-    {
-        DotNetCorePack(data);
-    }
-});
-
-///////////////////////////////////////////////////////////////////////////////
-// TARGETS
-///////////////////////////////////////////////////////////////////////////////
-
-Task("Build")
-    .IsDependentOn("Clean-Impl")
-    .IsDependentOn("Build-Impl");
-
-Task("Run-Tests")
-    .IsDependentOn("Build")
-    .IsDependentOn("Run-Unit-Tests-Impl")
-    .IsDependentOn("Run-Render-Tests-Impl")
-    .IsDependentOn("Run-Designer-Tests-Impl")
-    .IsDependentOn("Run-Leak-Tests-Impl");
-
-Task("Package")
-    .IsDependentOn("Run-Tests")
-    .IsDependentOn("Create-NuGet-Packages-Impl");
-
-Task("AppVeyor")
-  .IsDependentOn("Package")
-  .IsDependentOn("Zip-Files-Impl");
-
-Task("Travis")
-  .IsDependentOn("Run-Tests");
-
-Task("Azure-Linux")
-  .IsDependentOn("Run-Tests");
-
-Task("Azure-OSX")
-  .IsDependentOn("Package")
-  .IsDependentOn("Zip-Files-Impl");
-
-Task("Azure-Windows")
-  .IsDependentOn("Package")
-  .IsDependentOn("Zip-Files-Impl");
-
-///////////////////////////////////////////////////////////////////////////////
-// EXECUTE
-///////////////////////////////////////////////////////////////////////////////
-
-var target = Context.Argument("target", "Default");
-
-if (target == "Default")
-{
-    target = Context.IsRunningOnWindows() ? "Package" : "Run-Tests";
-}
-
-RunTarget(target);

+ 47 - 179
build.ps1

@@ -1,201 +1,69 @@
-##########################################################################
-# This is the Cake bootstrapper script for PowerShell.
-# This file was downloaded from https://github.com/cake-build/resources
-# Feel free to change this file to fit your needs.
-##########################################################################
-
-<#
-
-.SYNOPSIS
-This is a Powershell script to bootstrap a Cake build.
-
-.DESCRIPTION
-This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
-and execute your Cake build script with the parameters you provide.
-
-.PARAMETER Script
-The build script to execute.
-.PARAMETER Target
-The build script target to run.
-.PARAMETER Platform
-The build platform to use.
-.PARAMETER Configuration
-The build configuration to use.
-.PARAMETER Verbosity
-Specifies the amount of information to be displayed.
-.PARAMETER Experimental
-Tells Cake to use the latest Roslyn release.
-.PARAMETER WhatIf
-Performs a dry run of the build script.
-No tasks will be executed.
-.PARAMETER Mono
-Tells Cake to use the Mono scripting engine.
-.PARAMETER SkipToolPackageRestore
-Skips restoring of packages.
-.PARAMETER SkipTests
-Skips unit tests
-.PARAMETER ScriptArgs
-Remaining arguments are added here.
-
-.LINK
-http://cakebuild.net
-
-#>
-
 [CmdletBinding()]
 Param(
-    [string]$Script = "build.cake",
-    [string]$Target = "Default",
-    [ValidateSet("Any CPU", "x86", "x64", "NetCoreOnly", "iPhone")]
-    [string]$Platform = "Any CPU",
-    [ValidateSet("Release", "Debug")]
-    [string]$Configuration = "Release",
-    [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
-    [string]$Verbosity = "Verbose",
-    [switch]$Experimental,
-    [Alias("DryRun","Noop")]
-    [switch]$WhatIf,
-    [switch]$Mono,
-    [switch]$SkipToolPackageRestore,
+    #[switch]$CustomParam,
     [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
-    [string[]]$ScriptArgs
+    [string[]]$BuildArguments
 )
 
-[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
-function MD5HashFile([string] $filePath)
-{
-    if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
-    {
-        return $null
-    }
-
-    [System.IO.Stream] $file = $null;
-    [System.Security.Cryptography.MD5] $md5 = $null;
-    try
-    {
-        $md5 = [System.Security.Cryptography.MD5]::Create()
-        $file = [System.IO.File]::OpenRead($filePath)
-        return [System.BitConverter]::ToString($md5.ComputeHash($file))
-    }
-    finally
-    {
-        if ($file -ne $null)
-        {
-            $file.Dispose()
-        }
-    }
-}
-
-Write-Host "Preparing to run build script..."
-
-if(!$PSScriptRoot){
-    $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
-}
+Write-Output "Windows PowerShell $($Host.Version)"
 
-$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
-$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
-$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
-$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
-$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
-$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
+Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { exit 1 }
+$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
 
-# Should we use mono?
-$UseMono = "";
-if($Mono.IsPresent) {
-    Write-Verbose -Message "Using the Mono based scripting engine."
-    $UseMono = "-mono"
-}
+###########################################################################
+# CONFIGURATION
+###########################################################################
 
-# Should we use the new Roslyn?
-$UseExperimental = "";
-if($Experimental.IsPresent -and !($Mono.IsPresent)) {
-    Write-Verbose -Message "Using experimental version of Roslyn."
-    $UseExperimental = "-experimental"
-}
+$BuildProjectFile = "$PSScriptRoot\nukebuild\_build.csproj"
+$TempDirectory = "$PSScriptRoot\\.tmp"
 
-# Is this a dry run?
-$UseDryRun = "";
-if($WhatIf.IsPresent) {
-    $UseDryRun = "-dryrun"
-}
+$DotNetGlobalFile = "$PSScriptRoot\\global.json"
+$DotNetInstallUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1"
+$DotNetChannel = "Current"
 
-# Is this a dry run?
-$UseSkipTests = "";
-if($SkipTests.IsPresent) {
-    $UseSkipTests = "-skip-tests"
-}
+$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
+$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
+$env:NUGET_XMLDOC_MODE = "skip"
 
-# Make sure tools folder exists
-if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
-    Write-Verbose -Message "Creating tools directory..."
-    New-Item -Path $TOOLS_DIR -Type directory | out-null
-}
+###########################################################################
+# EXECUTION
+###########################################################################
 
-# Make sure that packages.config exist.
-if (!(Test-Path $PACKAGES_CONFIG)) {
-    Write-Verbose -Message "Downloading packages.config..."
-    try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
-        Throw "Could not download packages.config."
-    }
+function ExecSafe([scriptblock] $cmd) {
+    & $cmd
+    if ($LASTEXITCODE) { exit $LASTEXITCODE }
 }
 
-# Try find NuGet.exe in path if not exists
-if (!(Test-Path $NUGET_EXE)) {
-    Write-Verbose -Message "Trying to find nuget.exe in PATH..."
-    $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) }
-    $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
-    if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
-        Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
-        $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
+# If global.json exists, load expected version
+if (Test-Path $DotNetGlobalFile) {
+    $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
+    if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
+        $DotNetVersion = $DotNetGlobal.sdk.version
     }
 }
 
-# Try download NuGet.exe if not exists
-if (!(Test-Path $NUGET_EXE)) {
-    Write-Verbose -Message "Downloading NuGet.exe..."
-    try {
-        (New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
-    } catch {
-        Throw "Could not download NuGet.exe."
-    }
+# If dotnet is installed locally, and expected version is not set or installation matches the expected version
+if ((Get-Command "dotnet" -ErrorAction SilentlyContinue) -ne $null -and `
+     (!(Test-Path variable:DotNetVersion) -or $(& dotnet --version) -eq $DotNetVersion)) {
+    $env:DOTNET_EXE = (Get-Command "dotnet").Path
 }
-
-# Save nuget.exe path to environment to be available to child processed
-$ENV:NUGET_EXE = $NUGET_EXE
-
-# Restore tools from NuGet?
-if(-Not $SkipToolPackageRestore.IsPresent) {
-    Push-Location
-    Set-Location $TOOLS_DIR
-
-    # Check for changes in packages.config and remove installed tools if true.
-    [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
-    if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
-      ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
-        Write-Verbose -Message "Missing or changed package.config hash..."
-        Remove-Item * -Recurse -Exclude packages.config,nuget.exe
+else {
+    $DotNetDirectory = "$TempDirectory\dotnet-win"
+    $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
+
+    # Download install script
+    $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
+    md -force $TempDirectory > $null
+    (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
+
+    # Install by channel or version
+    if (!(Test-Path variable:DotNetVersion)) {
+        ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
+    } else {
+        ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
     }
-
-    Write-Verbose -Message "Restoring tools from NuGet..."
-    $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
-
-    if ($LASTEXITCODE -ne 0) {
-        Throw "An error occured while restoring NuGet tools."
-    }
-    else
-    {
-        $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
-    }
-    Write-Verbose -Message ($NuGetOutput | out-string)
-    Pop-Location
 }
 
-# Make sure that Cake has been installed.
-if (!(Test-Path $CAKE_EXE)) {
-    Throw "Could not find Cake.exe at $CAKE_EXE"
-}
+Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)"
 
-# Start Cake
-Write-Host "Running build script..."
-Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -platform=`"$Platform`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseSkipTests $UseMono $UseDryRun $UseExperimental $ScriptArgs"
-exit $LASTEXITCODE
+ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile -- $BuildArguments }

+ 53 - 86
build.sh

@@ -1,105 +1,72 @@
 #!/usr/bin/env bash
 
-##########################################################################
-# This is the Cake bootstrapper script for Linux and OS X.
-# This file was downloaded from https://github.com/cake-build/resources
-# Feel free to change this file to fit your needs.
-##########################################################################
+echo $(bash --version 2>&1 | head -n 1)
 
-# Define directories.
-SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
-TOOLS_DIR=$SCRIPT_DIR/tools
-NUGET_EXE=$TOOLS_DIR/nuget.exe
-CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
-PACKAGES_CONFIG=$TOOLS_DIR/packages.config
-PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum
-
-# Define md5sum or md5 depending on Linux/OSX
-MD5_EXE=
-if [[ "$(uname -s)" == "Darwin" ]]; then
-    MD5_EXE="md5 -r"
-else
-    MD5_EXE="md5sum"
-fi
-
-# Define default arguments.
-SCRIPT="build.cake"
-TARGET="Default"
-CONFIGURATION="Release"
-PLATFORM="Any CPU"
-VERBOSITY="verbose"
-DRYRUN=
-SKIP_TESTS=
-SHOW_VERSION=false
-SCRIPT_ARGUMENTS=()
-
-# Parse arguments.
+#CUSTOMPARAM=0
+BUILD_ARGUMENTS=()
 for i in "$@"; do
-    case $1 in
-        -s|--script) SCRIPT="$2"; shift ;;
-        -t|--target) TARGET="$2"; shift ;;
-        -p|--platform) PLATFORM="$2"; shift ;;
-        -c|--configuration) CONFIGURATION="$2"; shift ;;
-        --skip-tests) SKIP_TESTS="-skip-tests"; shift ;;
-        -v|--verbosity) VERBOSITY="$2"; shift ;;
-        -d|--dryrun) DRYRUN="-dryrun" ;;
-        --version) SHOW_VERSION=true ;;
-        --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;;
-        *) SCRIPT_ARGUMENTS+=("$1") ;;
+    case $(echo $1 | awk '{print tolower($0)}') in
+        # -custom-param) CUSTOMPARAM=1;;
+        *) BUILD_ARGUMENTS+=("$1") ;;
     esac
     shift
 done
 
-# Make sure the tools folder exist.
-if [ ! -d "$TOOLS_DIR" ]; then
-  mkdir "$TOOLS_DIR"
-fi
+set -eo pipefail
+SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
 
-# Make sure that packages.config exist.
-if [ ! -f "$TOOLS_DIR/packages.config" ]; then
-    echo "Downloading packages.config..."
-    curl -Lsfo "$TOOLS_DIR/packages.config" http://cakebuild.net/download/bootstrapper/packages
-    if [ $? -ne 0 ]; then
-        echo "An error occured while downloading packages.config."
-        exit 1
-    fi
-fi
+###########################################################################
+# CONFIGURATION
+###########################################################################
 
-# Download NuGet if it does not exist.
-if [ ! -f "$NUGET_EXE" ]; then
-    echo "Downloading NuGet..."
-    curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
-    if [ $? -ne 0 ]; then
-        echo "An error occured while downloading nuget.exe."
-        exit 1
-    fi
-fi
+BUILD_PROJECT_FILE="$SCRIPT_DIR/nukebuild/_build.csproj"
+TEMP_DIRECTORY="$SCRIPT_DIR//.tmp"
 
-# Restore tools from NuGet.
-pushd "$TOOLS_DIR" >/dev/null
-if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then
-    find . -type d ! -name . | xargs rm -rf
-fi
+DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
+DOTNET_INSTALL_URL="https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.sh"
+DOTNET_CHANNEL="Current"
 
-mono "$NUGET_EXE" install -ExcludeVersion
-if [ $? -ne 0 ]; then
-    echo "Could not restore NuGet packages."
-    exit 1
-fi
+export DOTNET_CLI_TELEMETRY_OPTOUT=1
+export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
+export NUGET_XMLDOC_MODE="skip"
 
-$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5
+###########################################################################
+# EXECUTION
+###########################################################################
 
-popd >/dev/null
+function FirstJsonValue {
+    perl -nle 'print $1 if m{"'$1'": "([^"\-]+)",?}' <<< ${@:2}
+}
 
-# Make sure that Cake has been installed.
-if [ ! -f "$CAKE_EXE" ]; then
-    echo "Could not find Cake.exe at '$CAKE_EXE'."
-    exit 1
+# If global.json exists, load expected version
+if [ -f "$DOTNET_GLOBAL_FILE" ]; then
+    DOTNET_VERSION=$(FirstJsonValue "version" $(cat "$DOTNET_GLOBAL_FILE"))
+    if [ "$DOTNET_VERSION" == ""  ]; then
+        unset DOTNET_VERSION
+    fi
 fi
 
-# Start Cake
-if $SHOW_VERSION; then
-    exec mono "$CAKE_EXE" -version
+# If dotnet is installed locally, and expected version is not set or installation matches the expected version
+if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version) == "$DOTNET_VERSION") ]]; then
+    export DOTNET_EXE="$(command -v dotnet)"
 else
-    exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -platform="$PLATFORM" -configuration="$CONFIGURATION" -target=$TARGET $DRYRUN $SKIP_TESTS "${SCRIPT_ARGUMENTS[@]}"
+    DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
+    export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
+    
+    # Download install script
+    DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
+    mkdir -p "$TEMP_DIRECTORY"
+    curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
+    chmod +x "$DOTNET_INSTALL_FILE"
+    
+    # Install by channel or version
+    if [ -z ${DOTNET_VERSION+x} ]; then
+        "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
+    else
+        "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
+    fi
 fi
+
+echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)"
+
+"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]}

+ 8 - 0
build/BuildTargets.targets

@@ -0,0 +1,8 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <AvaloniaBuildTasksLocation>$(MSBuildThisFileDirectory)\..\src\Avalonia.Build.Tasks\bin\$(Configuration)\netstandard2.0\Avalonia.Build.Tasks.dll</AvaloniaBuildTasksLocation>
+    <AvaloniaUseExternalMSBuild>true</AvaloniaUseExternalMSBuild>
+  </PropertyGroup>
+  <Import Project="$(MSBuildThisFileDirectory)\..\packages\Avalonia\AvaloniaBuildTasks.props"/>
+  <Import Project="$(MSBuildThisFileDirectory)\..\packages\Avalonia\AvaloniaBuildTasks.targets"/>
+</Project>

+ 1 - 1
build/Magick.NET-Q16-AnyCPU.props

@@ -1,5 +1,5 @@
 <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.0.6.102" />
+    <PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.9.0.2" />
   </ItemGroup>
 </Project>

+ 5 - 0
build/NetFX.props

@@ -3,4 +3,9 @@
     <FrameworkPathOverride>/usr/lib/mono/4.6.1-api</FrameworkPathOverride>
     <FrameworkPathOverride Condition="$([MSBuild]::IsOsPlatform('OSX'))">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api</FrameworkPathOverride>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(TargetFramework)' == 'net47' and '$(OS)' == 'Unix' ">
+    <FrameworkPathOverride>/usr/lib/mono/4.7-api/</FrameworkPathOverride>
+    <FrameworkPathOverride Condition="$([MSBuild]::IsOsPlatform('OSX'))">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.7-api</FrameworkPathOverride>
+  </PropertyGroup>
+
 </Project>

+ 0 - 1
build/ReferenceCoreLibraries.props

@@ -1,5 +1,4 @@
 <Project>
-  <Import Condition="'$(TargetFramework)' == 'netcoreapp2.0'" Project="CoreLibraries.props" />
   <ItemGroup>
       <ProjectReference Include="$(MSBuildThisFileDirectory)../packages/Avalonia/Avalonia.csproj" />
   </ItemGroup>

+ 2 - 2
build/SkiaSharp.props

@@ -1,6 +1,6 @@
 <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <PackageReference Include="SkiaSharp" Version="1.60.0" />
-    <PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="Avalonia.Skia.Linux.Natives" Version="1.60.0.1" />
+    <PackageReference Include="SkiaSharp" Version="1.68.0" />
+    <PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="Avalonia.Skia.Linux.Natives" Version="1.68.0.1" />
   </ItemGroup>
 </Project>

+ 8 - 0
build/UnitTests.NetFX.props

@@ -0,0 +1,8 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildThisFileDirectory)/NetFX.props" />	
+  <ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
+    <Content Include="$(MSBuildThisFileDirectory)/xunit.runner.mono.json" Link="xunit.runner.json" >
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+</Project>

+ 1 - 0
build/xunit.runner.mono.json

@@ -0,0 +1 @@
+{ "appDomain": "denied" }

+ 0 - 15
cake.config

@@ -1,15 +0,0 @@
-; This is the default configuration file for Cake.
-; This file was downloaded from https://github.com/cake-build/resources
-
-[Nuget]
-Source=https://api.nuget.org/v3/index.json
-UseInProcessClient=true
-LoadDependencies=false
-
-[Paths]
-Tools=./tools
-Addins=./tools/Addins
-Modules=./tools/Modules
-
-[Settings]
-SkipVerification=false

+ 1 - 1
global.json

@@ -1,7 +1,7 @@
 {
     "msbuild-sdks": {
         "Microsoft.Build.Traversal": "1.0.43",
-        "MSBuild.Sdk.Extras": "1.6.46",
+        "MSBuild.Sdk.Extras": "1.6.65",
         "AggregatePackage.NuGet.Sdk" : "0.1.12"
     }
 }

+ 10 - 4
native/Avalonia.Native/inc/avalonia-native.h

@@ -173,6 +173,12 @@ public:
     virtual HRESULT ObtainGlFeature(IAvnGlFeature** ppv) = 0;
 };
 
+AVNCOM(IAvnString, 17) : IUnknown
+{
+    virtual HRESULT Pointer(void**retOut) = 0;
+    virtual HRESULT Length(int*ret) = 0;
+};
+
 AVNCOM(IAvnWindowBase, 02) : IUnknown
 {
     virtual HRESULT Show() = 0;
@@ -207,10 +213,10 @@ AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase
 
 AVNCOM(IAvnWindow, 04) : virtual IAvnWindowBase
 {
-    virtual HRESULT ShowDialog (IUnknown**ppv) = 0;
+    virtual HRESULT ShowDialog (IAvnWindow* parent) = 0;
     virtual HRESULT SetCanResize(bool value) = 0;
     virtual HRESULT SetHasDecorations(bool value) = 0;
-    virtual HRESULT SetTitle (const char* title) = 0;
+    virtual HRESULT SetTitle (void* utf8Title) = 0;
     virtual HRESULT SetTitleBarColor (AvnColor color) = 0;
     virtual HRESULT SetWindowState(AvnWindowState state) = 0;
     virtual HRESULT GetWindowState(AvnWindowState*ret) = 0;
@@ -315,8 +321,8 @@ AVNCOM(IAvnScreens, 0e) : IUnknown
 
 AVNCOM(IAvnClipboard, 0f) : IUnknown
 {
-    virtual HRESULT GetText (void** retOut) = 0;
-    virtual HRESULT SetText (char* text) = 0;
+    virtual HRESULT GetText (IAvnString**ppv) = 0;
+    virtual HRESULT SetText (void* utf8Text) = 0;
     virtual HRESULT Clear() = 0;
 };
 

+ 6 - 0
native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj

@@ -9,6 +9,7 @@
 /* Begin PBXBuildFile section */
 		37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; };
 		37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* SystemDialogs.mm */; };
+		37DDA9B0219330F8002E132B /* AvnString.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37DDA9AF219330F8002E132B /* AvnString.mm */; };
 		37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37E2330E21583241000CB7E2 /* KeyTransform.mm */; };
 		5B21A982216530F500CEE36E /* cursor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B21A981216530F500CEE36E /* cursor.mm */; };
 		5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */; };
@@ -26,6 +27,8 @@
 		37A517B22159597E00FBA241 /* Screens.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Screens.mm; sourceTree = "<group>"; };
 		37C09D8721580FE4006A6758 /* SystemDialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemDialogs.mm; sourceTree = "<group>"; };
 		37C09D8A21581EF2006A6758 /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = "<group>"; };
+		37DDA9AF219330F8002E132B /* AvnString.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnString.mm; sourceTree = "<group>"; };
+		37DDA9B121933371002E132B /* AvnString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnString.h; sourceTree = "<group>"; };
 		37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = "<group>"; };
 		5B21A981216530F500CEE36E /* cursor.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cursor.mm; sourceTree = "<group>"; };
 		5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard.mm; sourceTree = "<group>"; };
@@ -65,6 +68,8 @@
 		AB7A61E62147C814003C5833 = {
 			isa = PBXGroup;
 			children = (
+				37DDA9B121933371002E132B /* AvnString.h */,
+				37DDA9AF219330F8002E132B /* AvnString.mm */,
 				37A4E71A2178846A00EACBCD /* headers */,
 				AB573DC3217605E400D389A2 /* gl.mm */,
 				5BF943652167AD1D009CAE35 /* cursor.h */,
@@ -161,6 +166,7 @@
 			files = (
 				5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */,
 				5B21A982216530F500CEE36E /* cursor.mm in Sources */,
+				37DDA9B0219330F8002E132B /* AvnString.mm in Sources */,
 				AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */,
 				37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */,
 				37A517B32159597E00FBA241 /* Screens.mm in Sources */,

+ 14 - 0
native/Avalonia.Native/src/OSX/AvnString.h

@@ -0,0 +1,14 @@
+//
+//  AvnString.h
+//  Avalonia.Native.OSX
+//
+//  Created by Dan Walmsley on 07/11/2018.
+//  Copyright © 2018 Avalonia. All rights reserved.
+//
+
+#ifndef AvnString_h
+#define AvnString_h
+
+extern IAvnString* CreateAvnString(NSString* string);
+
+#endif /* AvnString_h */

+ 55 - 0
native/Avalonia.Native/src/OSX/AvnString.mm

@@ -0,0 +1,55 @@
+//
+//  AvnString.m
+//  Avalonia.Native.OSX
+//
+//  Created by Dan Walmsley on 07/11/2018.
+//  Copyright © 2018 Avalonia. All rights reserved.
+//
+
+#include "common.h"
+
+class AvnStringImpl : public virtual ComSingleObject<IAvnString, &IID_IAvnString>
+{
+private:
+    NSString* _string;
+    
+public:
+    FORWARD_IUNKNOWN()
+    
+    AvnStringImpl(NSString* string)
+    {
+        _string = string;
+    }
+    
+    virtual HRESULT Pointer(void**retOut) override
+    {
+        @autoreleasepool
+        {
+            if(retOut == nullptr)
+            {
+                return E_POINTER;
+            }
+            
+            *retOut = (void*)_string.UTF8String;
+            
+            return S_OK;
+        }
+    }
+    
+    virtual HRESULT Length(int*retOut) override
+    {
+        if(retOut == nullptr)
+        {
+            return E_POINTER;
+        }
+        
+        *retOut = (int)_string.length;
+        
+        return S_OK;
+    }
+};
+
+IAvnString* CreateAvnString(NSString* string)
+{
+    return new AvnStringImpl(string);
+}

+ 12 - 7
native/Avalonia.Native/src/OSX/clipboard.mm

@@ -2,29 +2,34 @@
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
 #include "common.h"
+#include "AvnString.h"
 
 class Clipboard : public ComSingleObject<IAvnClipboard, &IID_IAvnClipboard>
 {
 public:
     FORWARD_IUNKNOWN()
-    virtual HRESULT GetText (void** retOut) override
+    virtual HRESULT GetText (IAvnString**ppv) override
     {
         @autoreleasepool
         {
-            NSString *str = [[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString];
-            *retOut = (void *)str.UTF8String;
+            if(ppv == nullptr)
+            {
+                return E_POINTER;
+            }
+            
+            *ppv = CreateAvnString([[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]);
+            
+            return S_OK;
         }
-        
-        return S_OK;
     }
     
-    virtual HRESULT SetText (char* text) override
+    virtual HRESULT SetText (void* utf8String) override
     {
         @autoreleasepool
         {
             NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
             [pasteBoard clearContents];
-            [pasteBoard setString:@(text) forType:NSPasteboardTypeString];
+            [pasteBoard setString:[NSString stringWithUTF8String:(const char*)utf8String] forType:NSPasteboardTypeString];
         }
         
         return S_OK;

+ 9 - 0
native/Avalonia.Native/src/OSX/common.h

@@ -31,4 +31,13 @@ extern NSSize ToNSSize (AvnSize s);
 #define NSDebugLog(...) (void)0
 #endif
 
+template<typename T> inline T* objc_cast(id from) {
+    if(from == nil)
+        return nil;
+    if ([from isKindOfClass:[T class]]) {
+        return static_cast<T*>(from);
+    }
+    return nil;
+}
+
 #endif

+ 2 - 4
native/Avalonia.Native/src/OSX/gl.mm

@@ -208,9 +208,8 @@ public:
     
     virtual ~AvnGlRenderingSession()
     {
-        glFlush();
         [_context flushBuffer];
-        [_context setView:nil];
+        [NSOpenGLContext clearCurrentContext];
         CGLUnlockContext([_context CGLContextObj]);
         [_view unlockFocus];
     }
@@ -241,9 +240,8 @@ public:
         auto gl = _context;
         CGLLockContext([_context CGLContextObj]);
         [gl setView: _view];
+        [gl update];
         [gl makeCurrentContext];
-        auto frame = [_view frame];
-        
         *ret = new AvnGlRenderingSession(_window, _view, gl);
         return S_OK;
     }

+ 10 - 14
native/Avalonia.Native/src/OSX/main.mm

@@ -32,27 +32,23 @@ public:
 - (void) do;
 @end
 @implementation ThreadingInitializer
-
-pthread_mutex_t mutex;
-pthread_cond_t cond;
-
+{
+    int _fds[2];
+}
 - (void) runOnce
 {
-    pthread_mutex_lock(&mutex);
-    pthread_cond_signal(&cond);
-    pthread_mutex_unlock(&mutex);
+    char buf[]={0};
+    write(_fds[1], buf, 1);
 }
 
 - (void) do
 {
-    pthread_mutex_init(&mutex, NULL);
-    pthread_cond_init(&cond, NULL);
+    pipe(_fds);
     [[[NSThread alloc] initWithTarget:self selector:@selector(runOnce) object:nil] start];
-    pthread_mutex_lock(&mutex);
-    pthread_cond_wait(&cond, &mutex);
-    pthread_mutex_unlock(&mutex);
-    pthread_cond_destroy(&cond);
-    pthread_mutex_destroy(&mutex);
+    char buf[1];
+    read(_fds[0], buf, 1);
+    close(_fds[0]);
+    close(_fds[1]);
 }
 
 

+ 2 - 0
native/Avalonia.Native/src/OSX/window.h

@@ -18,6 +18,8 @@ class WindowBaseImpl;
 -(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent;
 -(void) setCanBecomeKeyAndMain;
 -(void) pollModalSession: (NSModalSession _Nonnull) session;
+-(void) restoreParentWindow;
+-(bool) shouldTryToHandleEvents;
 @end
 
 struct INSWindowHolder

+ 103 - 47
native/Avalonia.Native/src/OSX/window.mm

@@ -109,6 +109,7 @@ public:
             if(Window != nullptr)
             {
                 [Window orderOut:Window];
+                [Window restoreParentWindow];
             }
             
             return S_OK;
@@ -392,30 +393,6 @@ protected:
     }
 };
 
-class ModalDisposable : public ComUnknownObject
-{
-    NSModalSession _session;
-    AvnWindow* _window;
-    
-    void Dispose ()
-    {
-        [_window orderOut:_window];
-        [NSApp endModalSession:_session];
-    }
-    
-public:
-    ModalDisposable(AvnWindow* window, NSModalSession session)
-    {
-        _session = session;
-        _window = window;
-    }
-    
-    virtual ~ModalDisposable()
-    {
-        Dispose();
-    }
-};
-
 class WindowImpl : public virtual WindowBaseImpl, public virtual IAvnWindow, public IWindowStateChanged
 {
 private:
@@ -444,32 +421,27 @@ private:
     {
         @autoreleasepool
         {
+            if([Window parentWindow] != nil)
+                [[Window parentWindow] removeChildWindow:Window];
             WindowBaseImpl::Show();
             
-            return SetWindowState(_lastWindowState);
+            return SetWindowState(Normal);
         }
     }
     
-    virtual HRESULT ShowDialog (IUnknown**ppv) override
+    virtual HRESULT ShowDialog (IAvnWindow* parent) override
     {
         @autoreleasepool
         {
-            if(ppv == nullptr)
-            {
+            if(parent == nullptr)
                 return E_POINTER;
-            }
-            
-            auto session = [NSApp beginModalSessionForWindow:Window];
-            auto disposable = new ModalDisposable(Window, session);
-            *ppv = disposable;
-            
-            SetPosition(lastPositionSet);
-            UpdateStyle();
-            
-            [Window setTitle:_lastTitle];
-            [Window setTitleVisibility:NSWindowTitleVisible];
+
+            auto cparent = dynamic_cast<WindowImpl*>(parent);
+            if(cparent == nullptr)
+                return E_INVALIDARG;
             
-            [Window pollModalSession:session];
+            [cparent->Window addChildWindow:Window ordered:NSWindowAbove];
+            WindowBaseImpl::Show();
             
             return S_OK;
         }
@@ -530,11 +502,11 @@ private:
         }
     }
     
-    virtual HRESULT SetTitle (const char* title) override
+    virtual HRESULT SetTitle (void* utf8title) override
     {
         @autoreleasepool
         {
-            _lastTitle = [NSString stringWithUTF8String:title];
+            _lastTitle = [NSString stringWithUTF8String:(const char*)utf8title];
             [Window setTitle:_lastTitle];
             [Window setTitleVisibility:NSWindowTitleVisible];
             
@@ -843,8 +815,19 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
     [super viewDidChangeBackingProperties];
 }
 
+- (bool) ignoreUserInput
+{
+    auto parentWindow = objc_cast<AvnWindow>([self window]);
+    if(parentWindow == nil || ![parentWindow shouldTryToHandleEvents])
+        return TRUE;
+    return FALSE;
+}
+
 - (void)mouseEvent:(NSEvent *)event withType:(AvnRawMouseEventType) type
 {
+    if([self ignoreUserInput])
+        return;
+    
     [self becomeFirstResponder];
     auto localPoint = [self convertPoint:[event locationInWindow] toView:self];
     auto avnPoint = [self toAvnPoint:localPoint];
@@ -952,7 +935,9 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
 } 
 
 - (void) keyboardEvent: (NSEvent *) event withType: (AvnRawKeyEventType)type
-{ 
+{
+    if([self ignoreUserInput])
+        return;
     auto key = s_KeyMap[[event keyCode]];
     
     auto timestamp = [event timestamp] * 1000;
@@ -1125,13 +1110,15 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
     {
         ComPtr<WindowBaseImpl> parent = _parent;
         _parent = NULL;
+        [self restoreParentWindow];
         parent->BaseEvents->Closed();
         [parent->View onClosed];
-        [self setContentView: nil];
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [self setContentView: nil];
+        });
     }
 }
 
-
 -(BOOL)canBecomeKeyWindow
 {
     return _canBecomeKeyAndMain;
@@ -1142,10 +1129,79 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
     return _canBecomeKeyAndMain;
 }
 
+-(bool) activateAppropriateChild: (bool)activating
+{
+    for(NSWindow* uch in [self childWindows])
+    {
+        auto ch = objc_cast<AvnWindow>(uch);
+        if(ch == nil)
+            continue;
+        [ch activateAppropriateChild:false];
+        return FALSE;
+    }
+    
+    if(!activating)
+        [self makeKeyAndOrderFront:self];
+    return TRUE;
+}
+
+-(bool)shouldTryToHandleEvents
+{
+    for(NSWindow* uch in [self childWindows])
+    {
+        auto ch = objc_cast<AvnWindow>(uch);
+        if(ch == nil)
+            continue;
+        return FALSE;
+    }
+    return TRUE;
+}
+
+-(void)makeKeyWindow
+{
+    if([self activateAppropriateChild: true])
+    {
+        [super makeKeyWindow];
+    }
+}
+
 -(void)becomeKeyWindow
 {
-    _parent->BaseEvents->Activated();
-    [super becomeKeyWindow];
+    if([self activateAppropriateChild: true])
+    {
+        _parent->BaseEvents->Activated();
+        [super becomeKeyWindow];
+    }
+}
+
+-(void) restoreParentWindow;
+{
+    auto parent = objc_cast<AvnWindow>([self parentWindow]);
+    if(parent != nil)
+    {
+        [parent removeChildWindow:self];
+        [parent activateAppropriateChild: false];
+    }
+}
+
+- (void)windowDidMiniaturize:(NSNotification *)notification
+{
+    auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->());
+    
+    if(parent != nullptr)
+    {
+        parent->WindowStateChanged();
+    }
+}
+
+- (void)windowDidDeminiaturize:(NSNotification *)notification
+{
+    auto parent = dynamic_cast<IWindowStateChanged*>(_parent.operator->());
+    
+    if(parent != nullptr)
+    {
+        parent->WindowStateChanged();
+    }
 }
 
 - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame

+ 8 - 0
nukebuild/.editorconfig

@@ -0,0 +1,8 @@
+# editorconfig.org
+
+# top-most EditorConfig file
+root = false
+
+# C# files
+[*.cs]
+dotnet_style_require_accessibility_modifiers = never

+ 265 - 0
nukebuild/Build.cs

@@ -0,0 +1,265 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Xml.Linq;
+using Nuke.Common;
+using Nuke.Common.Git;
+using Nuke.Common.ProjectModel;
+using Nuke.Common.Tooling;
+using Nuke.Common.Tools.DotNet;
+using Nuke.Common.Tools.MSBuild;
+using Nuke.Common.Utilities;
+using static Nuke.Common.EnvironmentInfo;
+using static Nuke.Common.IO.FileSystemTasks;
+using static Nuke.Common.IO.PathConstruction;
+using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
+using static Nuke.Common.Tools.DotNet.DotNetTasks;
+using static Nuke.Common.Tools.Xunit.XunitTasks;
+
+
+/*
+ Before editing this file, install support plugin for your IDE,
+ running and debugging a particular target (optionally without deps) would be way easier
+ ReSharper/Rider - https://plugins.jetbrains.com/plugin/10803-nuke-support
+ VSCode - https://marketplace.visualstudio.com/items?itemName=nuke.support
+ 
+ */
+
+partial class Build : NukeBuild
+{   
+    BuildParameters Parameters { get; set; }
+    protected override void OnBuildInitialized()
+    {
+        Parameters = new BuildParameters(this);
+        Information("Building version {0} of Avalonia ({1}) using version {2} of Nuke.", 
+            Parameters.Version,
+            Parameters.Configuration,
+            typeof(NukeBuild).Assembly.GetName().Version.ToString());
+
+        if (Parameters.IsLocalBuild)
+        {
+            Information("Repository Name: " + Parameters.RepositoryName);
+            Information("Repository Branch: " + Parameters.RepositoryBranch);
+        }
+        Information("Configuration: " + Parameters.Configuration);
+        Information("IsLocalBuild: " + Parameters.IsLocalBuild);
+        Information("IsRunningOnUnix: " + Parameters.IsRunningOnUnix);
+        Information("IsRunningOnWindows: " + Parameters.IsRunningOnWindows);
+        Information("IsRunningOnAzure:" + Parameters.IsRunningOnAzure);
+        Information("IsPullRequest: " + Parameters.IsPullRequest);
+        Information("IsMainRepo: " + Parameters.IsMainRepo);
+        Information("IsMasterBranch: " + Parameters.IsMasterBranch);
+        Information("IsReleaseBranch: " + Parameters.IsReleaseBranch);
+        Information("IsReleasable: " + Parameters.IsReleasable);
+        Information("IsMyGetRelease: " + Parameters.IsMyGetRelease);
+        Information("IsNuGetRelease: " + Parameters.IsNuGetRelease);
+
+        void ExecWait(string preamble, string command, string args)
+        {
+            Console.WriteLine(preamble);
+            Process.Start(new ProcessStartInfo(command, args) {UseShellExecute = false}).WaitForExit();
+        }
+        ExecWait("dotnet version:", "dotnet", "--version");
+        if (Parameters.IsRunningOnUnix)
+            ExecWait("Mono version:", "mono", "--version");
+
+
+    }
+
+    Target Clean => _ => _.Executes(() =>
+    {
+        DeleteDirectories(Parameters.BuildDirs);
+        EnsureCleanDirectories(Parameters.BuildDirs);
+        EnsureCleanDirectory(Parameters.ArtifactsDir);
+        EnsureCleanDirectory(Parameters.NugetIntermediateRoot);
+        EnsureCleanDirectory(Parameters.NugetRoot);
+        EnsureCleanDirectory(Parameters.ZipRoot);
+        EnsureCleanDirectory(Parameters.TestResultsRoot);
+    });
+
+    Target Compile => _ => _
+        .DependsOn(Clean)
+        .Executes(() =>
+        {
+
+            if (Parameters.IsRunningOnWindows)
+                MSBuild(Parameters.MSBuildSolution, c => c
+                    .SetArgumentConfigurator(a => a.Add("/r"))
+                    .SetConfiguration(Parameters.Configuration)
+                    .SetVerbosity(MSBuildVerbosity.Minimal)
+                    .AddProperty("PackageVersion", Parameters.Version)
+                    .AddProperty("iOSRoslynPathHackRequired", "true")
+                    .SetToolsVersion(MSBuildToolsVersion._15_0)
+                    .AddTargets("Build")
+                );
+
+            else
+                DotNetBuild(Parameters.MSBuildSolution, c => c
+                    .AddProperty("PackageVersion", Parameters.Version)
+                    .SetConfiguration(Parameters.Configuration)
+                );
+        });
+    
+    void RunCoreTest(string project)
+    {
+        if(!project.EndsWith(".csproj"))
+            project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj");
+        Information("Running tests from " + project);
+        XDocument xdoc;
+        using (var s = File.OpenRead(project))
+            xdoc = XDocument.Load(s);
+
+        List<string> frameworks = null;
+        var targets = xdoc.Root.Descendants("TargetFrameworks").FirstOrDefault();
+        if (targets != null)
+            frameworks = targets.Value.Split(';').Where(f => !string.IsNullOrWhiteSpace(f)).ToList();
+        else 
+            frameworks = new List<string> {xdoc.Root.Descendants("TargetFramework").First().Value};
+        
+        foreach(var fw in frameworks)
+        {
+            Information("Running for " + fw);
+            DotNetTest(c =>
+            {
+                c = c
+                    .SetProjectFile(project)
+                    .SetConfiguration(Parameters.Configuration)
+                    .SetFramework(fw)
+                    .EnableNoBuild()
+                    .EnableNoRestore();
+                // NOTE: I can see that we could maybe add another extension method "Switch" or "If" to make this more  convenient
+                if (Parameters.PublishTestResults)
+                    c = c.SetLogger("trx").SetResultsDirectory(Parameters.TestResultsRoot);
+                return c;
+            });
+        }
+    }
+
+    Target RunCoreLibsTests => _ => _
+        .OnlyWhen(() => !Parameters.SkipTests)
+        .DependsOn(Compile)
+        .Executes(() =>
+        {
+            RunCoreTest("./tests/Avalonia.Animation.UnitTests");
+            RunCoreTest("./tests/Avalonia.Base.UnitTests");
+            RunCoreTest("./tests/Avalonia.Controls.UnitTests");
+            RunCoreTest("./tests/Avalonia.Input.UnitTests");
+            RunCoreTest("./tests/Avalonia.Interactivity.UnitTests");
+            RunCoreTest("./tests/Avalonia.Layout.UnitTests");
+            RunCoreTest("./tests/Avalonia.Markup.UnitTests");
+            RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests");
+            RunCoreTest("./tests/Avalonia.Styling.UnitTests");
+            RunCoreTest("./tests/Avalonia.Visuals.UnitTests");
+            RunCoreTest("./tests/Avalonia.Skia.UnitTests");
+            RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests");
+        });
+
+    Target RunRenderTests => _ => _
+        .OnlyWhen(() => !Parameters.SkipTests)
+        .DependsOn(Compile)
+        .Executes(() =>
+        {
+            RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj");
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+                RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj");
+        });
+    
+    Target RunDesignerTests => _ => _
+        .OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows)
+        .DependsOn(Compile)
+        .Executes(() =>
+        {
+            RunCoreTest("./tests/Avalonia.DesignerSupport.Tests");
+        });
+
+    [PackageExecutable("JetBrains.dotMemoryUnit", "dotMemoryUnit.exe")] readonly Tool DotMemoryUnit;
+
+    Target RunLeakTests => _ => _
+        .OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows)
+        .DependsOn(Compile)
+        .Executes(() =>
+        {
+            var testAssembly = "tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll";
+            DotMemoryUnit(
+                $"{XunitPath.DoubleQuoteIfNeeded()} --propagate-exit-code -- {testAssembly}",
+                timeout: 120_000);
+        });
+
+    Target ZipFiles => _ => _
+        .After(CreateNugetPackages, Compile, RunCoreLibsTests, Package)    
+        .Executes(() =>
+        {
+            var data = Parameters;
+            Zip(data.ZipCoreArtifacts, data.BinRoot);
+            Zip(data.ZipNuGetArtifacts, data.NugetRoot);
+            Zip(data.ZipTargetControlCatalogDesktopDir,
+                GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.dll").Concat(
+                    GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.config")).Concat(
+                    GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.so")).Concat(
+                    GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.dylib")).Concat(
+                    GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.exe")));
+        });
+
+    Target CreateIntermediateNugetPackages => _ => _
+        .DependsOn(Compile)
+        .After(RunTests)
+        .Executes(() =>
+        {
+            if (Parameters.IsRunningOnWindows)
+
+                MSBuild(Parameters.MSBuildSolution, c => c
+                    .SetConfiguration(Parameters.Configuration)
+                    .SetVerbosity(MSBuildVerbosity.Minimal)
+                    .AddProperty("PackageVersion", Parameters.Version)
+                    .AddProperty("iOSRoslynPathHackRequired", "true")
+                    .SetToolsVersion(MSBuildToolsVersion._15_0)
+                    .AddTargets("Pack"));
+            else
+                DotNetPack(Parameters.MSBuildSolution, c =>
+                    c.SetConfiguration(Parameters.Configuration)
+                        .AddProperty("PackageVersion", Parameters.Version));
+        });
+
+    Target CreateNugetPackages => _ => _
+        .DependsOn(CreateIntermediateNugetPackages)
+        .Executes(() =>
+        {
+            var config = Numerge.MergeConfiguration.LoadFile(RootDirectory / "nukebuild" / "numerge.config");
+            EnsureCleanDirectory(Parameters.NugetRoot);
+            if(!Numerge.NugetPackageMerger.Merge(Parameters.NugetIntermediateRoot, Parameters.NugetRoot, config,
+                new NumergeNukeLogger()))
+                throw new Exception("Package merge failed");
+        });
+    
+    Target RunTests => _ => _
+        .DependsOn(RunCoreLibsTests)
+        .DependsOn(RunRenderTests)
+        .DependsOn(RunDesignerTests)
+        .DependsOn(RunLeakTests);
+    
+    Target Package => _ => _
+        .DependsOn(RunTests)
+        .DependsOn(CreateNugetPackages);
+    
+    Target CiAzureLinux => _ => _
+        .DependsOn(RunTests);
+    
+    Target CiAzureOSX => _ => _
+        .DependsOn(Package)
+        .DependsOn(ZipFiles);
+    
+    Target CiAzureWindows => _ => _
+        .DependsOn(Package)
+        .DependsOn(ZipFiles);
+
+    
+    public static int Main() =>
+        RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
+            ? Execute<Build>(x => x.Package)
+            : Execute<Build>(x => x.RunTests);
+
+}

+ 142 - 0
nukebuild/BuildParameters.cs

@@ -0,0 +1,142 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Xml.Linq;
+using Nuke.Common;
+using Nuke.Common.BuildServers;
+using Nuke.Common.Execution;
+using Nuke.Common.IO;
+using static Nuke.Common.IO.FileSystemTasks;
+using static Nuke.Common.IO.PathConstruction;
+using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
+
+public partial class Build
+{
+    [Parameter("configuration")]
+    public string Configuration { get; set; }
+    
+    [Parameter("skip-tests")]
+    public bool SkipTests { get; set; }
+    
+    [Parameter("force-nuget-version")]
+    public string ForceNugetVersion { get; set; }
+    
+    public class BuildParameters
+    {
+        public string Configuration { get; }
+        public bool SkipTests { get; }
+        public string MainRepo { get; }
+        public string MasterBranch { get; }
+        public string RepositoryName { get; }
+        public string RepositoryBranch { get; }
+        public string ReleaseConfiguration { get; }
+        public string ReleaseBranchPrefix { get; }
+        public string MSBuildSolution { get; }
+        public bool IsLocalBuild { get; }
+        public bool IsRunningOnUnix { get; }
+        public bool IsRunningOnWindows { get; }
+        public bool IsRunningOnAzure { get; }
+        public bool IsPullRequest { get; }
+        public bool IsMainRepo { get; }
+        public bool IsMasterBranch { get; }
+        public bool IsReleaseBranch { get; }
+        public bool IsReleasable { get; }
+        public bool IsMyGetRelease { get; }
+        public bool IsNuGetRelease { get; }
+        public bool PublishTestResults { get; }
+        public string Version { get; }
+        public AbsolutePath ArtifactsDir { get; }
+        public AbsolutePath NugetIntermediateRoot { get; }
+        public AbsolutePath NugetRoot { get; }
+        public AbsolutePath ZipRoot { get; }
+        public AbsolutePath BinRoot { get; }
+        public AbsolutePath TestResultsRoot { get; }
+        public string DirSuffix { get; }
+        public List<string> BuildDirs { get; }
+        public string FileZipSuffix { get; }
+        public AbsolutePath ZipCoreArtifacts { get; }
+        public AbsolutePath ZipNuGetArtifacts { get; }
+        public AbsolutePath ZipSourceControlCatalogDesktopDir { get; }
+        public AbsolutePath ZipTargetControlCatalogDesktopDir { get; }
+
+
+       public BuildParameters(Build b)
+        {
+            // ARGUMENTS
+            Configuration = b.Configuration ?? "Release";
+            SkipTests = b.SkipTests;
+
+            // CONFIGURATION
+            MainRepo = "https://github.com/AvaloniaUI/Avalonia";
+            MasterBranch = "refs/heads/master";
+            ReleaseBranchPrefix = "refs/heads/release/";
+            ReleaseConfiguration = "Release";
+            MSBuildSolution = RootDirectory / "dirs.proj";
+
+            // PARAMETERS
+            IsLocalBuild = Host == HostType.Console;
+            IsRunningOnUnix = Environment.OSVersion.Platform == PlatformID.Unix ||
+                              Environment.OSVersion.Platform == PlatformID.MacOSX;
+            IsRunningOnWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+            IsRunningOnAzure = Host == HostType.TeamServices ||
+                               Environment.GetEnvironmentVariable("LOGNAME") == "vsts";
+
+            if (IsRunningOnAzure)
+            {
+                RepositoryName = TeamServices.Instance.RepositoryUri;
+                RepositoryBranch = TeamServices.Instance.SourceBranch;
+                IsPullRequest = TeamServices.Instance.PullRequestId.HasValue;
+                IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, TeamServices.Instance.RepositoryUri);
+            }
+            IsMainRepo =
+                StringComparer.OrdinalIgnoreCase.Equals(MainRepo,
+                    RepositoryName);
+            IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch,
+                RepositoryBranch);
+            IsReleaseBranch = RepositoryBranch?.StartsWith(ReleaseBranchPrefix, StringComparison.OrdinalIgnoreCase) ==
+                              true;
+
+            IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration);
+            IsMyGetRelease = IsReleasable;
+            IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch;
+
+            // VERSION
+            Version = b.ForceNugetVersion ?? GetVersion();
+
+            if (IsRunningOnAzure)
+            {
+                if (!IsNuGetRelease)
+                {
+                    // Use AssemblyVersion with Build as version
+                    Version += "-cibuild" + int.Parse(Environment.GetEnvironmentVariable("BUILD_BUILDID")).ToString("0000000") + "-beta";
+                }
+
+                PublishTestResults = true;
+            }
+
+            // DIRECTORIES
+            ArtifactsDir = RootDirectory / "artifacts";
+            NugetRoot = ArtifactsDir / "nuget";
+            NugetIntermediateRoot = RootDirectory / "build-intermediate" / "nuget";
+            ZipRoot = ArtifactsDir / "zip";
+            BinRoot = ArtifactsDir / "bin";
+            TestResultsRoot = ArtifactsDir / "test-results";
+            BuildDirs = GlobDirectories(RootDirectory, "**bin").Concat(GlobDirectories(RootDirectory, "**obj")).ToList();
+            DirSuffix = Configuration;
+            FileZipSuffix = Version + ".zip";
+            ZipCoreArtifacts = ZipRoot / ("Avalonia-" + FileZipSuffix);
+            ZipNuGetArtifacts = ZipRoot / ("Avalonia-NuGet-" + FileZipSuffix);
+            ZipSourceControlCatalogDesktopDir =
+                RootDirectory / ("samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461");
+            ZipTargetControlCatalogDesktopDir = ZipRoot / ("ControlCatalog.Desktop-" + FileZipSuffix);
+        }
+
+        string GetVersion()
+        {
+            var xdoc = XDocument.Load(RootDirectory / "build/SharedVersion.props");
+            return xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value;
+        }
+    }
+
+}

+ 1 - 0
nukebuild/Numerge

@@ -0,0 +1 @@
+Subproject commit 4464343aef5c8ab7a42fcb20a483a6058199f8b8

+ 93 - 0
nukebuild/Shims.cs

@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+using Nuke.Common;
+using Nuke.Common.IO;
+using Numerge;
+
+public partial class Build
+{
+    static void Information(string info)
+    {
+        Logger.Info(info);
+    }
+
+    static void Information(string info, params object[] args)
+    {
+        Logger.Info(info, args);
+    }
+
+    private void Zip(PathConstruction.AbsolutePath target, params string[] paths) => Zip(target, paths.AsEnumerable());
+
+    private void Zip(PathConstruction.AbsolutePath target, IEnumerable<string> paths)
+    {
+        var targetPath = target.ToString();
+        bool finished = false, atLeastOneFileAdded = false;
+        try
+        {
+            using (var targetStream = File.Create(targetPath))
+            using(var archive = new System.IO.Compression.ZipArchive(targetStream, ZipArchiveMode.Create))
+            {
+                void AddFile(string path, string relativePath)
+                {
+                    var e = archive.CreateEntry(relativePath.Replace("\\", "/"), CompressionLevel.Optimal);
+                    using (var entryStream = e.Open())
+                    using (var fileStream = File.OpenRead(path))
+                        fileStream.CopyTo(entryStream);
+                    atLeastOneFileAdded = true;
+                }
+                
+                foreach (var path in paths)
+                {
+                    if (Directory.Exists(path))
+                    {
+                        var dirInfo = new DirectoryInfo(path);
+                        var rootPath = Path.GetDirectoryName(dirInfo.FullName);
+                        foreach(var fsEntry in dirInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories))
+                        {
+                            if (fsEntry is FileInfo)
+                            {
+                                var relPath = Path.GetRelativePath(rootPath, fsEntry.FullName);
+                                AddFile(fsEntry.FullName, relPath);
+                            }
+                        }
+                    }
+                    else if(File.Exists(path))
+                    {
+                        var name = Path.GetFileName(path);
+                        AddFile(path, name);
+                    }
+                }
+            }
+
+            finished = true;
+        }
+        finally 
+        {
+            try
+            {
+                if (!finished || !atLeastOneFileAdded)
+                    File.Delete(targetPath);
+            }
+            catch
+            {
+                //Ignore
+            }
+        }
+    }
+
+    class NumergeNukeLogger : INumergeLogger
+    {
+        public void Log(NumergeLogLevel level, string message)
+        {
+            if(level == NumergeLogLevel.Error)
+                Logger.Error(message);
+            else if (level == NumergeLogLevel.Warning)
+                Logger.Warn(message);
+            else
+                Logger.Info(message);
+        }
+    }
+}

+ 37 - 0
nukebuild/_build.csproj

@@ -0,0 +1,37 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
+    <RootNamespace></RootNamespace>
+    <IsPackable>False</IsPackable>
+    <NoWarn>CS0649;CS0169</NoWarn>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Nuke.Common" Version="0.12.3" />
+    <PackageReference Include="xunit.runner.console" Version="2.3.1" />
+    <PackageReference Include="JetBrains.dotMemoryUnit" Version="3.0.20171219.105559" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <NukeMetadata Include="**\*.json" Exclude="bin\**;obj\**" />
+    <NukeExternalFiles Include="**\*.*.ext" Exclude="bin\**;obj\**" />
+    <None Remove="*.csproj.DotSettings;*.ref.*.txt" />
+    
+    <!-- Common build related files -->
+    <None Include="..\build.ps1" />
+    <None Include="..\build.sh" />
+    <None Include="..\.nuke" />     
+    <None Include="..\global.json" Condition="Exists('..\global.json')" />
+    <None Include="..\nuget.config" Condition="Exists('..\nuget.config')" />
+    <None Include="..\Jenkinsfile" Condition="Exists('..\Jenkinsfile')" />
+    <None Include="..\appveyor.yml" Condition="Exists('..\appveyor.yml')" />
+    <None Include="..\.travis.yml" Condition="Exists('..\.travis.yml')" />
+    <None Include="..\GitVersion.yml" Condition="Exists('..\GitVersion.yml')" />
+    <Compile Remove="Numerge/**/*.*" />
+    <Compile Include="Numerge/Numerge/**/*.cs" />
+  </ItemGroup>
+
+</Project>

+ 24 - 0
nukebuild/_build.csproj.DotSettings

@@ -0,0 +1,24 @@
+<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
+	<s:Boolean x:Key="/Default/CodeInspection/ImplicitNullability/EnableFields/@EntryValue">False</s:Boolean>
+	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_INTERNAL_MODIFIER/@EntryValue">Implicit</s:String>
+	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_PRIVATE_MODIFIER/@EntryValue">Implicit</s:String>
+	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String>
+	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">0</s:String>
+	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String>
+	<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">False</s:Boolean>
+	<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_ATTRIBUTE_LENGTH_FOR_SAME_LINE/@EntryValue">120</s:Int64>
+	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">IF_OWNER_IS_SINGLE_LINE</s:String>
+	<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">WRAP_IF_LONG</s:String>
+	<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

+ 23 - 0
nukebuild/numerge.config

@@ -0,0 +1,23 @@
+{
+  "Packages":
+  [
+    {
+      "Id": "Avalonia",
+      "MergeAll": true,
+      "Exclude": ["Avalonia.Remote.Protocol"],
+      "IncomingIncludeAssetsOverride": "",
+      "Merge": [
+        {
+          "Id": "Avalonia.Build.Tasks",
+          "IgnoreMissingFrameworkBinaries": true,
+          "DoNotMergeDependencies": true
+        },
+        {
+          "Id": "Avalonia.DesktopRuntime",
+          "IgnoreMissingFrameworkBinaries": true,
+          "IgnoreMissingFrameworkDependencies": true
+        }
+      ]
+    }
+  ]
+}

+ 14 - 8
packages/Avalonia/Avalonia.csproj

@@ -1,10 +1,12 @@
-<Project Sdk="AggregatePackage.NuGet.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
       <TargetFrameworks>netstandard2.0;net461;netcoreapp2.0</TargetFrameworks>
   </PropertyGroup>
 
   <ItemGroup>
-      <ProjectReference Include="../../src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj" EmbedReference="false" />
+      <ProjectReference Include="../../src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj"/>
+      <ProjectReference Include="../../src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj" />
+
   </ItemGroup>
 
   <PropertyGroup>
@@ -27,14 +29,18 @@
         <Visible>false</Visible>
         <BuildAction>None</BuildAction>
       </_PackageFiles>
-      <_PackageFiles Include="Avalonia.props">
-        <PackagePath>build/Avalonia.props</PackagePath>
-        <Visible>false</Visible>
-        <BuildAction>None</BuildAction>
-      </_PackageFiles>
     </ItemGroup>
   </Target>
-
+  <ItemGroup>
+    <Content Include="*.props">
+       <Pack>true</Pack>
+       <PackagePath>build\</PackagePath>
+    </Content>
+    <Content Include="*.targets">
+      <Pack>true</Pack>
+      <PackagePath>build\</PackagePath>
+    </Content>
+  </ItemGroup>
   <Import Project="..\..\build\SharedVersion.props" />
   <Import Project="..\..\build\NetFX.props" />
   <Import Project="..\..\build\CoreLibraries.props" />

+ 3 - 0
packages/Avalonia/Avalonia.props

@@ -2,5 +2,8 @@
   <PropertyGroup>
     <AvaloniaPreviewerNetCoreToolPath>$(MSBuildThisFileDirectory)\..\tools\netcoreapp2.0\designer\Avalonia.Designer.HostApp.dll</AvaloniaPreviewerNetCoreToolPath>
     <AvaloniaPreviewerNetFullToolPath>$(MSBuildThisFileDirectory)\..\tools\net461\designer\Avalonia.Designer.HostApp.exe</AvaloniaPreviewerNetFullToolPath>
+    <AvaloniaBuildTasksLocation>$(MSBuildThisFileDirectory)\..\tools\netstandard2.0\Avalonia.Build.Tasks.dll</AvaloniaBuildTasksLocation>
+    <AvaloniaUseExternalMSBuild>false</AvaloniaUseExternalMSBuild>
   </PropertyGroup>
+  <Import Project="$(MSBuildThisFileDirectory)\AvaloniaBuildTasks.props"/>
 </Project>

+ 3 - 0
packages/Avalonia/Avalonia.targets

@@ -0,0 +1,3 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildThisFileDirectory)\AvaloniaBuildTasks.targets"/>
+</Project>

+ 3 - 0
packages/Avalonia/AvaloniaBuildTasks.props

@@ -0,0 +1,3 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+</Project>

+ 43 - 0
packages/Avalonia/AvaloniaBuildTasks.targets

@@ -0,0 +1,43 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <_AvaloniaUseExternalMSBuild>$(AvaloniaUseExternalMSBuild)</_AvaloniaUseExternalMSBuild>
+    <_AvaloniaUseExternalMSBuild Condition="'$(_AvaloniaForceInternalMSBuild)' == 'true'">false</_AvaloniaUseExternalMSBuild>
+  </PropertyGroup>
+  
+  <UsingTask TaskName="GenerateAvaloniaResourcesTask"
+             AssemblyFile="$(AvaloniaBuildTasksLocation)"
+             />
+
+
+  <Target Name="AddAvaloniaResources" BeforeTargets="ResolveReferences">
+    <PropertyGroup>
+      <AvaloniaResourcesTemporaryFilePath Condition="'$(AvaloniaResourcesTemporaryFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/resources</AvaloniaResourcesTemporaryFilePath>
+    </PropertyGroup>
+    <ItemGroup>
+      <EmbeddedResource Include="$(AvaloniaResourcesTemporaryFilePath)">
+        <LogicalName>!AvaloniaResources</LogicalName>
+      </EmbeddedResource>
+    </ItemGroup>
+  </Target>
+  
+  <Target Name="GenerateAvaloniaResources" 
+          BeforeTargets="CoreCompile;CoreResGen"
+          Inputs="@(AvaloniaResource);$(MSBuildAllProjects)"
+          Outputs="$(AvaloniaResourcesTemporaryFilePath)"
+          DependsOnTargets="$(BuildAvaloniaResourcesDependsOn);AddAvaloniaResources;ResolveReferences">
+    <GenerateAvaloniaResourcesTask
+      Condition="'$(_AvaloniaUseExternalMSBuild)' != 'true'"
+      Output="$(AvaloniaResourcesTemporaryFilePath)"
+      Root="$(MSBuildProjectDirectory)"
+      Resources="@(AvaloniaResource)"
+      EmbeddedResources="@(EmbeddedResources)"/>
+    <Exec 
+      Condition="'$(_AvaloniaUseExternalMSBuild)' == 'true'"
+      Command="dotnet msbuild /nodereuse:false $(MSBuildProjectFile) /t:GenerateAvaloniaResources /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=$(Configuration)"/>
+
+  </Target>
+  
+  <ItemGroup>
+    <UpToDateCheckInput Include="@(AvaloniaResource)" />
+  </ItemGroup>
+</Project>

+ 0 - 129
parameters.cake

@@ -1,129 +0,0 @@
-using System.Xml.Linq;
-using System.Linq;
-
-public class Parameters
-{
-    public string Configuration { get; private set; }
-    public bool SkipTests { get; private set; }
-    public string MainRepo { get; private set; }
-    public string MasterBranch { get; private set; }
-    public string ReleasePlatform { get; private set; }
-    public string ReleaseConfiguration { get; private set; }
-    public string ReleaseBranchPrefix { get; private set; }
-    public string MSBuildSolution { get; private set; }
-    public bool IsLocalBuild { get; private set; }
-    public bool IsRunningOnUnix { get; private set; }
-    public bool IsRunningOnWindows { get; private set; }
-    public bool IsRunningOnAppVeyor { get; private set; }
-    public bool IsRunningOnAzure { get; private set; }
-    public bool IsPullRequest { get; private set; }
-    public bool IsMainRepo { get; private set; }
-    public bool IsMasterBranch { get; private set; }
-    public bool IsReleaseBranch { get; private set; }
-    public bool IsTagged { get; private set; }
-    public bool IsReleasable { get; private set; }
-    public bool IsMyGetRelease { get; private set; }
-    public bool IsNuGetRelease { get; private set; }
-    public bool PublishTestResults { get; private set; }
-    public string Version { get; private set; } 
-    public DirectoryPath ArtifactsDir { get; private set; }
-    public DirectoryPath NugetRoot { get; private set; }
-    public DirectoryPath ZipRoot { get; private set; }
-    public DirectoryPath BinRoot { get; private set; }
-    public DirectoryPath TestResultsRoot { get; private set; }
-    public string DirSuffix { get; private set; }
-    public DirectoryPathCollection BuildDirs { get; private set; }
-    public string FileZipSuffix { get; private set; }
-    public FilePath ZipCoreArtifacts { get; private set; }
-    public FilePath ZipNuGetArtifacts { get; private set; }
-    public DirectoryPath ZipSourceControlCatalogDesktopDirs { get; private set; }
-    public FilePath ZipTargetControlCatalogDesktopDirs { get; private set; }
-
-    public Parameters(ICakeContext context)
-    {
-        var buildSystem = context.BuildSystem();
-
-        // ARGUMENTS
-        Configuration = context.Argument("configuration", "Release");
-        SkipTests = context.HasArgument("skip-tests");
-
-        // CONFIGURATION
-        MainRepo = "https://github.com/AvaloniaUI/Avalonia";
-        MasterBranch = "master";
-        ReleaseBranchPrefix = "refs/heads/release/";
-        ReleaseConfiguration = "Release";
-        MSBuildSolution = "./dirs.proj";
-
-        // PARAMETERS
-        IsLocalBuild = buildSystem.IsLocalBuild;
-        IsRunningOnUnix = context.IsRunningOnUnix();
-        IsRunningOnWindows = context.IsRunningOnWindows();
-        IsRunningOnAppVeyor = buildSystem.AppVeyor.IsRunningOnAppVeyor;
-        IsRunningOnAzure = buildSystem.IsRunningOnVSTS || buildSystem.IsRunningOnTFS || context.EnvironmentVariable("LOGNAME") == "vsts";
-        
-        IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest;
-        IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, context.EnvironmentVariable("BUILD_REPOSITORY_URI"));
-        IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME"));
-        IsReleaseBranch = (context.EnvironmentVariable("BUILD_SOURCEBRANCH")??"").StartsWith(ReleaseBranchPrefix, StringComparison.OrdinalIgnoreCase);
-        IsTagged = buildSystem.AppVeyor.Environment.Repository.Tag.IsTag 
-                && !string.IsNullOrWhiteSpace(buildSystem.AppVeyor.Environment.Repository.Tag.Name);
-        IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration);
-        IsMyGetRelease = !IsTagged && IsReleasable;
-        IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch;
-
-        // VERSION
-        Version = context.Argument("force-nuget-version", GetVersion());
-
-        if (IsRunningOnAppVeyor)
-        {
-            string tagVersion = null;
-            if (IsTagged)
-            {
-                var tag = buildSystem.AppVeyor.Environment.Repository.Tag.Name;
-                var nugetReleasePrefix = "nuget-release-";
-                IsNuGetRelease = IsTagged && IsReleasable && tag.StartsWith(nugetReleasePrefix);
-                if(IsNuGetRelease)
-                    tagVersion = tag.Substring(nugetReleasePrefix.Length);
-            }
-            if(tagVersion != null)
-            {
-                Version = tagVersion;
-            }
-            else
-            {
-                // Use AssemblyVersion with Build as version
-                Version += "-build" + context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-beta";
-            }
-        }
-        else if (IsRunningOnAzure)
-        {
-            if(!IsNuGetRelease)
-            {
-                // Use AssemblyVersion with Build as version
-                Version += "-build" + context.EnvironmentVariable("BUILD_BUILDID") + "-beta";
-            }
-
-            PublishTestResults = true; 
-        }
-
-        // DIRECTORIES
-        ArtifactsDir = (DirectoryPath)context.Directory("./artifacts");
-        NugetRoot = ArtifactsDir.Combine("nuget");
-        ZipRoot = ArtifactsDir.Combine("zip");
-        BinRoot = ArtifactsDir.Combine("bin");
-        TestResultsRoot = ArtifactsDir.Combine("test-results");
-        BuildDirs = context.GetDirectories("**/bin") + context.GetDirectories("**/obj");
-        DirSuffix = Configuration;
-        FileZipSuffix = Version + ".zip";
-        ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix);
-        ZipNuGetArtifacts = ZipRoot.CombineWithFilePath("Avalonia-NuGet-" + FileZipSuffix);
-        ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461");
-        ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix);
-    }
-
-    private static string GetVersion()
-    {
-        var xdoc = XDocument.Load("./build/SharedVersion.props");
-        return xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value;
-    }
-}

+ 3 - 3
readme.md

@@ -2,9 +2,9 @@
 
 # Avalonia
 
-| Gitter Chat | Build Status (Win, Linux, OSX) | Appveyor Build Status | Open Collective |
-|---|---|---|---|
-|  [![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://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) |
+| Gitter Chat | Build Status (Win, Linux, OSX) | Open Collective | NuGet | MyGet |
+|---|---|---|---|---|
+|  [![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://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) | [![NuGet](https://img.shields.io/nuget/v/Avalonia.svg)](https://www.nuget.org/packages/Avalonia) | [![MyGet](https://img.shields.io/myget/avalonia-ci/vpre/Avalonia.svg?label=myget)](https://www.myget.org/gallery/avalonia-ci) |
 
 ## About
 

+ 1 - 1
samples/ControlCatalog.Desktop/Program.cs

@@ -22,7 +22,7 @@ namespace ControlCatalog
         /// This method is needed for IDE previewer infrastructure
         /// </summary>
         public static AppBuilder BuildAvaloniaApp()
-            => AppBuilder.Configure<App>().LogToDebug().UsePlatformDetect();
+            => AppBuilder.Configure<App>().LogToDebug().UsePlatformDetect().UseReactiveUI();
 
         private static void ConfigureAssetAssembly(AppBuilder builder)
         {

+ 1 - 0
samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj

@@ -9,6 +9,7 @@
     <ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
     <ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
     <ProjectReference Include="..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" />
   </ItemGroup>
 
 

+ 8 - 2
samples/ControlCatalog.NetCore/Program.cs

@@ -23,6 +23,7 @@ namespace ControlCatalog.NetCore
                         break;
                 }
             }
+
             if (args.Contains("--fbdev"))
                 AppBuilder.Configure<App>().InitializeWithLinuxFramebuffer(tl =>
                 {
@@ -30,7 +31,12 @@ namespace ControlCatalog.NetCore
                     System.Threading.ThreadPool.QueueUserWorkItem(_ => ConsoleSilencer());
                 });
             else
-                BuildAvaloniaApp().Start<MainWindow>();
+                BuildAvaloniaApp().Start(AppMain, args);
+        }
+
+        static void AppMain(Application app, string[] args)
+        {
+            app.Run(new MainWindow());
         }
 
         /// <summary>
@@ -46,4 +52,4 @@ namespace ControlCatalog.NetCore
                 Console.ReadKey(true);
         }
     }
-}
+}

+ 6 - 4
samples/ControlCatalog/App.xaml

@@ -1,7 +1,9 @@
-<Application xmlns="https://github.com/avaloniaui">
+<Application xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.App">
   <Application.Styles>
-    <StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/>
-    <StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
+      <StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
+      <StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
     <Style Selector="TextBlock.h1">
       <Setter Property="FontSize" Value="{DynamicResource FontSizeLarge}"/>
       <Setter Property="FontWeight" Value="Medium"/>
@@ -12,6 +14,6 @@
     <Style Selector="TextBlock.h3">
       <Setter Property="FontSize" Value="{DynamicResource FontSizeSmall}"/>
     </Style>
-    <StyleInclude Source="resm:ControlCatalog.SideBar.xaml"/>
+    <StyleInclude Source="/SideBar.xaml"/>
   </Application.Styles>
 </Application>

+ 5 - 3
samples/ControlCatalog/ControlCatalog.csproj

@@ -6,10 +6,11 @@
     <Compile Update="**\*.xaml.cs">
       <DependentUpon>%(Filename)</DependentUpon>
     </Compile>
-    <EmbeddedResource Include="**\*.xaml">
+    <AvaloniaResource Include="**\*.xaml">
       <SubType>Designer</SubType>
-    </EmbeddedResource>
-    <EmbeddedResource Include="Assets\*" />
+    </AvaloniaResource>
+    <AvaloniaResource Include="Assets\*" />
+    <AvaloniaResource Include="Assets\Fonts\*" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Assets\Fonts\SourceSansPro-Bold.ttf" />
@@ -24,4 +25,5 @@
   </ItemGroup>
   
   <Import Project="..\..\build\Serilog.props" />
+  <Import Project="..\..\build\BuildTargets.targets" />
 </Project>

+ 12 - 5
samples/ControlCatalog/DecoratedWindow.xaml

@@ -1,7 +1,8 @@
-<Window xmlns="https://github.com/avaloniaui" MinWidth="500" MinHeight="300"
+<Window xmlns="https://github.com/avaloniaui" MinWidth="500" MinHeight="300"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        x:Class="ControlCatalog.DecoratedWindow"
         Title="Avalonia Control Gallery"
-        Icon="resm:ControlCatalog.Assets.test_icon.ico"
-        xmlns:local="clr-namespace:ControlCatalog" HasSystemDecorations="False">
+        xmlns:local="clr-namespace:ControlCatalog" HasSystemDecorations="False" Name="Window">
     <Grid RowDefinitions="5,*,5" ColumnDefinitions="5,*,5">
         <DockPanel  Grid.Column="1"  Grid.Row="1" >
             <Grid Name="TitleBar" Background="LightBlue" DockPanel.Dock="Top" ColumnDefinitions="Auto,*,Auto">
@@ -18,7 +19,13 @@
                 </StackPanel>
             </Grid>
             <Border Background="White" Margin="5">
-                <TextBlock>Hello world!</TextBlock>
+                <StackPanel>
+                    <TextBlock>Hello world!</TextBlock>
+
+                    <CheckBox IsChecked="{Binding ElementName=Window, Path=HasSystemDecorations}">Decorated</CheckBox>
+
+                    <CheckBox IsChecked="{Binding ElementName=Window, Path=CanResize}">CanResize</CheckBox>
+                </StackPanel>
             </Border>
         </DockPanel>
         <Border Name="TopLeft" Background="Red"/>
@@ -30,4 +37,4 @@
         <Border Name="Bottom" Background="Blue" Grid.Row="2" Grid.Column="1"  />
         <Border Name="Left" Background="Blue"  Grid.Row="1" />
     </Grid>
-</Window>
+</Window>

+ 39 - 30
samples/ControlCatalog/MainView.xaml

@@ -1,33 +1,42 @@
 <UserControl xmlns="https://github.com/avaloniaui"
         xmlns:pages="clr-namespace:ControlCatalog.Pages"
-        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
-  <TabControl Classes="sidebar" Name="Sidebar">
-    <TabControl.PageTransition>
-      <CrossFade Duration="0.25"/>
-    </TabControl.PageTransition>
-    <TabItem Header="AutoCompleteBox"><pages:AutoCompleteBoxPage/></TabItem>
-    <TabItem Header="Border"><pages:BorderPage/></TabItem>
-    <TabItem Header="Button"><pages:ButtonPage/></TabItem>
-    <TabItem Header="ButtonSpinner"><pages:ButtonSpinnerPage/></TabItem>
-    <TabItem Header="Calendar"><pages:CalendarPage/></TabItem>
-    <TabItem Header="Canvas"><pages:CanvasPage/></TabItem>
-    <TabItem Header="Carousel"><pages:CarouselPage/></TabItem>
-    <TabItem Header="CheckBox"><pages:CheckBoxPage/></TabItem>
-    <TabItem Header="ContextMenu"><pages:ContextMenuPage/></TabItem>
-    <TabItem Header="DatePicker"><pages:DatePickerPage/></TabItem>
-    <TabItem Header="Drag+Drop"><pages:DragAndDropPage/></TabItem>
-    <TabItem Header="DropDown"><pages:DropDownPage/></TabItem>
-    <TabItem Header="Expander"><pages:ExpanderPage/></TabItem>
-    <TabItem Header="Image"><pages:ImagePage/></TabItem>
-    <TabItem Header="LayoutTransformControl"><pages:LayoutTransformControlPage/></TabItem>
-    <TabItem Header="ListBox"><pages:ListBoxPage/></TabItem>
-    <TabItem Header="Menu"><pages:MenuPage/></TabItem>
-	<TabItem Header="NumericUpDown"><pages:NumericUpDownPage/></TabItem>
-    <TabItem Header="ProgressBar"><pages:ProgressBarPage/></TabItem>
-    <TabItem Header="RadioButton"><pages:RadioButtonPage/></TabItem>
-    <TabItem Header="Slider"><pages:SliderPage/></TabItem>
-    <TabItem Header="TextBox"><pages:TextBoxPage/></TabItem>
-    <TabItem Header="ToolTip"><pages:ToolTipPage/></TabItem>
-    <TabItem Header="TreeView"><pages:TreeViewPage/></TabItem>
-  </TabControl>
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        x:Class="ControlCatalog.MainView"
+        Background="{DynamicResource ThemeBackgroundBrush}"
+        Foreground="{DynamicResource ThemeForegroundBrush}"
+        FontSize="{DynamicResource FontSizeNormal}">
+  <Grid>
+    <DropDown x:Name="Themes" SelectedIndex="0" Width="100" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Bottom">
+      <DropDownItem>Light</DropDownItem>
+      <DropDownItem>Dark</DropDownItem>
+    </DropDown>
+    <TabControl Classes="sidebar" Name="Sidebar">
+      <TabItem Header="AutoCompleteBox"><pages:AutoCompleteBoxPage/></TabItem>
+      <TabItem Header="Border"><pages:BorderPage/></TabItem>
+      <TabItem Header="Button"><pages:ButtonPage/></TabItem>
+      <TabItem Header="ButtonSpinner"><pages:ButtonSpinnerPage/></TabItem>
+      <TabItem Header="Calendar"><pages:CalendarPage/></TabItem>
+      <TabItem Header="Canvas"><pages:CanvasPage/></TabItem>
+      <TabItem Header="Carousel"><pages:CarouselPage/></TabItem>
+      <TabItem Header="CheckBox"><pages:CheckBoxPage/></TabItem>
+      <TabItem Header="ContextMenu"><pages:ContextMenuPage/></TabItem>
+      <TabItem Header="DatePicker"><pages:DatePickerPage/></TabItem>
+      <TabItem Header="Drag+Drop"><pages:DragAndDropPage/></TabItem>
+      <TabItem Header="DropDown"><pages:DropDownPage/></TabItem>
+      <TabItem Header="Expander"><pages:ExpanderPage/></TabItem>
+      <TabItem Header="Image"><pages:ImagePage/></TabItem>
+      <TabItem Header="LayoutTransformControl"><pages:LayoutTransformControlPage/></TabItem>
+      <TabItem Header="ListBox"><pages:ListBoxPage/></TabItem>
+      <TabItem Header="Menu"><pages:MenuPage/></TabItem>
+	  <TabItem Header="NumericUpDown"><pages:NumericUpDownPage/></TabItem>
+      <TabItem Header="ProgressBar"><pages:ProgressBarPage/></TabItem>
+      <TabItem Header="RadioButton"><pages:RadioButtonPage/></TabItem>
+      <TabItem Header="Slider"><pages:SliderPage/></TabItem>
+      <TabItem Header="TabControl"><pages:TabControlPage/></TabItem>
+      <TabItem Header="TextBox"><pages:TextBoxPage/></TabItem>
+      <TabItem Header="ToolTip"><pages:ToolTipPage/></TabItem>
+      <TabItem Header="TreeView"><pages:TreeViewPage/></TabItem>
+      <TabItem Header="Viewbox"><pages:ViewboxPage/></TabItem>
+    </TabControl>
+  </Grid>
 </UserControl>

+ 17 - 0
samples/ControlCatalog/MainView.xaml.cs

@@ -2,6 +2,7 @@ using System.Collections;
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Markup.Xaml;
+using Avalonia.Markup.Xaml.Styling;
 using Avalonia.Platform;
 using ControlCatalog.Pages;
 
@@ -27,6 +28,22 @@ namespace ControlCatalog
                 });
 
             }
+            var light = AvaloniaXamlLoader.Parse<StyleInclude>(@"<StyleInclude xmlns='https://github.com/avaloniaui' Source='resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default'/>");
+            var dark = AvaloniaXamlLoader.Parse<StyleInclude>(@"<StyleInclude xmlns='https://github.com/avaloniaui' Source='resm:Avalonia.Themes.Default.Accents.BaseDark.xaml?assembly=Avalonia.Themes.Default'/>");
+            var themes = this.Find<DropDown>("Themes");
+            themes.SelectionChanged += (sender, e) =>
+            {
+                switch (themes.SelectedIndex)
+                {
+                    case 0:
+                        Styles[0] = light;
+                        break;
+                    case 1:
+                        Styles[0] = dark;
+                        break;
+                }
+            };
+            Styles.Add(light);
         }
 
         private void InitializeComponent()

+ 5 - 3
samples/ControlCatalog/MainWindow.xaml

@@ -1,6 +1,8 @@
 <Window xmlns="https://github.com/avaloniaui" MinWidth="500" MinHeight="300"
         Title="Avalonia Control Gallery"
-        Icon="resm:ControlCatalog.Assets.test_icon.ico?assembly=ControlCatalog"
-        xmlns:local="clr-namespace:ControlCatalog">
+        Icon="/Assets/test_icon.ico"
+        xmlns:local="clr-namespace:ControlCatalog"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        x:Class="ControlCatalog.MainWindow">
     <local:MainView/>
-</Window>
+</Window>

+ 3 - 1
samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.AutoCompleteBoxPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">AutoCompleteBox</TextBlock>
     <TextBlock Classes="h2">A control into which the user can input text</TextBlock>

+ 3 - 1
samples/ControlCatalog/Pages/BorderPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.BorderPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">Border</TextBlock>
     <TextBlock Classes="h2">A control which decorates a child with a border and background</TextBlock>

+ 2 - 1
samples/ControlCatalog/Pages/ButtonPage.xaml

@@ -1,5 +1,6 @@
 <UserControl xmlns="https://github.com/avaloniaui"
-             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.ButtonPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">Button</TextBlock>
     <TextBlock Classes="h2">A button control</TextBlock>

+ 2 - 1
samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml

@@ -1,5 +1,6 @@
 <UserControl xmlns="https://github.com/avaloniaui"
-             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.ButtonSpinnerPage">
 
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">ButtonSpinner</TextBlock>

+ 2 - 1
samples/ControlCatalog/Pages/CalendarPage.xaml

@@ -1,5 +1,6 @@
 <UserControl xmlns="https://github.com/avaloniaui"
-             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.CalendarPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">Calendar</TextBlock>
     <TextBlock Classes="h2">A calendar control for selecting dates</TextBlock>

+ 3 - 1
samples/ControlCatalog/Pages/CanvasPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.CanvasPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">Canvas</TextBlock>
     <TextBlock Classes="h2">A panel which lays out its children by explicit coordinates</TextBlock>

+ 6 - 4
samples/ControlCatalog/Pages/CarouselPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.CarouselPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">Carousel</TextBlock>
     <TextBlock Classes="h2">An items control that displays its items as pages that fill the control.</TextBlock>
@@ -11,9 +13,9 @@
         <Carousel.PageTransition>
           <PageSlide Duration="0.25" Orientation="Vertical" />
         </Carousel.PageTransition>
-        <Image Source="resm:ControlCatalog.Assets.delicate-arch-896885_640.jpg"/>
-        <Image Source="resm:ControlCatalog.Assets.hirsch-899118_640.jpg"/>
-        <Image Source="resm:ControlCatalog.Assets.maple-leaf-888807_640.jpg"/>
+        <Image Source="/Assets/delicate-arch-896885_640.jpg"/>
+        <Image Source="/Assets/hirsch-899118_640.jpg"/>
+        <Image Source="/Assets/maple-leaf-888807_640.jpg"/>
       </Carousel>
       <Button Name="right" VerticalAlignment="Center" Padding="20">
         <Path Data="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z" Fill="Black"/>

+ 2 - 1
samples/ControlCatalog/Pages/CheckBoxPage.xaml

@@ -1,5 +1,6 @@
 <UserControl xmlns="https://github.com/avaloniaui"
-             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.CheckBoxPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">CheckBox</TextBlock>
     <TextBlock Classes="h2">A check box control</TextBlock>

+ 4 - 2
samples/ControlCatalog/Pages/ContextMenuPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.ContextMenuPage">
     <StackPanel Orientation="Vertical" Spacing="4">
         <TextBlock Classes="h1">Context Menu</TextBlock>
         <TextBlock Classes="h2">A right click menu that can be applied to any control.</TextBlock>
@@ -19,7 +21,7 @@
                         </MenuItem>
                         <MenuItem Header="Menu Item with _Icon">
                             <MenuItem.Icon>
-                                <Image Source="resm:ControlCatalog.Assets.github_icon.png"/>
+                                <Image Source="/Assets/github_icon.png"/>
                             </MenuItem.Icon>
                         </MenuItem>
                         <MenuItem Header="Menu Item with _Checkbox">

+ 2 - 1
samples/ControlCatalog/Pages/DatePickerPage.xaml

@@ -1,5 +1,6 @@
 <UserControl xmlns="https://github.com/avaloniaui"
-             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.DatePickerPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">DatePicker</TextBlock>
     <TextBlock Classes="h2">A control for selecting dates with a calendar drop-down</TextBlock>

+ 5 - 5
samples/ControlCatalog/Pages/DialogsPage.xaml

@@ -1,12 +1,12 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.DialogsPage">
   <StackPanel Orientation="Vertical" Spacing="4" Margin="4">
       <Button Name="OpenFile">Open File</Button>
       <Button Name="SaveFile">Save File</Button>
       <Button Name="SelectFolder">Select Folder</Button>
-      <StackPanel Orientation="Horizontal">
-          <CheckBox Name="IsModal" IsChecked="True"/>
-          <TextBlock>Modal to window</TextBlock>
-      </StackPanel>
       <Button Name="DecoratedWindow">Decorated window</Button>
+      <Button Name="DecoratedWindowDialog">Decorated window (dialog)</Button>
+      <Button Name="Dialog">Dialog</Button>
   </StackPanel>
 </UserControl>

+ 14 - 1
samples/ControlCatalog/Pages/DialogsPage.xaml.cs

@@ -34,9 +34,22 @@ namespace ControlCatalog.Pages
             {
                 new DecoratedWindow().Show();
             };
+            this.FindControl<Button>("DecoratedWindowDialog").Click += delegate
+            {
+                new DecoratedWindow().ShowDialog(GetWindow());
+            };
+            this.FindControl<Button>("Dialog").Click += delegate
+                {
+                    var window = new Window();
+                    window.Height = 200;
+                    window.Width = 200;
+                    window.Content = new TextBlock { Text = "Hello world!" };
+                    window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
+                    window.ShowDialog(GetWindow());
+                };
         }
 
-        Window GetWindow() => this.FindControl<CheckBox>("IsModal").IsChecked.Value ? (Window)this.VisualRoot : null;
+        Window GetWindow() => (Window)this.VisualRoot;
 
         private void InitializeComponent()
         {

+ 3 - 1
samples/ControlCatalog/Pages/DragAndDropPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.DragAndDropPage">
     <StackPanel Orientation="Vertical" Spacing="4">
         <TextBlock Classes="h1">Drag+Drop</TextBlock>
         <TextBlock Classes="h2">Example of Drag+Drop capabilities</TextBlock>

+ 12 - 1
samples/ControlCatalog/Pages/DropDownPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.DropDownPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">DropDown</TextBlock>
     <TextBlock Classes="h2">A drop-down list.</TextBlock>
@@ -25,6 +27,15 @@
           <TextBox Text="TextBox"/>
         </DropDownItem>
       </DropDown>
+
+
+       <DropDown x:Name="fontDropDown"  SelectedIndex="0">
+            <DropDown.ItemTemplate>
+                <DataTemplate>
+                    <TextBlock Text="{Binding Name}" FontFamily="{Binding}" />
+                </DataTemplate>
+            </DropDown.ItemTemplate>
+       </DropDown>
     </StackPanel>
 
   </StackPanel>

+ 3 - 0
samples/ControlCatalog/Pages/DropDownPage.xaml.cs

@@ -13,6 +13,9 @@ namespace ControlCatalog.Pages
         private void InitializeComponent()
         {
             AvaloniaXamlLoader.Load(this);
+            var fontDropDown = this.Find<DropDown>("fontDropDown");
+            fontDropDown.Items = Avalonia.Media.FontFamily.SystemFontFamilies;
+            fontDropDown.SelectedIndex = 0;
         }
     }
 }

+ 3 - 1
samples/ControlCatalog/Pages/ExpanderPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.ExpanderPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">Expander</TextBlock>
     <TextBlock Classes="h2">Expands to show nested content</TextBlock>

+ 8 - 6
samples/ControlCatalog/Pages/ImagePage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.ImagePage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">Image</TextBlock>
     <TextBlock Classes="h2">Displays an image</TextBlock>
@@ -9,28 +11,28 @@
                 Spacing="16">
       <StackPanel Orientation="Vertical">
         <TextBlock>No Stretch</TextBlock>
-        <Image Source="resm:ControlCatalog.Assets.delicate-arch-896885_640.jpg"
+        <Image Source="/Assets/delicate-arch-896885_640.jpg"
                Width="100" Height="200"
                Stretch="None"/>
       </StackPanel>
 
       <StackPanel Orientation="Vertical">
         <TextBlock>Fill</TextBlock>
-        <Image Source="resm:ControlCatalog.Assets.delicate-arch-896885_640.jpg"
+        <Image Source="/Assets/delicate-arch-896885_640.jpg"
                Width="100" Height="200"
                Stretch="Fill"/>
       </StackPanel>
 
       <StackPanel Orientation="Vertical">
         <TextBlock>Uniform</TextBlock>
-        <Image Source="resm:ControlCatalog.Assets.delicate-arch-896885_640.jpg"
+        <Image Source="/Assets/delicate-arch-896885_640.jpg"
                 Width="100" Height="200"
                 Stretch="Uniform"/>
       </StackPanel>
 
       <StackPanel Orientation="Vertical">
         <TextBlock>UniformToFill</TextBlock>
-        <Image Source="resm:ControlCatalog.Assets.delicate-arch-896885_640.jpg"
+        <Image Source="/Assets/delicate-arch-896885_640.jpg"
                Width="100" Height="200"
                Stretch="UniformToFill"/>
       </StackPanel>
@@ -40,4 +42,4 @@
       <Image Name="Icon" Width="100" Height="200" Stretch="None" />
     </StackPanel>
   </StackPanel>
-</UserControl>
+</UserControl>

+ 3 - 2
samples/ControlCatalog/Pages/LayoutTransformControlPage.xaml

@@ -1,5 +1,6 @@
 <UserControl xmlns="https://github.com/avaloniaui"
-             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.LayoutTransformControlPage">
   <DockPanel>
     <Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto" Margin="16" DockPanel.Dock="Top">
       <TextBlock Grid.Column="0" Grid.Row="0">Rotation</TextBlock>
@@ -23,4 +24,4 @@
       </LayoutTransformControl>
     </Grid>
   </DockPanel>
-</UserControl>
+</UserControl>

+ 3 - 1
samples/ControlCatalog/Pages/ListBoxPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.ListBoxPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">ListBox</TextBlock>
     <TextBlock Classes="h2">Hosts a collection of ListBoxItem.</TextBlock>

+ 4 - 2
samples/ControlCatalog/Pages/MenuPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.MenuPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">Menu</TextBlock>
     <TextBlock Classes="h2">A window menu</TextBlock>
@@ -19,7 +21,7 @@
                         </MenuItem>
                         <MenuItem Header="Menu Item with _Icon">
                             <MenuItem.Icon>
-                                <Image Source="resm:ControlCatalog.Assets.github_icon.png"/>
+                                <Image Source="/Assets/github_icon.png"/>
                             </MenuItem.Icon>
                         </MenuItem>
                         <MenuItem Header="Menu Item with _Checkbox">

+ 1 - 1
samples/ControlCatalog/Pages/MenuPage.xaml.cs

@@ -83,7 +83,7 @@ namespace ControlCatalog.Pages
         public async Task Open()
         {
             var dialog = new OpenFileDialog();
-            var result = await dialog.ShowAsync();
+            var result = await dialog.ShowAsync(App.Current.MainWindow);
 
             if (result != null)
             {

+ 10 - 9
samples/ControlCatalog/Pages/NumericUpDownPage.xaml

@@ -1,12 +1,13 @@
 <UserControl xmlns="https://github.com/avaloniaui"
-             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.NumericUpDownPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Margin="2" Classes="h1">Numeric up-down control</TextBlock>
     <TextBlock Margin="2" Classes="h2" TextWrapping="Wrap">Numeric up-down control provides a TextBox with button spinners that allow incrementing and decrementing numeric values by using the spinner buttons, keyboard up/down arrows, or mouse wheel.</TextBlock>
 
     <TextBlock Margin="2,5,2,2" FontSize="14" FontWeight="Bold">Features:</TextBlock>
     <Grid Margin="2" ColumnDefinitions="Auto,Auto,Auto,Auto" RowDefinitions="Auto,Auto">
-      <Grid Grid.Row="0" Grid.Column="0" ColumnDefinitions="Auto, Auto" RowDefinitions="35,35,35,35,35">
+      <Grid Grid.Row="0" Grid.Column="0" ColumnDefinitions="Auto, Auto" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
         <TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Margin="2">ShowButtonSpinner:</TextBlock>
         <CheckBox Grid.Row="0" Grid.Column="1" IsChecked="{Binding #upDown.ShowButtonSpinner}" VerticalAlignment="Center" Margin="2"/>
 
@@ -20,7 +21,7 @@
         <CheckBox Grid.Row="3" Grid.Column="1" IsChecked="{Binding #upDown.ClipValueToMinMax}" VerticalAlignment="Center" Margin="2"/>
 
       </Grid>
-      <Grid Grid.Row="0" Grid.Column="1" Margin="10,2,2,2" ColumnDefinitions="Auto, 120" RowDefinitions="35,35,35,35,35">
+      <Grid Grid.Row="0" Grid.Column="1" Margin="10,2,2,2" ColumnDefinitions="Auto, 120" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
         <TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Margin="2">FormatString:</TextBlock>
         <DropDown Grid.Row="0" Grid.Column="1" Items="{Binding Formats}" SelectedItem="{Binding SelectedFormat}"
                   VerticalAlignment="Center" Margin="2">
@@ -49,22 +50,22 @@
         <TextBlock Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" Margin="2">Text:</TextBlock>
         <TextBox Grid.Row="4" Grid.Column="1" Text="{Binding #upDown.Text}" VerticalAlignment="Center" Margin="2" />
       </Grid>
-      <Grid Grid.Row="0" Grid.Column="2" Margin="10,2,2,2" RowDefinitions="35,35,35,35,35" ColumnDefinitions="Auto, 120">
+      <Grid Grid.Row="0" Grid.Column="2" Margin="10,2,2,2" RowDefinitions="Auto,Auto,Auto,Auto,Auto" ColumnDefinitions="Auto, 120">
         <TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Margin="10,2,2,2">Minimum:</TextBlock>
         <NumericUpDown Grid.Row="0" Grid.Column="1" Value="{Binding #upDown.Minimum}"
-                       CultureInfo="{Binding #upDown.CultureInfo}" VerticalAlignment="Center" Height="25" Margin="2" Width="70" HorizontalAlignment="Center"/>
+                       CultureInfo="{Binding #upDown.CultureInfo}" VerticalAlignment="Center" Margin="2" Width="70" HorizontalAlignment="Center"/>
 
         <TextBlock Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Margin="10,2,2,2">Maximum:</TextBlock>
         <NumericUpDown Grid.Row="1" Grid.Column="1" Value="{Binding #upDown.Maximum}"
-                       CultureInfo="{Binding #upDown.CultureInfo}" VerticalAlignment="Center" Height="25" Margin="2" Width="70" HorizontalAlignment="Center"/>
+                       CultureInfo="{Binding #upDown.CultureInfo}" VerticalAlignment="Center" Margin="2" Width="70" HorizontalAlignment="Center"/>
 
         <TextBlock Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Margin="10,2,2,2">Increment:</TextBlock>
         <NumericUpDown Grid.Row="2" Grid.Column="1" Value="{Binding #upDown.Increment}" VerticalAlignment="Center"
-                       Height="25" Margin="2" Width="70" HorizontalAlignment="Center"/>
+                       Margin="2" Width="70" HorizontalAlignment="Center"/>
 
         <TextBlock Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Margin="10,2,2,2">Value:</TextBlock>
         <NumericUpDown Grid.Row="3" Grid.Column="1" Value="{Binding #upDown.Value}" VerticalAlignment="Center"
-                       Height="25" Margin="2" Width="70" HorizontalAlignment="Center"/>
+                       Margin="2" Width="70" HorizontalAlignment="Center"/>
 
       </Grid>
     </Grid>
@@ -72,7 +73,7 @@
     <StackPanel Margin="2,10,2,2" Orientation="Horizontal" Spacing="10">
       <TextBlock FontSize="14" FontWeight="Bold" VerticalAlignment="Center">Usage of NumericUpDown:</TextBlock>
       <NumericUpDown Name="upDown" Minimum="0" Maximum="10" Increment="0.5"
-                     CultureInfo="en-US" VerticalAlignment="Center" Height="25" Width="100"
+                     CultureInfo="en-US" VerticalAlignment="Center" Width="100"
                      Watermark="Enter text" FormatString="{Binding SelectedFormat.Value}"/>
     </StackPanel>
 

+ 4 - 2
samples/ControlCatalog/Pages/ProgressBarPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.ProgressBarPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">ProgressBar</TextBlock>
     <TextBlock Classes="h2">A progress bar control</TextBlock>
@@ -21,4 +23,4 @@
       </StackPanel>
     </StackPanel>
   </StackPanel>
-</UserControl>
+</UserControl>

+ 3 - 2
samples/ControlCatalog/Pages/RadioButtonPage.xaml

@@ -1,5 +1,6 @@
 <UserControl xmlns="https://github.com/avaloniaui"
-             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.RadioButtonPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">RadioButton</TextBlock>
     <TextBlock Classes="h2">Allows the selection of a single option of many</TextBlock>
@@ -37,4 +38,4 @@
       </StackPanel>
     </StackPanel>
   </StackPanel>
-</UserControl>
+</UserControl>

+ 3 - 1
samples/ControlCatalog/Pages/ScreenPage.cs

@@ -4,6 +4,7 @@ using Avalonia.Controls;
 using Avalonia.Markup.Xaml;
 using Avalonia.Media;
 using Avalonia.Platform;
+using Avalonia.Rendering;
 
 namespace ControlCatalog.Pages
 {
@@ -23,6 +24,7 @@ namespace ControlCatalog.Pages
             base.Render(context);
             Window w = (Window)VisualRoot;
             Screen[] screens = w.Screens.All;
+            var scaling = ((IRenderRoot)w).RenderScaling;
 
             Pen p = new Pen(Brushes.Black);
             if (screens != null)
@@ -56,7 +58,7 @@ namespace ControlCatalog.Pages
                     text.Text = $"Primary: {screen.Primary}";
                     context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
                     
-                    text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new Rect(w.Position, w.Bounds.Size)))}";
+                    text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
                     context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
                 }
 

+ 4 - 2
samples/ControlCatalog/Pages/SliderPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.SliderPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">Slider</TextBlock>
     <TextBlock Classes="h2">A control that lets the user select from a range of values by moving a Thumb control along a Track.</TextBlock>
@@ -18,4 +20,4 @@
     </StackPanel>
 
   </StackPanel>
-</UserControl>
+</UserControl>

+ 100 - 0
samples/ControlCatalog/Pages/TabControlPage.xaml

@@ -0,0 +1,100 @@
+<UserControl
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    x:Class="ControlCatalog.Pages.TabControlPage"
+    xmlns="https://github.com/avaloniaui">
+    <DockPanel>
+        <TextBlock 
+            DockPanel.Dock="Top" 
+            Classes="h1"
+            Text="TabControl"
+            Margin="4">           
+        </TextBlock>
+        <TextBlock 
+            DockPanel.Dock="Top" 
+            Classes="h2"
+            Text="A tab control that displays a tab strip along with the content of the selected tab"
+            Margin="4">          
+        </TextBlock>
+        <Grid 
+            ColumnDefinitions="*,*" 
+            RowDefinitions="*,100">
+            <DockPanel
+                Grid.Column="0"
+                Margin="4">
+                <TextBlock
+                    DockPanel.Dock="Top"
+                    Classes="h1"
+                    Text="From Inline TabItems">
+                </TextBlock>
+                <TabControl
+                    Margin="0 16"
+                    TabStripPlacement="{Binding TabPlacement}">
+                    <TabItem Header="Arch">
+                        <StackPanel Orientation="Vertical" Spacing="8">
+                            <TextBlock>This is the first page in the TabControl.</TextBlock>
+                            <Image Source="/Assets/delicate-arch-896885_640.jpg" Width="300"/>
+                        </StackPanel>
+                    </TabItem>
+                    <TabItem Header="Leaf">                       
+                        <StackPanel Orientation="Vertical" Spacing="8">
+                            <TextBlock>This is the second page in the TabControl.</TextBlock>
+                            <Image Source="/Assets/maple-leaf-888807_640.jpg" Width="300"/>
+                        </StackPanel>
+                    </TabItem>
+                    <TabItem Header="Disabled" IsEnabled="False">
+                        <TextBlock>You should not see this.</TextBlock>
+                    </TabItem>
+                </TabControl>
+            </DockPanel>
+            <DockPanel
+                Grid.Column="1"
+                Margin="4">
+                <TextBlock
+                    DockPanel.Dock="Top"
+                    Classes="h1"
+                    Text="From DataTemplate">
+                </TextBlock>
+                <TabControl
+                    Items="{Binding Tabs}"
+                    Margin="0 16"
+                    TabStripPlacement="{Binding TabPlacement}">
+                    <TabControl.ItemTemplate>
+                        <DataTemplate>
+                            <TextBlock
+                                Text="{Binding Header}">
+                            </TextBlock>
+                        </DataTemplate>
+                    </TabControl.ItemTemplate>
+                    <TabControl.ContentTemplate>
+                        <DataTemplate>
+                            <StackPanel Orientation="Vertical" Spacing="8">
+                                <TextBlock Text="{Binding Text}"/>
+                                <Image Source="{Binding Image}" Width="300"/>
+                            </StackPanel>
+                        </DataTemplate>
+                    </TabControl.ContentTemplate>
+                    <TabControl.Styles>
+                        <Style Selector="TabItem">
+                            <Setter Property="IsEnabled" Value="{Binding IsEnabled}"/>
+                        </Style>
+                    </TabControl.Styles>
+                </TabControl>
+            </DockPanel>
+            <StackPanel
+                Grid.Row="1"
+                Grid.ColumnSpan="2"
+                Orientation="Horizontal"
+                Spacing="8"
+                HorizontalAlignment="Center"
+                VerticalAlignment="Center">
+                <TextBlock VerticalAlignment="Center">Tab Placement:</TextBlock>
+                <DropDown SelectedIndex="{Binding TabPlacement, Mode=TwoWay}">
+                    <DropDownItem>Left</DropDownItem>
+                    <DropDownItem>Bottom</DropDownItem>
+                    <DropDownItem>Right</DropDownItem>
+                    <DropDownItem>Top</DropDownItem>
+                </DropDown>
+            </StackPanel>
+        </Grid>
+    </DockPanel>
+</UserControl>

+ 80 - 0
samples/ControlCatalog/Pages/TabControlPage.xaml.cs

@@ -0,0 +1,80 @@
+using System;
+
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.Media.Imaging;
+using Avalonia.Platform;
+
+using ReactiveUI;
+
+namespace ControlCatalog.Pages
+{
+    using System.Collections.Generic;
+
+    public class TabControlPage : UserControl
+    {
+        public TabControlPage()
+        {
+            InitializeComponent();
+
+            DataContext = new PageViewModel
+            {
+                Tabs = new[]
+                {
+                    new TabItemViewModel
+                    {
+                        Header = "Arch",
+                        Text = "This is the first templated tab page.",
+                        Image = LoadBitmap("avares://ControlCatalog/Assets/delicate-arch-896885_640.jpg"),
+                    },
+                    new TabItemViewModel
+                    {
+                        Header = "Leaf",
+                        Text = "This is the second templated tab page.",
+                        Image = LoadBitmap("avares://ControlCatalog/Assets/maple-leaf-888807_640.jpg"),
+                    },
+                    new TabItemViewModel
+                    {
+                        Header = "Disabled",
+                        Text = "You should not see this.",
+                        IsEnabled = false,
+                    },
+                },
+                TabPlacement = Dock.Top,
+            };
+        }
+
+        private void InitializeComponent()
+        {
+            AvaloniaXamlLoader.Load(this);
+        }
+
+        private IBitmap LoadBitmap(string uri)
+        {
+            var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
+            return new Bitmap(assets.Open(new Uri(uri)));
+        }
+
+        private class PageViewModel : ReactiveObject
+        {
+            private Dock _tabPlacement;
+
+            public TabItemViewModel[] Tabs { get; set; }
+
+            public Dock TabPlacement
+            {
+                get { return _tabPlacement; }
+                set { this.RaiseAndSetIfChanged(ref _tabPlacement, value); }
+            }
+        }
+
+        private class TabItemViewModel
+        {
+            public string Header { get; set; }
+            public string Text { get; set; }
+            public IBitmap Image { get; set; }
+            public bool IsEnabled { get; set; } = true;           
+        }
+    }
+}

+ 13 - 2
samples/ControlCatalog/Pages/TextBoxPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.TextBoxPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">TextBox</TextBlock>
     <TextBlock Classes="h2">A control into which the user can input text</TextBlock>
@@ -33,11 +35,20 @@
                  Text="Multiline TextBox with no TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
       </StackPanel>
         <StackPanel Orientation="Vertical" Spacing="8">
+            <TextBlock Classes="h2">resm fonts</TextBlock>
             <TextBox Width="200" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
                 <TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
                 <TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-Italic.ttf?assembly=ControlCatalog#Source Sans Pro"/>
                 <TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-*.ttf?assembly=ControlCatalog#Source Sans Pro"/>
         </StackPanel>
+        
+        <StackPanel Orientation="Vertical" Spacing="8">
+            <TextBlock Classes="h2">res fonts</TextBlock>
+            <TextBox Width="200" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
+            <TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="avares://ControlCatalog/Assets/Fonts#Source Sans Pro"/>
+            <TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-Italic.ttf#Source Sans Pro"/>
+            <TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-*.ttf#Source Sans Pro"/>
+        </StackPanel>
       </StackPanel>
   </StackPanel>
-</UserControl>
+</UserControl>

+ 4 - 2
samples/ControlCatalog/Pages/ToolTipPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.ToolTipPage">
     <StackPanel Orientation="Vertical"
                 Spacing="4">
         <TextBlock Classes="h1">ToolTip</TextBlock>
@@ -38,4 +40,4 @@
             </Border>
         </Grid>
     </StackPanel>
-</UserControl>
+</UserControl>

+ 4 - 2
samples/ControlCatalog/Pages/TreeViewPage.xaml

@@ -1,4 +1,6 @@
-<UserControl xmlns="https://github.com/avaloniaui">
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.TreeViewPage">
   <StackPanel Orientation="Vertical" Spacing="4">
     <TextBlock Classes="h1">TreeView</TextBlock>
     <TextBlock Classes="h2">Displays a hierachical tree of data.</TextBlock>
@@ -16,4 +18,4 @@
       </TreeView>
     </StackPanel>
   </StackPanel>
-</UserControl>
+</UserControl>

+ 66 - 0
samples/ControlCatalog/Pages/ViewboxPage.xaml

@@ -0,0 +1,66 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="ControlCatalog.Pages.ViewboxPage">
+    <UserControl.Resources>
+        <StreamGeometry x:Key="Acorn">
+            F1 M 16.6309,18.6563C 17.1309,
+            8.15625 29.8809,14.1563 29.8809,
+            14.1563C 30.8809,11.1563 34.1308,
+            11.4063 34.1308,11.4063C 33.5,12
+            34.6309,13.1563 34.6309,13.1563C
+            32.1309,13.1562 31.1309,14.9062
+            31.1309,14.9062C 41.1309,23.9062
+            32.6309,27.9063 32.6309,27.9062C
+            24.6309,24.9063 21.1309,22.1562
+            16.6309,18.6563 Z M 16.6309,19.9063C
+            21.6309,24.1563 25.1309,26.1562
+            31.6309,28.6562C 31.6309,28.6562
+            26.3809,39.1562 18.3809,36.1563C
+            18.3809,36.1563 18,38 16.3809,36.9063C
+            15,36 16.3809,34.9063 16.3809,34.9063C
+            16.3809,34.9063 10.1309,30.9062 16.6309,19.9063 Z
+        </StreamGeometry>
+    </UserControl.Resources>
+
+    <Grid RowDefinitions="Auto,*">
+        <StackPanel Orientation="Vertical" Spacing="4">
+            <TextBlock Classes="h1">Viewbox</TextBlock>
+            <TextBlock Classes="h2">A control used to scale single child.</TextBlock>
+        </StackPanel>
+        <Grid ColumnDefinitions="Auto,*,*"
+              RowDefinitions="*,*,*,*"
+              Grid.Row="1" Margin="48"
+              MaxWidth="400">
+            <TextBlock Grid.Row="0" VerticalAlignment="Center">None</TextBlock>
+            <TextBlock Grid.Row="1" VerticalAlignment="Center">Fill</TextBlock>
+            <TextBlock Grid.Row="2" VerticalAlignment="Center">Uniform</TextBlock>
+            <TextBlock Grid.Row="3" VerticalAlignment="Center">UniformToFill</TextBlock>
+
+            <Viewbox Grid.Row="0" Grid.Column="1" Stretch="None">
+                <TextBlock>Hello World!</TextBlock>
+            </Viewbox>
+            <Viewbox Grid.Row="1" Grid.Column="1" Stretch="Fill">
+                <TextBlock>Hello World!</TextBlock>
+            </Viewbox>
+            <Viewbox Grid.Row="2" Grid.Column="1" Stretch="Uniform">
+                <TextBlock>Hello World!</TextBlock>
+            </Viewbox>
+            <Viewbox Grid.Row="3" Grid.Column="1" Stretch="UniformToFill">
+                <TextBlock>Hello World!</TextBlock>
+            </Viewbox>
+
+            <Viewbox Grid.Row="0" Grid.Column="2" Stretch="None">
+                <Path Fill="Blue" Data="{StaticResource Acorn}"/>
+            </Viewbox>
+            <Viewbox Grid.Row="1" Grid.Column="2" Stretch="Fill">
+                <Path Fill="Blue" Data="{StaticResource Acorn}"/>
+            </Viewbox>
+            <Viewbox Grid.Row="2" Grid.Column="2" Stretch="Uniform">
+                <Path Fill="Blue" Data="{StaticResource Acorn}"/>
+            </Viewbox>
+            <Viewbox Grid.Row="3" Grid.Column="2" Stretch="UniformToFill">
+                <Path Fill="Blue" Data="{StaticResource Acorn}"/>
+            </Viewbox>
+        </Grid>
+    </Grid>
+</UserControl>

+ 18 - 0
samples/ControlCatalog/Pages/ViewboxPage.xaml.cs

@@ -0,0 +1,18 @@
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace ControlCatalog.Pages
+{
+    public class ViewboxPage : UserControl
+    {
+        public ViewboxPage()
+        {
+            this.InitializeComponent();
+        }
+
+        private void InitializeComponent()
+        {
+            AvaloniaXamlLoader.Load(this);
+        }
+    }
+}

+ 64 - 49
samples/ControlCatalog/SideBar.xaml

@@ -1,52 +1,67 @@
 <Styles xmlns="https://github.com/avaloniaui"
-        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
-  <Style Selector="TabControl.sidebar">
-    <Setter Property="Template">
-      <ControlTemplate>
-        <DockPanel>
-          <ScrollViewer MinWidth="190" Background="{DynamicResource ThemeAccentBrush}" DockPanel.Dock="Left">
-            <TabStrip Name="PART_TabStrip"
-                      MemberSelector="{x:Static TabControl.HeaderSelector}"
-                      Items="{TemplateBinding Items}"
-                      SelectedIndex="{TemplateBinding SelectedIndex, Mode=TwoWay}">
-              <TabStrip.ItemsPanel>
-                <ItemsPanelTemplate>
-                  <StackPanel Orientation="Vertical"/>
-                </ItemsPanelTemplate>
-              </TabStrip.ItemsPanel>
-            </TabStrip>
-          </ScrollViewer>
-          <Carousel Name="PART_Content"
-                    Margin="8 0 0 0"
-                    MemberSelector="{x:Static TabControl.ContentSelector}"
-                    Items="{TemplateBinding Items}"
-                    SelectedIndex="{TemplateBinding SelectedIndex}"
-                    PageTransition="{TemplateBinding PageTransition}"
-                    Grid.Row="1"/>
-        </DockPanel>
-      </ControlTemplate>
-    </Setter>
-  </Style>
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        x:Class="ControlCatalog.SideBar">
+    <Style Selector="TabControl.sidebar">
+        <Setter Property="TabStripPlacement" Value="Left"/>
+        <Setter Property="Padding" Value="8 0 0 0"/>
+        <Setter Property="Background" Value="{DynamicResource ThemeAccentBrush}"/>
+        <Setter Property="Template">
+            <ControlTemplate>
+                <Border 
+                    Margin="{TemplateBinding Margin}"
+                    BorderBrush="{TemplateBinding BorderBrush}"
+                    BorderThickness="{TemplateBinding BorderThickness}">
+                    <DockPanel>
+                        <ScrollViewer
+                            Name="PART_ScrollViewer"
+                            HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
+                            VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}"
+                            Background="{TemplateBinding Background}">
+                            <ItemsPresenter
+                                Name="PART_ItemsPresenter"                          
+                                Items="{TemplateBinding Items}"
+                                ItemsPanel="{TemplateBinding ItemsPanel}"
+                                ItemTemplate="{TemplateBinding ItemTemplate}"
+                                MemberSelector="{TemplateBinding MemberSelector}">
+                            </ItemsPresenter>
+                        </ScrollViewer>
+                        <ContentPresenter
+                            Name="PART_SelectedContentHost"
+                            Margin="{TemplateBinding Padding}"                           
+                            HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                            VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+                            Content="{TemplateBinding SelectedContent}"
+                            ContentTemplate="{TemplateBinding SelectedContentTemplate}">
+                        </ContentPresenter>
+                    </DockPanel>
+                </Border>
+            </ControlTemplate>
+        </Setter>
+    </Style>
 
-  <Style Selector="TabControl.sidebar TabStripItem">
-    <Setter Property="Foreground" Value="White"/>
-    <Setter Property="FontSize" Value="14"/>
-    <Setter Property="Margin" Value="0"/>
-    <Setter Property="Padding" Value="16"/>
-    <Setter Property="Opacity" Value="0.5"/>
-    <Setter Property="Transitions">
-      <Transitions>
-        <DoubleTransition Property="Opacity" Duration="0:0:0.2"/>
-      </Transitions>
-    </Setter>
-  </Style>
-
-  <Style Selector="TabControl.sidebar TabStripItem:pointerover">
-    <Setter Property="Opacity" Value="1"/>
-  </Style>
-
-  <Style Selector="TabControl.sidebar TabStripItem:selected">
-    <Setter Property="Background" Value="{DynamicResource ThemeAccentBrush2}"/>
-    <Setter Property="Opacity" Value="1"/>
-  </Style>
+    <Style Selector="TabControl.sidebar > TabItem">       
+        <Setter Property="BorderThickness" Value="0"/>
+        <Setter Property="Foreground" Value="White"/>
+        <Setter Property="FontSize" Value="14"/>
+        <Setter Property="Margin" Value="0"/>
+        <Setter Property="Padding" Value="16"/>
+        <Setter Property="Opacity" Value="0.5"/>
+        <Setter Property="Transitions">
+            <Transitions>
+                <DoubleTransition Property="Opacity" Duration="0:0:0.5"/>
+            </Transitions>
+        </Setter>
+    </Style>
+    <Style Selector="TabControl.sidebar > TabItem:pointerover">
+        <Setter Property="Opacity" Value="1"/>
+    </Style>
+    <Style Selector="TabControl.sidebar > TabItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
+        <Setter Property="Background" Value="Transparent"/>
+    </Style>
+    <Style Selector="TabControl.sidebar > TabItem:selected">
+        <Setter Property="Opacity" Value="1"/>
+    </Style>
+    <Style Selector="TabControl.sidebar > TabItem:selected /template/ ContentPresenter#PART_ContentPresenter">
+        <Setter Property="Background" Value="{DynamicResource ThemeAccentBrush2}"/>
+    </Style>
 </Styles>

+ 6 - 0
samples/PlatformSanityChecks/App.xaml

@@ -0,0 +1,6 @@
+<Application xmlns="https://github.com/avaloniaui">
+    <Application.Styles>
+        <StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/>
+        <StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
+    </Application.Styles>
+</Application>

+ 13 - 0
samples/PlatformSanityChecks/App.xaml.cs

@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Markup.Xaml;
+
+namespace PlatformSanityChecks
+{
+    public class App : Application
+    {
+        public override void Initialize()
+        {
+            AvaloniaXamlLoader.Load(this);
+        }
+    }
+}

+ 13 - 0
samples/PlatformSanityChecks/PlatformSanityChecks.csproj

@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" />
+  </ItemGroup>
+
+</Project>

+ 132 - 0
samples/PlatformSanityChecks/Program.cs

@@ -0,0 +1,132 @@
+using System;
+using System.Diagnostics;
+using System.Reactive.Disposables;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using Avalonia;
+using Avalonia.Platform;
+using Avalonia.Threading;
+using Avalonia.X11;
+
+namespace PlatformSanityChecks
+{
+    public class Program
+    {
+        static Thread UiThread;
+        
+        static void Main(string[] args)
+        {
+            UiThread = Thread.CurrentThread;
+            AppBuilder.Configure<App>().RuntimePlatformServicesInitializer();
+            var app = new App();
+            
+            AvaloniaX11PlatformExtensions.InitializeX11Platform();
+
+            CheckPlatformThreading();
+        }
+
+        static bool CheckAccess() => UiThread == Thread.CurrentThread;
+
+        static void VerifyAccess()
+        {
+            if (!CheckAccess())
+                Die("Call from invalid thread");
+        }
+        
+        static Exception Die(string error)
+        {
+            Console.Error.WriteLine(error);
+            Console.Error.WriteLine(Environment.StackTrace);
+            Process.GetCurrentProcess().Kill();
+            throw new Exception(error);
+        }
+
+        static IDisposable Enter([CallerMemberName] string caller = null)
+        {
+            Console.WriteLine("Entering " + caller);
+            return Disposable.Create(() => { Console.WriteLine("Leaving " + caller); });
+        }
+
+        static void EnterLoop(Action<CancellationTokenSource> cb, [CallerMemberName] string caller = null)
+        {
+            using (Enter(caller))
+            {
+                var cts = new CancellationTokenSource();
+                cb(cts);
+                Dispatcher.UIThread.MainLoop(cts.Token);
+                if (!cts.IsCancellationRequested)
+                    Die("Unexpected loop exit");
+            }
+        }
+        
+        static void CheckTimerOrdering() => EnterLoop(cts =>
+        {
+            bool firstFired = false, secondFired = false;
+            DispatcherTimer.Run(() =>
+            {
+                Console.WriteLine("Second tick");
+                VerifyAccess();
+                if (!firstFired)
+                    throw Die("Invalid timer ordering");
+                if (secondFired)
+                    throw Die("Invocation of finished timer");
+                secondFired = true;
+                cts.Cancel();
+                return false;
+            }, TimeSpan.FromSeconds(2));
+            DispatcherTimer.Run(() =>
+            {
+                Console.WriteLine("First tick");
+                VerifyAccess();
+                if (secondFired)
+                    throw Die("Invalid timer ordering");
+                if (firstFired)
+                    throw Die("Invocation of finished timer");
+                firstFired = true;
+                return false;
+            }, TimeSpan.FromSeconds(1));
+        });
+
+        static void CheckTimerTicking() => EnterLoop(cts =>
+        {
+            int ticks = 0;
+            var st = Stopwatch.StartNew();
+            DispatcherTimer.Run(() =>
+            {
+                ticks++;
+                Console.WriteLine($"Tick {ticks} at {st.Elapsed}");
+                if (ticks == 5)
+                {
+                    if (st.Elapsed.TotalSeconds < 4.5)
+                        Die("Timer is too fast");
+                    if (st.Elapsed.TotalSeconds > 6)
+                        Die("Timer is too slow");
+                    cts.Cancel();
+                    return false;
+                }
+
+                return true;
+            }, TimeSpan.FromSeconds(1));
+        });
+
+        static void CheckSignaling() => EnterLoop(cts =>
+        {
+            ThreadPool.QueueUserWorkItem(_ =>
+            {
+                Thread.Sleep(100);
+                Dispatcher.UIThread.Post(() =>
+                {
+                    VerifyAccess();
+                    cts.Cancel();
+                });
+            });
+        });
+
+        static void CheckPlatformThreading()
+        {
+            CheckSignaling();
+            CheckTimerOrdering();
+            CheckTimerTicking();
+        }
+    }
+}

+ 1 - 4
samples/RenderDemo/MainWindow.xaml

@@ -24,9 +24,6 @@
       </MenuItem>
     </Menu>
     <TabControl Classes="sidebar">
-      <TabControl.PageTransition>
-        <CrossFade Duration="0.25"/>
-      </TabControl.PageTransition>
       <TabItem Header="Animations">
         <pages:AnimationsPage/>
       </TabItem>
@@ -38,4 +35,4 @@
       </TabItem>
     </TabControl>
   </DockPanel>
-</Window>
+</Window>

+ 33 - 2
samples/RenderDemo/Pages/AnimationsPage.xaml

@@ -43,7 +43,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
       <Style Selector="Border.Rect1:pointerover">
         <Style.Animations>
           <Animation Duration="0:0:2.5"
-                     RepeatCount="4"
+                     IterationCount="4"
                      FillMode="None"
                      PlaybackDirection="AlternateReverse"
                      Easing="SineEaseInOut">
@@ -73,7 +73,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
         <Style.Animations>
           <Animation Duration="0:0:0.5"
                      Easing="QuadraticEaseInOut"
-                     RepeatCount="Loop">
+                     IterationCount="Infinite">
             <KeyFrame Cue="50%">
               <Setter Property="ScaleTransform.ScaleX" Value="0.8"/>
               <Setter Property="ScaleTransform.ScaleY" Value="0.8"/>
@@ -87,6 +87,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
           <Animation Duration="0:0:3" Easing="BounceEaseInOut">
             <KeyFrame Cue="48%">
               <Setter Property="TranslateTransform.Y" Value="-100"/>
+              <Setter Property="Background" Value="Magenta"/>
             </KeyFrame>
           </Animation>
         </Style.Animations>
@@ -103,6 +104,35 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
           </Animation>
         </Style.Animations>
       </Style>
+      <Style Selector="Border.Rect6">
+        <Style.Animations>
+          <Animation Duration="0:0:3"
+                     IterationCount="Infinite"
+                     PlaybackDirection="Alternate">
+            <KeyFrame Cue="0%">
+              <Setter Property="Background" Value="Red"/>
+            </KeyFrame>
+            <KeyFrame Cue="15%">
+              <Setter Property="Background" Value="Yellow"/>
+            </KeyFrame>
+            <KeyFrame Cue="30%">
+              <Setter Property="Background" Value="Green"/>
+            </KeyFrame>
+            <KeyFrame Cue="45%">
+              <Setter Property="Background" Value="Cyan"/>
+            </KeyFrame>
+            <KeyFrame Cue="60%">
+              <Setter Property="Background" Value="Blue"/>
+            </KeyFrame>
+            <KeyFrame Cue="75%">
+              <Setter Property="Background" Value="Indigo"/>
+            </KeyFrame>
+            <KeyFrame Cue="90%">
+              <Setter Property="Background" Value="Violet"/>
+            </KeyFrame>
+          </Animation>
+        </Style.Animations>
+      </Style>
     </Styles>
   </UserControl.Styles>
   <Grid>
@@ -120,6 +150,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
         <Border Classes="Test Rect3"/>
         <Border Classes="Test Rect4" Background="Navy"/>
         <Border Classes="Test Rect5" Background="SeaGreen"/>
+        <Border Classes="Test Rect6" Background="Red"/>
       </WrapPanel>
     </StackPanel>
   </Grid>

+ 1 - 1
samples/RenderDemo/Pages/ClippingPage.xaml

@@ -8,7 +8,7 @@ xmlns="https://github.com/avaloniaui">
         </Style>
         <Style Selector="Border#clipChild">
           <Style.Animations>
-            <Animation Duration="0:0:2" RepeatCount="Loop">
+            <Animation Duration="0:0:2" IterationCount="Infinite">
               <KeyFrame Cue="100%">
                 <Setter Property="RotateTransform.Angle" Value="360"/>
               </KeyFrame>

Some files were not shown because too many files changed in this diff