ソースを参照

Merge pull request #4 from AvaloniaUI/master

Merge
Benedikt Schroeder 7 年 前
コミット
2b6307b35e
100 ファイル変更1468 行追加2347 行削除
  1. 1 1
      .travis.yml
  2. 6 4
      Avalonia.sln
  3. 1 1
      build/Base.props
  4. 11 0
      build/EmbedXaml.props
  5. 13 0
      build/SampleApp.props
  6. 14 0
      build/SharedVersion.props
  7. 1 1
      parameters.cake
  8. 26 148
      samples/BindingTest/BindingTest.csproj
  9. 4 1
      samples/BindingTest/MainWindow.xaml
  10. 0 36
      samples/BindingTest/Properties/AssemblyInfo.cs
  11. 13 130
      samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
  12. 0 36
      samples/ControlCatalog.Desktop/Properties/AssemblyInfo.cs
  13. 8 2
      samples/ControlCatalog/Pages/TextBoxPage.xaml
  14. 3 0
      samples/Directory.Build.props
  15. 4 2
      samples/RenderTest/MainWindow.xaml
  16. 0 36
      samples/RenderTest/Properties/AssemblyInfo.cs
  17. 27 178
      samples/RenderTest/RenderTest.csproj
  18. 3 1
      samples/VirtualizationTest/MainWindow.xaml
  19. 0 36
      samples/VirtualizationTest/Properties/AssemblyInfo.cs
  20. 26 144
      samples/VirtualizationTest/VirtualizationTest.csproj
  21. 0 28
      src/Avalonia.Animation/Avalonia.Animation.csproj
  22. 0 6
      src/Avalonia.Animation/Properties/AssemblyInfo.cs
  23. 1 28
      src/Avalonia.Base/Avalonia.Base.csproj
  24. 15 3
      src/Avalonia.Base/AvaloniaObject.cs
  25. 0 1
      src/Avalonia.Base/Properties/AssemblyInfo.cs
  26. 20 6
      src/Avalonia.Base/Utilities/StringTokenizer.cs
  27. 4 0
      src/Avalonia.Controls/AutoCompleteBox.cs
  28. 0 28
      src/Avalonia.Controls/Avalonia.Controls.csproj
  29. 3 25
      src/Avalonia.Controls/Border.cs
  30. 3 14
      src/Avalonia.Controls/Decorator.cs
  31. 148 674
      src/Avalonia.Controls/Grid.cs
  32. 5 0
      src/Avalonia.Controls/Platform/IWindowImpl.cs
  33. 67 75
      src/Avalonia.Controls/Presenters/ContentPresenter.cs
  34. 27 2
      src/Avalonia.Controls/Presenters/TextPresenter.cs
  35. 3 14
      src/Avalonia.Controls/Primitives/AccessText.cs
  36. 0 1
      src/Avalonia.Controls/Properties/AssemblyInfo.cs
  37. 6 3
      src/Avalonia.Controls/TextBlock.cs
  38. 26 9
      src/Avalonia.Controls/TextBox.cs
  39. 4 4
      src/Avalonia.Controls/ToolTip.cs
  40. 117 137
      src/Avalonia.Controls/Utils/BorderRenderHelper.cs
  41. 700 0
      src/Avalonia.Controls/Utils/GridLayout.cs
  42. 20 10
      src/Avalonia.Controls/Window.cs
  43. 0 8
      src/Avalonia.DesignerSupport/Properties/AssemblyInfo.cs
  44. 1 0
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  45. 1 0
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  46. 2 35
      src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
  47. 0 6
      src/Avalonia.Diagnostics/Properties/AssemblyInfo.cs
  48. 1 10
      src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj
  49. 0 6
      src/Avalonia.DotNetCoreRuntime/Properties/AssemblyInfo.cs
  50. 2 6
      src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
  51. 1 115
      src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj
  52. 1 29
      src/Avalonia.Input/Avalonia.Input.csproj
  53. 0 1
      src/Avalonia.Input/Properties/AssemblyInfo.cs
  54. 3 29
      src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
  55. 0 6
      src/Avalonia.Interactivity/Properties/AssemblyInfo.cs
  56. 1 29
      src/Avalonia.Layout/Avalonia.Layout.csproj
  57. 29 0
      src/Avalonia.Layout/LayoutHelper.cs
  58. 0 6
      src/Avalonia.Layout/Properties/AssemblyInfo.cs
  59. 1 25
      src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
  60. 0 3
      src/Avalonia.Logging.Serilog/Properties/AssemblyInfo.cs
  61. 0 2
      src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
  62. 0 6
      src/Avalonia.ReactiveUI/Properties/AssemblyInfo.cs
  63. 1 28
      src/Avalonia.Styling/Avalonia.Styling.csproj
  64. 0 1
      src/Avalonia.Styling/Properties/AssemblyInfo.cs
  65. 2 33
      src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
  66. 12 6
      src/Avalonia.Themes.Default/ButtonSpinner.xaml
  67. 1 1
      src/Avalonia.Themes.Default/CalendarItem.xaml
  68. 3 1
      src/Avalonia.Themes.Default/ContentControl.xaml
  69. 16 9
      src/Avalonia.Themes.Default/Expander.xaml
  70. 3 1
      src/Avalonia.Themes.Default/ListBoxItem.xaml
  71. 0 6
      src/Avalonia.Themes.Default/Properties/AssemblyInfo.cs
  72. 1 1
      src/Avalonia.Themes.Default/RepeatButton.xaml
  73. 2 0
      src/Avalonia.Themes.Default/TabStripItem.xaml
  74. 4 3
      src/Avalonia.Themes.Default/TextBox.xaml
  75. 2 0
      src/Avalonia.Themes.Default/TreeViewItem.xaml
  76. 5 3
      src/Avalonia.Themes.Default/Window.xaml
  77. 1 29
      src/Avalonia.Visuals/Avalonia.Visuals.csproj
  78. 1 1
      src/Avalonia.Visuals/Matrix.cs
  79. 1 1
      src/Avalonia.Visuals/Media/Color.cs
  80. 2 2
      src/Avalonia.Visuals/Media/DrawingContext.cs
  81. 1 1
      src/Avalonia.Visuals/Media/Immutable/ImmutableSolidColorBrush.cs
  82. 1 1
      src/Avalonia.Visuals/Point.cs
  83. 0 1
      src/Avalonia.Visuals/Properties/AssemblyInfo.cs
  84. 1 1
      src/Avalonia.Visuals/Rect.cs
  85. 2 2
      src/Avalonia.Visuals/RelativePoint.cs
  86. 1 1
      src/Avalonia.Visuals/RelativeRect.cs
  87. 1 1
      src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
  88. 1 1
      src/Avalonia.Visuals/Size.cs
  89. 1 1
      src/Avalonia.Visuals/Thickness.cs
  90. 1 1
      src/Avalonia.Visuals/Vector.cs
  91. 1 1
      src/Avalonia.Visuals/VisualTree/TransformedBounds.cs
  92. 3 0
      src/Directory.Build.props
  93. 1 22
      src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
  94. 0 2
      src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs
  95. 1 1
      src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs
  96. 21 3
      src/Gtk/Avalonia.Gtk3/WindowImpl.cs
  97. 1 1
      src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
  98. 0 4
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  99. 0 1
      src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs
  100. 0 28
      src/Markup/Avalonia.Markup/Avalonia.Markup.csproj

+ 1 - 1
.travis.yml

@@ -9,7 +9,7 @@ env:
     - DOTNET_CLI_TELEMETRY_OPTOUT=1
 mono:
   - 5.2.0
-dotnet: 2.0.0
+dotnet: 2.1.200
 script:
   - ./build.sh --target "Travis" --platform "NetCoreOnly" --configuration "Release"
 notifications:

+ 6 - 4
Avalonia.sln

@@ -76,7 +76,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup", "src\Mark
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BindingTest", "samples\BindingTest\BindingTest.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BindingTest", "samples\BindingTest\BindingTest.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}"
 EndProject
 Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "RenderHelpers", "src\Shared\RenderHelpers\RenderHelpers.shproj", "{3C4C0CB4-0C0F-4450-A37B-148C84FF905F}"
 EndProject
@@ -114,7 +114,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.DesignerSupport.Te
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.DesignerSupport.TestApp", "tests\Avalonia.DesignerSupport.TestApp\Avalonia.DesignerSupport.TestApp.csproj", "{F1381F98-4D24-409A-A6C5-1C5B1E08BB08}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtualizationTest", "samples\VirtualizationTest\VirtualizationTest.csproj", "{FBCAF3D0-2808-4934-8E96-3F607594517B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtualizationTest", "samples\VirtualizationTest\VirtualizationTest.csproj", "{FBCAF3D0-2808-4934-8E96-3F607594517B}"
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{A0CC0258-D18C-4AB3-854F-7101680FC3F9}"
 EndProject
@@ -122,7 +122,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInteropTest", "sampl
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DotNetFrameworkRuntime", "src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj", "{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenderTest", "samples\RenderTest\RenderTest.csproj", "{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderTest", "samples\RenderTest\RenderTest.csproj", "{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}"
 EndProject
@@ -146,11 +146,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
 		build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props
 		build\Moq.props = build\Moq.props
 		build\NetCore.props = build\NetCore.props
+		build\NetFX.props = build\NetFX.props
 		build\ReactiveUI.props = build\ReactiveUI.props
 		build\Rx.props = build\Rx.props
+		build\SampleApp.props = build\SampleApp.props
 		build\Serilog.props = build\Serilog.props
 		build\SharpDX.props = build\SharpDX.props
-		build\SkiaSharp.Desktop.props = build\SkiaSharp.Desktop.props
 		build\SkiaSharp.props = build\SkiaSharp.props
 		build\Splat.props = build\Splat.props
 		build\Sprache.props = build\Sprache.props
@@ -2590,6 +2591,7 @@ Global
 		{E2999E4A-9086-401F-898C-AEB0AD38E676} = {9B9E3891-2366-4253-A952-D08BCEB71098}
 		{050CC912-FF49-4A8B-B534-9544017446DD} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
 		{F40FC0A2-1BC3-401C-BFC1-928EC4D4A9CE} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+		{CBFD5788-567D-401B-9DFA-74E4224025A0} = {A59C4C0A-64DF-4621-B450-2BA00D6F61E2}
 		{4ADA61C8-D191-428D-9066-EF4F0D86520F} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution

+ 1 - 1
build/Base.props

@@ -2,4 +2,4 @@
   <ItemGroup>
     <PackageReference Include="System.ValueTuple" Version="4.3.1" />
   </ItemGroup>
-</Project>
+</Project>

+ 11 - 0
build/EmbedXaml.props

@@ -0,0 +1,11 @@
+<Project DefaultTargets="Build" 
+  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+     <Compile Update="**\*.xaml.cs">
+      <DependentUpon>%(Filename)</DependentUpon>
+    </Compile>
+    <EmbeddedResource Include="**\*.xaml">
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+  </ItemGroup>
+</Project>

+ 13 - 0
build/SampleApp.props

@@ -0,0 +1,13 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(TargetFramework)'=='net461'" >
+    <OutputType>WinExe</OutputType>
+  </PropertyGroup>
+
+  <!-- Should be a Condition="'$(TargetFramework)'=='net461'" here but that doesn't work due
+       to https://github.com/dotnet/sdk/issues/1227 -->
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\Windows\Avalonia.Win32\Avalonia.Win32.csproj" />
+    <ProjectReference Include="..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj" />
+  </ItemGroup>
+  <Import Condition="'$(TargetFramework)'=='net461'" Project="SharpDX.props" />
+</Project>

+ 14 - 0
build/SharedVersion.props

@@ -0,0 +1,14 @@
+<Project DefaultTargets="Build" 
+  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Product>Avalonia</Product>
+    <Version>0.6.2</Version>
+    <Copyright>Copyright 2016 &#169; The AvaloniaUI Project</Copyright>
+    <PackageLicenseUrl>https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md</PackageLicenseUrl>
+    <PackageProjectUrl>https://github.com/AvaloniaUI/Avalonia/</PackageProjectUrl>
+    <RepositoryUrl>https://github.com/AvaloniaUI/Avalonia/</RepositoryUrl>
+    <GenerateDocumentationFile>true</GenerateDocumentationFile>
+    <NoWarn>CS1591</NoWarn>
+    <LangVersion>latest</LangVersion>
+  </PropertyGroup>
+</Project>

+ 1 - 1
parameters.cake

@@ -115,7 +115,7 @@ public class Parameters
 
         FileZipSuffix = Version + ".zip";
         ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix);
-        ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix);
+        ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461");
         ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix);
     }
 }

+ 26 - 148
samples/BindingTest/BindingTest.csproj

@@ -1,155 +1,33 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}</ProjectGuid>
-    <OutputType>WinExe</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>BindingTest</RootNamespace>
-    <AssemblyName>BindingTest</AssemblyName>
-    <TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
-    <TargetFrameworkProfile />
-    <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
+    <OutputType>Exe</OutputType>
+    <TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup>
-    <StartupObject />
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.ComponentModel.DataAnnotations" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="App.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-    <Compile Include="App.xaml.cs">
-      <DependentUpon>App.xaml</DependentUpon>
-    </Compile>
-    <Compile Include="MainWindow.xaml.cs">
-      <DependentUpon>MainWindow.xaml</DependentUpon>
-    </Compile>
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="TestItemView.xaml.cs">
-      <DependentUpon>TestItemView.xaml</DependentUpon>
-    </Compile>
-    <Compile Include="ViewModels\DataAnnotationsErrorViewModel.cs" />
-    <Compile Include="ViewModels\IndeiErrorViewModel.cs" />
-    <Compile Include="ViewModels\ExceptionErrorViewModel.cs" />
-    <Compile Include="ViewModels\MainWindowViewModel.cs" />
-    <Compile Include="ViewModels\NestedCommandViewModel.cs" />
-    <Compile Include="ViewModels\TestItem.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="App.config" />
-    <EmbeddedResource Include="MainWindow.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-    <EmbeddedResource Include="TestItemView.xaml" />
-  </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj">
-      <Project>{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}</Project>
-      <Name>Avalonia.DotNetFrameworkRuntime</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj">
-      <Project>{3e53a01a-b331-47f3-b828-4a5717e77a24}</Project>
-      <Name>Avalonia.Markup.Xaml</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj">
-      <Project>{6417e941-21bc-467b-a771-0de389353ce6}</Project>
-      <Name>Avalonia.Markup</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj">
-      <Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project>
-      <Name>Avalonia.Animation</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Base\Avalonia.Base.csproj">
-      <Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project>
-      <Name>Avalonia.Base</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj">
-      <Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project>
-      <Name>Avalonia.Controls</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj">
-      <Project>{799a7bb5-3c2c-48b6-85a7-406a12c420da}</Project>
-      <Name>Avalonia.DesignerSupport</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj">
-      <Project>{7062ae20-5dcc-4442-9645-8195bdece63e}</Project>
-      <Name>Avalonia.Diagnostics</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Input\Avalonia.Input.csproj">
-      <Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project>
-      <Name>Avalonia.Input</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Interactivity\Avalonia.Interactivity.csproj">
-      <Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project>
-      <Name>Avalonia.Interactivity</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Layout\Avalonia.Layout.csproj">
-      <Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project>
-      <Name>Avalonia.Layout</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj">
-      <Project>{b61b66a3-b82d-4875-8001-89d3394fe0c9}</Project>
-      <Name>Avalonia.Logging.Serilog</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj">
-      <Project>{6417b24e-49c2-4985-8db2-3ab9d898ec91}</Project>
-      <Name>Avalonia.ReactiveUI</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Visuals\Avalonia.Visuals.csproj">
-      <Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
-      <Name>Avalonia.Visuals</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj">
-      <Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project>
-      <Name>Avalonia.Styling</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj">
-      <Project>{3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}</Project>
-      <Name>Avalonia.Themes.Default</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj" Condition="'$(Platform)'!='Mono'">
-      <Project>{3e908f67-5543-4879-a1dc-08eace79b3cd}</Project>
-      <Name>Avalonia.Direct2D1</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Windows\Avalonia.Win32\Avalonia.Win32.csproj" Condition="'$(Platform)'!='Mono'">
-      <Project>{811a76cf-1cf6-440f-963b-bbe31bd72a82}</Project>
-      <Name>Avalonia.Win32</Name>
-    </ProjectReference>
+    <ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj" />
+    
+    <ProjectReference Condition="'$(TargetFramework)'=='netcoreapp2.0'" Include="..\..\src\Avalonia.DotNetCoreRuntime\Avalonia.DotNetCoreRuntime.csproj" />
+                      
+    <ProjectReference Condition="'$(TargetFramework)'=='net461'" Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj" />
+
+    <ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Base\Avalonia.Base.csproj" />
+    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
+    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Input\Avalonia.Input.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Interactivity\Avalonia.Interactivity.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Layout\Avalonia.Layout.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Visuals\Avalonia.Visuals.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj" />
   </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\..\build\SampleApp.props" />
+  <Import Project="..\..\build\EmbedXaml.props" />
   <Import Project="..\..\build\Serilog.props" />
   <Import Project="..\..\build\Rx.props" />
   <Import Project="..\..\build\ReactiveUI.props" />

+ 4 - 1
samples/BindingTest/MainWindow.xaml

@@ -1,7 +1,10 @@
 <Window xmlns="https://github.com/avaloniaui"
         xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
         xmlns:vm="clr-namespace:BindingTest.ViewModels"
-        xmlns:local="clr-namespace:BindingTest">
+        xmlns:local="clr-namespace:BindingTest"
+        Title="AvaloniaUI Bindings Test"
+        Width="800"
+        Height="600">
   <Window.Styles>
     <Style Selector="TextBlock.h1">
       <Setter Property="FontSize" Value="18"/>

+ 0 - 36
samples/BindingTest/Properties/AssemblyInfo.cs

@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("BindingTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("BindingTest")]
-[assembly: AssemblyCopyright("Copyright ©  2015")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("08b3e6b9-1cd5-443c-9f61-6d49d1c5f162")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]

+ 13 - 130
samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj

@@ -1,138 +1,21 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+<Project Sdk="Microsoft.NET.Sdk">
+
   <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{2B888490-D14A-4BCA-AB4B-48676FA93C9B}</ProjectGuid>
-    <OutputType>WinExe</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>ControlCatalog.Desktop</RootNamespace>
-    <AssemblyName>ControlCatalog.Desktop</AssemblyName>
-    <TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
-    <TargetFrameworkProfile />
-    <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net461</TargetFramework>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <PlatformTarget>x86</PlatformTarget>
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup>
-    <StartupObject />
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Net.Http" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Program.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-  </ItemGroup>
+
   <ItemGroup>
-    <None Include="App.config" />
+    <ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj" />
+    <ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
   </ItemGroup>
+
   <ItemGroup>
-    <ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj">
-      <Project>{799a7bb5-3c2c-48b6-85a7-406a12c420da}</Project>
-      <Name>Avalonia.DesignerSupport</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj">
-      <Project>{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}</Project>
-      <Name>Avalonia.DotNetFrameworkRuntime</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Gtk\Avalonia.Gtk3\Avalonia.Gtk3.csproj">
-      <Project>{bb1f7bb5-6ad4-4776-94d9-c09d0a972658}</Project>
-      <Name>Avalonia.Gtk3</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj">
-      <Project>{3E53A01A-B331-47F3-B828-4A5717E77A24}</Project>
-      <Name>Avalonia.Markup.Xaml</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj">
-      <Project>{6417E941-21BC-467B-A771-0DE389353CE6}</Project>
-      <Name>Avalonia.Markup</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj">
-      <Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project>
-      <Name>Avalonia.Animation</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Base\Avalonia.Base.csproj">
-      <Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project>
-      <Name>Avalonia.Base</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj">
-      <Project>{D2221C82-4A25-4583-9B43-D791E3F6820C}</Project>
-      <Name>Avalonia.Controls</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Input\Avalonia.Input.csproj">
-      <Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project>
-      <Name>Avalonia.Input</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Interactivity\Avalonia.Interactivity.csproj">
-      <Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project>
-      <Name>Avalonia.Interactivity</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Layout\Avalonia.Layout.csproj">
-      <Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project>
-      <Name>Avalonia.Layout</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj">
-      <Project>{B61B66A3-B82D-4875-8001-89D3394FE0C9}</Project>
-      <Name>Avalonia.Logging.Serilog</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Visuals\Avalonia.Visuals.csproj">
-      <Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
-      <Name>Avalonia.Visuals</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj">
-      <Project>{F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}</Project>
-      <Name>Avalonia.Styling</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj">
-      <Project>{3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}</Project>
-      <Name>Avalonia.Themes.Default</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj">
-      <Project>{7d2d3083-71dd-4cc9-8907-39a0d86fb322}</Project>
-      <Name>Avalonia.Skia</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj" Condition="'$(Platform)'!='Mono'">
-      <Project>{3E908F67-5543-4879-A1DC-08EACE79B3CD}</Project>
-      <Name>Avalonia.Direct2D1</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Windows\Avalonia.Win32\Avalonia.Win32.csproj" Condition="'$(Platform)'!='Mono'">
-      <Project>{811A76CF-1CF6-440F-963B-BBE31BD72A82}</Project>
-      <Name>Avalonia.Win32</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj">
-      <Project>{d0a739b9-3c68-4ba6-a328-41606954b6bd}</Project>
-      <Name>ControlCatalog</Name>
-    </ProjectReference>
+    <Folder Include="Properties\" />
   </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+
+  <Import Project="..\..\build\SampleApp.props" />
   <Import Project="..\..\build\Serilog.props" />
-  <Import Project="..\..\build\SkiaSharp.props" />
 </Project>

+ 0 - 36
samples/ControlCatalog.Desktop/Properties/AssemblyInfo.cs

@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("ControlCatalog.Desktop")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("ControlCatalog.Desktop")]
-[assembly: AssemblyCopyright("Copyright ©  2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("2b888490-d14a-4bca-ab4b-48676fa93c9b")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]

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

@@ -10,10 +10,16 @@
       <StackPanel Orientation="Vertical" Gap="8">
         <TextBox Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit." Width="200" />
         <TextBox Width="200" Watermark="Watermark" />
-        <TextBox Width="200" 
-                 Watermark="Floating Watermark" 
+        <TextBox Width="200"
+                 Watermark="Floating Watermark"
                  UseFloatingWatermark="True"
                  Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit."/>
+
+        <TextBox Width="200"
+                 Watermark="Password Box"
+                 UseFloatingWatermark="True"
+                 PasswordChar="*"
+                 Text="Password" />
         <TextBox Width="200" Text="Left aligned text" TextAlignment="Left" />
         <TextBox Width="200" Text="Center aligned text" TextAlignment="Center" />
         <TextBox Width="200" Text="Right aligned text" TextAlignment="Right" />

+ 3 - 0
samples/Directory.Build.props

@@ -0,0 +1,3 @@
+<Project>
+  <Import Project="..\build\SharedVersion.props" />
+</Project>

+ 4 - 2
samples/RenderTest/MainWindow.xaml

@@ -1,6 +1,8 @@
 <Window xmlns="https://github.com/avaloniaui"
-        Title="Avalonia Render Test"
-        xmlns:pages="clr-namespace:RenderTest.Pages">
+        Title="AvaloniaUI Rendering Test"
+        xmlns:pages="clr-namespace:RenderTest.Pages"
+        Width="800"
+        Height="600">
   <DockPanel>
     <Menu DockPanel.Dock="Top">
       <MenuItem Header="Rendering">

+ 0 - 36
samples/RenderTest/Properties/AssemblyInfo.cs

@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("RenderTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("RenderTest")]
-[assembly: AssemblyCopyright("Copyright ©  2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("f1fdc5b0-4654-416f-ae69-e3e9bbd87801")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]

+ 27 - 178
samples/RenderTest/RenderTest.csproj

@@ -1,184 +1,33 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}</ProjectGuid>
-    <OutputType>WinExe</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>RenderTest</RootNamespace>
-    <AssemblyName>RenderTest</AssemblyName>
-    <TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
-    <TargetFrameworkProfile />
+    <OutputType>Exe</OutputType>
+    <TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup>
-    <StartupObject />
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Net.Http" />
-    <Reference Include="System.Xml" />
-    <Reference Include="WindowsBase" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="App.xaml.cs">
-      <DependentUpon>App.xaml</DependentUpon>
-    </Compile>
-    <Compile Include="Pages\DrawingPage.xaml.cs">
-      <DependentUpon>DrawingPage.xaml</DependentUpon>
-    </Compile>
-    <Compile Include="Pages\ClippingPage.xaml.cs">
-      <DependentUpon>ClippingPage.xaml</DependentUpon>
-    </Compile>
-    <Compile Include="Pages\AnimationsPage.xaml.cs">
-      <DependentUpon>AnimationsPage.xaml</DependentUpon>
-    </Compile>
-    <Compile Include="Program.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="MainWindow.xaml.cs">
-      <DependentUpon>MainWindow.xaml</DependentUpon>
-    </Compile>
-    <Compile Include="ViewModels\MainWindowViewModel.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="App.config" />
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="App.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-  </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj">
-      <Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project>
-      <Name>Avalonia.Animation</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Base\Avalonia.Base.csproj">
-      <Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project>
-      <Name>Avalonia.Base</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj">
-      <Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project>
-      <Name>Avalonia.Controls</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj">
-      <Project>{799a7bb5-3c2c-48b6-85a7-406a12c420da}</Project>
-      <Name>Avalonia.DesignerSupport</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj">
-      <Project>{7062ae20-5dcc-4442-9645-8195bdece63e}</Project>
-      <Name>Avalonia.Diagnostics</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj">
-      <Project>{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}</Project>
-      <Name>Avalonia.DotNetFrameworkRuntime</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Input\Avalonia.Input.csproj">
-      <Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project>
-      <Name>Avalonia.Input</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Interactivity\Avalonia.Interactivity.csproj">
-      <Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project>
-      <Name>Avalonia.Interactivity</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Layout\Avalonia.Layout.csproj">
-      <Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project>
-      <Name>Avalonia.Layout</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj">
-      <Project>{b61b66a3-b82d-4875-8001-89d3394fe0c9}</Project>
-      <Name>Avalonia.Logging.Serilog</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj">
-      <Project>{6417b24e-49c2-4985-8db2-3ab9d898ec91}</Project>
-      <Name>Avalonia.ReactiveUI</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Visuals\Avalonia.Visuals.csproj">
-      <Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
-      <Name>Avalonia.Visuals</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj">
-      <Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project>
-      <Name>Avalonia.Styling</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj">
-      <Project>{3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}</Project>
-      <Name>Avalonia.Themes.Default</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj">
-      <Project>{3e53a01a-b331-47f3-b828-4a5717e77a24}</Project>
-      <Name>Avalonia.Markup.Xaml</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj">
-      <Project>{6417e941-21bc-467b-a771-0de389353ce6}</Project>
-      <Name>Avalonia.Markup</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj">
-      <Project>{7d2d3083-71dd-4cc9-8907-39a0d86fb322}</Project>
-      <Name>Avalonia.Skia</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj">
-      <Project>{3e908f67-5543-4879-a1dc-08eace79b3cd}</Project>
-      <Name>Avalonia.Direct2D1</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Windows\Avalonia.Win32\Avalonia.Win32.csproj">
-      <Project>{811a76cf-1cf6-440f-963b-bbe31bd72a82}</Project>
-      <Name>Avalonia.Win32</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="MainWindow.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="SideBar.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="Pages\AnimationsPage.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="Pages\ClippingPage.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="Pages\DrawingPage.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-  </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+    <ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj" />
+    
+    <ProjectReference Condition="'$(TargetFramework)'=='netcoreapp2.0'" Include="..\..\src\Avalonia.DotNetCoreRuntime\Avalonia.DotNetCoreRuntime.csproj" />
+                      
+    <ProjectReference Condition="'$(TargetFramework)'=='net461'" Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj" />
+
+    <ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Base\Avalonia.Base.csproj" />
+    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
+    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Input\Avalonia.Input.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Interactivity\Avalonia.Interactivity.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Layout\Avalonia.Layout.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Visuals\Avalonia.Visuals.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj" />
+  </ItemGroup>
+  <Import Project="..\..\build\SampleApp.props" />
+  <Import Project="..\..\build\EmbedXaml.props" />
   <Import Project="..\..\build\Serilog.props" />
   <Import Project="..\..\build\Rx.props" />
   <Import Project="..\..\build\ReactiveUI.props" />

+ 3 - 1
samples/VirtualizationTest/MainWindow.xaml

@@ -1,5 +1,7 @@
 <Window xmlns="https://github.com/avaloniaui"
-        Title="Avalonia Virtualization Test">
+        Title="AvaloniaUI Virtualization Test"
+        Width="800"
+        Height="600">
     <DockPanel LastChildFill="True" Margin="16">
         <StackPanel DockPanel.Dock="Right" 
                     Margin="16 0 0 0" 

+ 0 - 36
samples/VirtualizationTest/Properties/AssemblyInfo.cs

@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("VirtualizationTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("VirtualizationTest")]
-[assembly: AssemblyCopyright("Copyright ©  2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("fbcaf3d0-2808-4934-8e96-3f607594517b")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]

+ 26 - 144
samples/VirtualizationTest/VirtualizationTest.csproj

@@ -1,151 +1,33 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{FBCAF3D0-2808-4934-8E96-3F607594517B}</ProjectGuid>
-    <OutputType>WinExe</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>VirtualizationTest</RootNamespace>
-    <AssemblyName>VirtualizationTest</AssemblyName>
-    <TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
-    <TargetFrameworkProfile />
+    <OutputType>Exe</OutputType>
+    <TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup>
-    <StartupObject />
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Net.Http" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="App.xaml.cs">
-      <DependentUpon>App.xaml</DependentUpon>
-    </Compile>
-    <Compile Include="MainWindow.xaml.cs">
-      <DependentUpon>MainWindow.xaml</DependentUpon>
-    </Compile>
-    <Compile Include="Program.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="ViewModels\ItemViewModel.cs" />
-    <Compile Include="ViewModels\MainWindowViewModel.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="App.config" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj">
-      <Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project>
-      <Name>Avalonia.Animation</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Base\Avalonia.Base.csproj">
-      <Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project>
-      <Name>Avalonia.Base</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj">
-      <Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project>
-      <Name>Avalonia.Controls</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj">
-      <Project>{799a7bb5-3c2c-48b6-85a7-406a12c420da}</Project>
-      <Name>Avalonia.DesignerSupport</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj">
-      <Project>{7062ae20-5dcc-4442-9645-8195bdece63e}</Project>
-      <Name>Avalonia.Diagnostics</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj">
-      <Project>{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}</Project>
-      <Name>Avalonia.DotNetFrameworkRuntime</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Input\Avalonia.Input.csproj">
-      <Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project>
-      <Name>Avalonia.Input</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Interactivity\Avalonia.Interactivity.csproj">
-      <Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project>
-      <Name>Avalonia.Interactivity</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Layout\Avalonia.Layout.csproj">
-      <Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project>
-      <Name>Avalonia.Layout</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj">
-      <Project>{B61B66A3-B82D-4875-8001-89D3394FE0C9}</Project>
-      <Name>Avalonia.Logging.Serilog</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj">
-      <Project>{6417b24e-49c2-4985-8db2-3ab9d898ec91}</Project>
-      <Name>Avalonia.ReactiveUI</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Visuals\Avalonia.Visuals.csproj">
-      <Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
-      <Name>Avalonia.Visuals</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj">
-      <Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project>
-      <Name>Avalonia.Styling</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj">
-      <Project>{3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}</Project>
-      <Name>Avalonia.Themes.Default</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj">
-      <Project>{3e53a01a-b331-47f3-b828-4a5717e77a24}</Project>
-      <Name>Avalonia.Markup.Xaml</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj">
-      <Project>{6417e941-21bc-467b-a771-0de389353ce6}</Project>
-      <Name>Avalonia.Markup</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj" Condition="'$(Platform)'!='Mono'">
-      <Project>{3e908f67-5543-4879-a1dc-08eace79b3cd}</Project>
-      <Name>Avalonia.Direct2D1</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\..\src\Windows\Avalonia.Win32\Avalonia.Win32.csproj" Condition="'$(Platform)'!='Mono'">
-      <Project>{811a76cf-1cf6-440f-963b-bbe31bd72a82}</Project>
-      <Name>Avalonia.Win32</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="App.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-  </ItemGroup>
   <ItemGroup>
-    <EmbeddedResource Include="MainWindow.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
+    <ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj" />
+    
+    <ProjectReference Condition="'$(TargetFramework)'=='netcoreapp2.0'" Include="..\..\src\Avalonia.DotNetCoreRuntime\Avalonia.DotNetCoreRuntime.csproj" />
+                      
+    <ProjectReference Condition="'$(TargetFramework)'=='net461'" Include="..\..\src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj" />
+
+    <ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Base\Avalonia.Base.csproj" />
+    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
+    <ProjectReference Include="..\..\src\Markup\Avalonia.Markup\Avalonia.Markup.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Animation\Avalonia.Animation.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Input\Avalonia.Input.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Interactivity\Avalonia.Interactivity.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Layout\Avalonia.Layout.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Visuals\Avalonia.Visuals.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj" />
   </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\..\build\SampleApp.props" />
+  <Import Project="..\..\build\EmbedXaml.props" />
   <Import Project="..\..\build\Serilog.props" />
   <Import Project="..\..\build\Rx.props" />
   <Import Project="..\..\build\ReactiveUI.props" />

+ 0 - 28
src/Avalonia.Animation/Avalonia.Animation.csproj

@@ -1,35 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Animation.xml</DocumentationFile>
-    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Animation.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-  </PropertyGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-  </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
   </ItemGroup>

+ 0 - 6
src/Avalonia.Animation/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System.Reflection;
-
-[assembly: AssemblyTitle("Avalonia.Animation")]

+ 1 - 28
src/Avalonia.Base/Avalonia.Base.csproj

@@ -1,36 +1,9 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+    <AssemblyName>Avalonia.Base</AssemblyName>
     <RootNamespace>Avalonia</RootNamespace>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Base.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Base.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-  </PropertyGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-  </ItemGroup>
   <Import Project="..\..\build\Base.props" />
   <Import Project="..\..\build\Rx.props" />
   <Import Project="..\..\build\JetBrains.Annotations.props" />

+ 15 - 3
src/Avalonia.Base/AvaloniaObject.cs

@@ -71,7 +71,8 @@ namespace Avalonia
         public AvaloniaObject()
         {
             VerifyAccess();
-            foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegistered(this))
+
+            void Notify(AvaloniaProperty property)
             {
                 object value = property.IsDirect ?
                     ((IDirectPropertyAccessor)property).GetValue(this) :
@@ -86,6 +87,16 @@ namespace Avalonia
 
                 property.NotifyInitialized(e);
             }
+
+            foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegistered(this))
+            {
+                Notify(property);
+            }
+
+            foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegisteredAttached(this.GetType()))
+            {
+                Notify(property);
+            }
         }
 
         /// <summary>
@@ -128,8 +139,9 @@ namespace Avalonia
                     {
                         _inheritanceParent.PropertyChanged -= ParentPropertyChanged;
                     }
-
-                    var inherited = (from property in AvaloniaPropertyRegistry.Instance.GetRegistered(this)
+                    var properties = AvaloniaPropertyRegistry.Instance.GetRegistered(this)
+                        .Concat(AvaloniaPropertyRegistry.Instance.GetRegisteredAttached(this.GetType()));
+                    var inherited = (from property in properties
                                      where property.Inherits
                                      select new
                                      {

+ 0 - 1
src/Avalonia.Base/Properties/AssemblyInfo.cs

@@ -4,7 +4,6 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
-[assembly: AssemblyTitle("Avalonia.Base")]
 [assembly: InternalsVisibleTo("Avalonia.Base.UnitTests")]
 [assembly: InternalsVisibleTo("Avalonia.UnitTests")]
 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] 

+ 20 - 6
src/Avalonia.Base/Utilities/StringTokenizer.cs

@@ -52,9 +52,16 @@ namespace Avalonia.Utilities
 
         public bool TryReadInt32(out Int32 result, char? separator = null)
         {
-            var success = TryReadString(out var stringResult, separator);
-            result = success ? int.Parse(stringResult, _formatProvider) : 0;
-            return success;
+            if (TryReadString(out var stringResult, separator) &&
+                int.TryParse(stringResult, NumberStyles.Integer, _formatProvider, out result))
+            {
+                return true;
+            }
+            else
+            {
+                result = default(Int32);
+                return false;
+            }
         }
 
         public int ReadInt32(char? separator = null)
@@ -69,9 +76,16 @@ namespace Avalonia.Utilities
 
         public bool TryReadDouble(out double result, char? separator = null)
         {
-            var success = TryReadString(out var stringResult, separator);
-            result = success ? double.Parse(stringResult, _formatProvider) : 0;
-            return success;
+            if (TryReadString(out var stringResult, separator) &&
+                double.TryParse(stringResult, NumberStyles.Float, _formatProvider, out result))
+            {
+                return true;
+            }
+            else
+            {
+                result = default(double);
+                return false;
+            }
         }
 
         public double ReadDouble(char? separator = null)

+ 4 - 0
src/Avalonia.Controls/AutoCompleteBox.cs

@@ -1954,6 +1954,10 @@ namespace Avalonia.Controls
             // 1. Minimum prefix length
             // 2. If a delay timer is in use, use it
             bool populateReady = newText.Length >= MinimumPrefixLength && MinimumPrefixLength >= 0;
+            if(populateReady && MinimumPrefixLength == 0 && String.IsNullOrEmpty(newText) && String.IsNullOrEmpty(SearchText))
+            {
+                populateReady = false;
+            }
             _userCalledPopulate = populateReady ? userInitiated : false;
 
             // Update the interface and values only as necessary

+ 0 - 28
src/Avalonia.Controls/Avalonia.Controls.csproj

@@ -1,35 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Controls.xml</DocumentationFile>
-    <NoWarn>CS1591;CS0067</NoWarn>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Controls.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-  </PropertyGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-  </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />

+ 3 - 25
src/Avalonia.Controls/Border.cs

@@ -3,6 +3,7 @@
 
 using Avalonia;
 using Avalonia.Controls.Utils;
+using Avalonia.Layout;
 using Avalonia.Media;
 
 namespace Avalonia.Controls
@@ -99,7 +100,7 @@ namespace Avalonia.Controls
         /// <returns>The desired size of the control.</returns>
         protected override Size MeasureOverride(Size availableSize)
         {
-            return MeasureOverrideImpl(availableSize, Child, Padding, BorderThickness);
+            return LayoutHelper.MeasureChild(Child, availableSize, Padding, BorderThickness);
         }
 
         /// <summary>
@@ -109,32 +110,9 @@ namespace Avalonia.Controls
         /// <returns>The space taken.</returns>
         protected override Size ArrangeOverride(Size finalSize)
         {
-            if (Child != null)
-            {
-                var padding = Padding + BorderThickness;
-                Child.Arrange(new Rect(finalSize).Deflate(padding));
-            }
-
             _borderRenderHelper.Update(finalSize, BorderThickness, CornerRadius);
 
-            return finalSize;
-        }
-
-        internal static Size MeasureOverrideImpl(
-            Size availableSize,
-            IControl child,
-            Thickness padding,
-            Thickness borderThickness)
-        {
-            padding += borderThickness;
-
-            if (child != null)
-            {
-                child.Measure(availableSize.Deflate(padding));
-                return child.DesiredSize.Inflate(padding);
-            }
-
-            return new Size(padding.Left + padding.Right, padding.Bottom + padding.Top);
+            return LayoutHelper.ArrangeChild(Child, finalSize, Padding, BorderThickness);
         }
     }
 }

+ 3 - 14
src/Avalonia.Controls/Decorator.cs

@@ -1,6 +1,7 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
+using Avalonia.Layout;
 using Avalonia.Metadata;
 
 namespace Avalonia.Controls
@@ -53,25 +54,13 @@ namespace Avalonia.Controls
         /// <inheritdoc/>
         protected override Size MeasureOverride(Size availableSize)
         {
-            var content = Child;
-            var padding = Padding;
-
-            if (content != null)
-            {
-                content.Measure(availableSize.Deflate(padding));
-                return content.DesiredSize.Inflate(padding);
-            }
-            else
-            {
-                return new Size(padding.Left + padding.Right, padding.Bottom + padding.Top);
-            }
+            return LayoutHelper.MeasureChild(Child, availableSize, Padding);
         }
 
         /// <inheritdoc/>
         protected override Size ArrangeOverride(Size finalSize)
         {
-            Child?.Arrange(new Rect(finalSize).Deflate(Padding));
-            return finalSize;
+            return LayoutHelper.ArrangeChild(Child, finalSize, Padding);
         }
 
         /// <summary>

+ 148 - 674
src/Avalonia.Controls/Grid.cs

@@ -4,7 +4,10 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Runtime.CompilerServices;
 using Avalonia.Collections;
+using Avalonia.Controls.Utils;
+using JetBrains.Annotations;
 
 namespace Avalonia.Controls
 {
@@ -45,10 +48,6 @@ namespace Avalonia.Controls
 
         private RowDefinitions _rowDefinitions;
 
-        private Segment[,] _rowMatrix;
-
-        private Segment[,] _colMatrix;
-
         /// <summary>
         /// Gets or sets the columns definitions for the grid.
         /// </summary>
@@ -183,6 +182,18 @@ namespace Avalonia.Controls
             element.SetValue(RowSpanProperty, value);
         }
 
+        /// <summary>
+        /// Gets the result of the last column measurement.
+        /// Use this result to reduce the arrange calculation.
+        /// </summary>
+        private GridLayout.MeasureResult _columnMeasureCache;
+
+        /// <summary>
+        /// Gets the result of the last row measurement.
+        /// Use this result to reduce the arrange calculation.
+        /// </summary>
+        private GridLayout.MeasureResult _rowMeasureCache;
+
         /// <summary>
         /// Measures the grid.
         /// </summary>
@@ -190,293 +201,74 @@ namespace Avalonia.Controls
         /// <returns>The desired size of the control.</returns>
         protected override Size MeasureOverride(Size constraint)
         {
-            Size totalSize = constraint;
-            int colCount = ColumnDefinitions.Count;
-            int rowCount = RowDefinitions.Count;
-            double totalStarsX = 0;
-            double totalStarsY = 0;
-            bool emptyRows = rowCount == 0;
-            bool emptyCols = colCount == 0;
-            bool hasChildren = Children.Count > 0;
-
-            if (emptyRows)
-            {
-                rowCount = 1;
-            }
-
-            if (emptyCols)
-            {
-                colCount = 1;
-            }
-
-            CreateMatrices(rowCount, colCount);
+            // Situation 1/2:
+            // If the grid doesn't have any column/row definitions, it behaves like a normal panel.
+            // GridLayout supports this situation but we handle this separately for performance.
 
-            if (emptyRows)
-            {
-                _rowMatrix[0, 0] = new Segment(0, 0, double.PositiveInfinity, GridUnitType.Star);
-                _rowMatrix[0, 0].Stars = 1.0;
-                totalStarsY += 1.0;
-            }
-            else
+            if (ColumnDefinitions.Count == 0 && RowDefinitions.Count == 0)
             {
-                for (int i = 0; i < rowCount; i++)
+                var maxWidth = 0.0;
+                var maxHeight = 0.0;
+                foreach (var child in Children.OfType<Control>())
                 {
-                    RowDefinition rowdef = RowDefinitions[i];
-                    GridLength height = rowdef.Height;
-
-                    rowdef.ActualHeight = double.PositiveInfinity;
-                    _rowMatrix[i, i] = new Segment(0, rowdef.MinHeight, rowdef.MaxHeight, height.GridUnitType);
-
-                    if (height.GridUnitType == GridUnitType.Pixel)
-                    {
-                        _rowMatrix[i, i].OfferedSize = Clamp(height.Value, _rowMatrix[i, i].Min, _rowMatrix[i, i].Max);
-                        _rowMatrix[i, i].DesiredSize = _rowMatrix[i, i].OfferedSize;
-                        rowdef.ActualHeight = _rowMatrix[i, i].OfferedSize;
-                    }
-                    else if (height.GridUnitType == GridUnitType.Star)
-                    {
-                        _rowMatrix[i, i].Stars = height.Value;
-                        totalStarsY += height.Value;
-                    }
-                    else if (height.GridUnitType == GridUnitType.Auto)
-                    {
-                        _rowMatrix[i, i].OfferedSize = Clamp(0, _rowMatrix[i, i].Min, _rowMatrix[i, i].Max);
-                        _rowMatrix[i, i].DesiredSize = _rowMatrix[i, i].OfferedSize;
-                    }
+                    child.Measure(constraint);
+                    maxWidth = Math.Max(maxWidth, child.DesiredSize.Width);
+                    maxHeight = Math.Max(maxHeight, child.DesiredSize.Height);
                 }
-            }
 
-            if (emptyCols)
-            {
-                _colMatrix[0, 0] = new Segment(0, 0, double.PositiveInfinity, GridUnitType.Star);
-                _colMatrix[0, 0].Stars = 1.0;
-                totalStarsX += 1.0;
-            }
-            else
-            {
-                for (int i = 0; i < colCount; i++)
-                {
-                    ColumnDefinition coldef = ColumnDefinitions[i];
-                    GridLength width = coldef.Width;
-
-                    coldef.ActualWidth = double.PositiveInfinity;
-                    _colMatrix[i, i] = new Segment(0, coldef.MinWidth, coldef.MaxWidth, width.GridUnitType);
-
-                    if (width.GridUnitType == GridUnitType.Pixel)
-                    {
-                        _colMatrix[i, i].OfferedSize = Clamp(width.Value, _colMatrix[i, i].Min, _colMatrix[i, i].Max);
-                        _colMatrix[i, i].DesiredSize = _colMatrix[i, i].OfferedSize;
-                        coldef.ActualWidth = _colMatrix[i, i].OfferedSize;
-                    }
-                    else if (width.GridUnitType == GridUnitType.Star)
-                    {
-                        _colMatrix[i, i].Stars = width.Value;
-                        totalStarsX += width.Value;
-                    }
-                    else if (width.GridUnitType == GridUnitType.Auto)
-                    {
-                        _colMatrix[i, i].OfferedSize = Clamp(0, _colMatrix[i, i].Min, _colMatrix[i, i].Max);
-                        _colMatrix[i, i].DesiredSize = _colMatrix[i, i].OfferedSize;
-                    }
-                }
+                maxWidth = Math.Min(maxWidth, constraint.Width);
+                maxHeight = Math.Min(maxHeight, constraint.Height);
+                return new Size(maxWidth, maxHeight);
             }
 
-            List<GridNode> sizes = new List<GridNode>();
-            GridNode node;
-            GridNode separator = new GridNode(null, 0, 0, 0);
-            int separatorIndex;
+            // Situation 2/2:
+            // If the grid defines some columns or rows.
+            // Debug Tip:
+            //     - GridLayout doesn't hold any state, so you can drag the debugger execution
+            //       arrow back to any statements and re-run them without any side-effect.
 
-            sizes.Add(separator);
+            var measureCache = new Dictionary<Control, Size>();
+            var (safeColumns, safeRows) = GetSafeColumnRows();
+            var columnLayout = new GridLayout(ColumnDefinitions);
+            var rowLayout = new GridLayout(RowDefinitions);
+            // Note: If a child stays in a * or Auto column/row, use constraint to measure it.
+            columnLayout.AppendMeasureConventions(safeColumns, child => MeasureOnce(child, constraint).Width);
+            rowLayout.AppendMeasureConventions(safeRows, child => MeasureOnce(child, constraint).Height);
 
-            // Pre-process the grid children so that we know what types of elements we have so
-            // we can apply our special measuring rules.
-            GridWalker gridWalker = new GridWalker(this, _rowMatrix, _colMatrix);
+            // Calculate measurement.
+            var columnResult = columnLayout.Measure(constraint.Width);
+            var rowResult = rowLayout.Measure(constraint.Height);
 
-            for (int i = 0; i < 6; i++)
+            // Use the results of the measurement to measure the rest of the children.
+            foreach (var child in Children.OfType<Control>())
             {
-                // These bools tell us which grid element type we should be measuring. i.e.
-                // 'star/auto' means we should measure elements with a star row and auto col
-                bool autoAuto = i == 0;
-                bool starAuto = i == 1;
-                bool autoStar = i == 2;
-                bool starAutoAgain = i == 3;
-                bool nonStar = i == 4;
-                bool remainingStar = i == 5;
-
-                if (hasChildren)
-                {
-                    ExpandStarCols(totalSize);
-                    ExpandStarRows(totalSize);
-                }
+                var (column, columnSpan) = safeColumns[child];
+                var (row, rowSpan) = safeRows[child];
+                var width = Enumerable.Range(column, columnSpan).Select(x => columnResult.LengthList[x]).Sum();
+                var height = Enumerable.Range(row, rowSpan).Select(x => rowResult.LengthList[x]).Sum();
 
-                foreach (Control child in Children)
-                {
-                    int col, row;
-                    int colspan, rowspan;
-                    double childSizeX = 0;
-                    double childSizeY = 0;
-                    bool starCol = false;
-                    bool starRow = false;
-                    bool autoCol = false;
-                    bool autoRow = false;
-
-                    col = Math.Min(GetColumn(child), colCount - 1);
-                    row = Math.Min(GetRow(child), rowCount - 1);
-                    colspan = Math.Min(GetColumnSpan(child), colCount - col);
-                    rowspan = Math.Min(GetRowSpan(child), rowCount - row);
-
-                    for (int r = row; r < row + rowspan; r++)
-                    {
-                        starRow |= _rowMatrix[r, r].Type == GridUnitType.Star;
-                        autoRow |= _rowMatrix[r, r].Type == GridUnitType.Auto;
-                    }
-
-                    for (int c = col; c < col + colspan; c++)
-                    {
-                        starCol |= _colMatrix[c, c].Type == GridUnitType.Star;
-                        autoCol |= _colMatrix[c, c].Type == GridUnitType.Auto;
-                    }
-
-                    // This series of if statements checks whether or not we should measure
-                    // the current element and also if we need to override the sizes
-                    // passed to the Measure call.
-
-                    // If the element has Auto rows and Auto columns and does not span Star
-                    // rows/cols it should only be measured in the auto_auto phase.
-                    // There are similar rules governing auto/star and star/auto elements.
-                    // NOTE: star/auto elements are measured twice. The first time with
-                    // an override for height, the second time without it.
-                    if (autoRow && autoCol && !starRow && !starCol)
-                    {
-                        if (!autoAuto)
-                        {
-                            continue;
-                        }
-
-                        childSizeX = double.PositiveInfinity;
-                        childSizeY = double.PositiveInfinity;
-                    }
-                    else if (starRow && autoCol && !starCol)
-                    {
-                        if (!(starAuto || starAutoAgain))
-                        {
-                            continue;
-                        }
-
-                        if (starAuto && gridWalker.HasAutoStar)
-                        {
-                            childSizeY = double.PositiveInfinity;
-                        }
-
-                        childSizeX = double.PositiveInfinity;
-                    }
-                    else if (autoRow && starCol && !starRow)
-                    {
-                        if (!autoStar)
-                        {
-                            continue;
-                        }
-
-                        childSizeY = double.PositiveInfinity;
-                    }
-                    else if ((autoRow || autoCol) && !(starRow || starCol))
-                    {
-                        if (!nonStar)
-                        {
-                            continue;
-                        }
-
-                        if (autoRow)
-                        {
-                            childSizeY = double.PositiveInfinity;
-                        }
-
-                        if (autoCol)
-                        {
-                            childSizeX = double.PositiveInfinity;
-                        }
-                    }
-                    else if (!(starRow || starCol))
-                    {
-                        if (!nonStar)
-                        {
-                            continue;
-                        }
-                    }
-                    else
-                    {
-                        if (!remainingStar)
-                        {
-                            continue;
-                        }
-                    }
-
-                    for (int r = row; r < row + rowspan; r++)
-                    {
-                        childSizeY += _rowMatrix[r, r].OfferedSize;
-                    }
-
-                    for (int c = col; c < col + colspan; c++)
-                    {
-                        childSizeX += _colMatrix[c, c].OfferedSize;
-                    }
-
-                    child.Measure(new Size(childSizeX, childSizeY));
-                    Size desired = child.DesiredSize;
-
-                    // Elements distribute their height based on two rules:
-                    // 1) Elements with rowspan/colspan == 1 distribute their height first
-                    // 2) Everything else distributes in a LIFO manner.
-                    // As such, add all UIElements with rowspan/colspan == 1 after the separator in
-                    // the list and everything else before it. Then to process, just keep popping
-                    // elements off the end of the list.
-                    if (!starAuto)
-                    {
-                        node = new GridNode(_rowMatrix, row + rowspan - 1, row, desired.Height);
-                        separatorIndex = sizes.IndexOf(separator);
-                        sizes.Insert(node.Row == node.Column ? separatorIndex + 1 : separatorIndex, node);
-                    }
-
-                    node = new GridNode(_colMatrix, col + colspan - 1, col, desired.Width);
-
-                    separatorIndex = sizes.IndexOf(separator);
-                    sizes.Insert(node.Row == node.Column ? separatorIndex + 1 : separatorIndex, node);
-                }
+                MeasureOnce(child, new Size(width, height));
+            }
 
-                sizes.Remove(separator);
+            // Cache the measure result and return the desired size.
+            _columnMeasureCache = columnResult;
+            _rowMeasureCache = rowResult;
+            return new Size(columnResult.DesiredLength, rowResult.DesiredLength);
 
-                while (sizes.Count > 0)
+            // Measure each child only once.
+            // If a child has been measured, it will just return the desired size.
+            Size MeasureOnce(Control child, Size size)
+            {
+                if (measureCache.TryGetValue(child, out var desiredSize))
                 {
-                    node = sizes.Last();
-                    node.Matrix[node.Row, node.Column].DesiredSize = Math.Max(node.Matrix[node.Row, node.Column].DesiredSize, node.Size);
-                    AllocateDesiredSize(rowCount, colCount);
-                    sizes.Remove(node);
+                    return desiredSize;
                 }
 
-                sizes.Add(separator);
-            }
-
-            // Once we have measured and distributed all sizes, we have to store
-            // the results. Every time we want to expand the rows/cols, this will
-            // be used as the baseline.
-            SaveMeasureResults();
-
-            sizes.Remove(separator);
-
-            double gridSizeX = 0;
-            double gridSizeY = 0;
-
-            for (int c = 0; c < colCount; c++)
-            {
-                gridSizeX += _colMatrix[c, c].DesiredSize;
+                child.Measure(size);
+                desiredSize = child.DesiredSize;
+                measureCache[child] = desiredSize;
+                return desiredSize;
             }
-
-            for (int r = 0; r < rowCount; r++)
-            {
-                gridSizeY += _rowMatrix[r, r].DesiredSize;
-            }
-
-            return new Size(gridSizeX, gridSizeY);
         }
 
         /// <summary>
@@ -486,456 +278,138 @@ namespace Avalonia.Controls
         /// <returns>The space taken.</returns>
         protected override Size ArrangeOverride(Size finalSize)
         {
-            int colCount = ColumnDefinitions.Count;
-            int rowCount = RowDefinitions.Count;
-            int colMatrixDim = _colMatrix.GetLength(0);
-            int rowMatrixDim = _rowMatrix.GetLength(0);
-
-            RestoreMeasureResults();
+            // Situation 1/2:
+            // If the grid doesn't have any column/row definitions, it behaves like a normal panel.
+            // GridLayout supports this situation but we handle this separately for performance.
 
-            double totalConsumedX = 0;
-            double totalConsumedY = 0;
-
-            for (int c = 0; c < colMatrixDim; c++)
+            if (ColumnDefinitions.Count == 0 && RowDefinitions.Count == 0)
             {
-                _colMatrix[c, c].OfferedSize = _colMatrix[c, c].DesiredSize;
-                totalConsumedX += _colMatrix[c, c].OfferedSize;
-            }
-
-            for (int r = 0; r < rowMatrixDim; r++)
-            {
-                _rowMatrix[r, r].OfferedSize = _rowMatrix[r, r].DesiredSize;
-                totalConsumedY += _rowMatrix[r, r].OfferedSize;
-            }
-
-            if (totalConsumedX != finalSize.Width)
-            {
-                ExpandStarCols(finalSize);
-            }
-
-            if (totalConsumedY != finalSize.Height)
-            {
-                ExpandStarRows(finalSize);
-            }
-
-            for (int c = 0; c < colCount; c++)
-            {
-                ColumnDefinitions[c].ActualWidth = _colMatrix[c, c].OfferedSize;
-            }
-
-            for (int r = 0; r < rowCount; r++)
-            {
-                RowDefinitions[r].ActualHeight = _rowMatrix[r, r].OfferedSize;
-            }
-
-            foreach (Control child in Children)
-            {
-                int col = Math.Min(GetColumn(child), colMatrixDim - 1);
-                int row = Math.Min(GetRow(child), rowMatrixDim - 1);
-                int colspan = Math.Min(GetColumnSpan(child), colMatrixDim - col);
-                int rowspan = Math.Min(GetRowSpan(child), rowMatrixDim - row);
-
-                double childFinalX = 0;
-                double childFinalY = 0;
-                double childFinalW = 0;
-                double childFinalH = 0;
-
-                for (int c = 0; c < col; c++)
-                {
-                    childFinalX += _colMatrix[c, c].OfferedSize;
-                }
-
-                for (int c = col; c < col + colspan; c++)
+                foreach (var child in Children.OfType<Control>())
                 {
-                    childFinalW += _colMatrix[c, c].OfferedSize;
+                    child.Arrange(new Rect(finalSize));
                 }
 
-                for (int r = 0; r < row; r++)
-                {
-                    childFinalY += _rowMatrix[r, r].OfferedSize;
-                }
-
-                for (int r = row; r < row + rowspan; r++)
-                {
-                    childFinalH += _rowMatrix[r, r].OfferedSize;
-                }
-
-                child.Arrange(new Rect(childFinalX, childFinalY, childFinalW, childFinalH));
+                return finalSize;
             }
 
-            return finalSize;
-        }
-
-        private static double Clamp(double val, double min, double max)
-        {
-            if (val < min)
-            {
-                return min;
-            }
-            else if (val > max)
-            {
-                return max;
-            }
-            else
-            {
-                return val;
-            }
-        }
+            // Situation 2/2:
+            // If the grid defines some columns or rows.
+            // Debug Tip:
+            //     - GridLayout doesn't hold any state, so you can drag the debugger execution
+            //       arrow back to any statements and re-run them without any side-effect.
 
-        private static int ValidateColumn(AvaloniaObject o, int value)
-        {
-            if (value < 0)
-            {
-                throw new ArgumentException("Invalid Grid.Column value.");
-            }
+            var (safeColumns, safeRows) = GetSafeColumnRows();
+            var columnLayout = new GridLayout(ColumnDefinitions);
+            var rowLayout = new GridLayout(RowDefinitions);
 
-            return value;
-        }
+            // Calculate for arrange result.
+            var columnResult = columnLayout.Arrange(finalSize.Width, _columnMeasureCache);
+            var rowResult = rowLayout.Arrange(finalSize.Height, _rowMeasureCache);
 
-        private static int ValidateRow(AvaloniaObject o, int value)
-        {
-            if (value < 0)
+            // Arrange the children.
+            foreach (var child in Children.OfType<Control>())
             {
-                throw new ArgumentException("Invalid Grid.Row value.");
-            }
+                var (column, columnSpan) = safeColumns[child];
+                var (row, rowSpan) = safeRows[child];
+                var x = Enumerable.Range(0, column).Sum(c => columnResult.LengthList[c]);
+                var y = Enumerable.Range(0, row).Sum(r => rowResult.LengthList[r]);
+                var width = Enumerable.Range(column, columnSpan).Sum(c => columnResult.LengthList[c]);
+                var height = Enumerable.Range(row, rowSpan).Sum(r => rowResult.LengthList[r]);
 
-            return value;
-        }
-
-        private void CreateMatrices(int rowCount, int colCount)
-        {
-            if (_rowMatrix == null || _colMatrix == null ||
-                _rowMatrix.GetLength(0) != rowCount ||
-                _colMatrix.GetLength(0) != colCount)
-            {
-                _rowMatrix = new Segment[rowCount, rowCount];
-                _colMatrix = new Segment[colCount, colCount];
-            }
-            else
-            {
-                Array.Clear(_rowMatrix, 0, _rowMatrix.Length);
-                Array.Clear(_colMatrix, 0, _colMatrix.Length);
+                child.Arrange(new Rect(x, y, width, height));
             }
-        }
-
-        private void ExpandStarCols(Size availableSize)
-        {
-            int matrixCount = _colMatrix.GetLength(0);
-            int columnsCount = ColumnDefinitions.Count;
-            double width = availableSize.Width;
 
-            for (int i = 0; i < matrixCount; i++)
+            // Assign the actual width.
+            for (var i = 0; i < ColumnDefinitions.Count; i++)
             {
-                if (_colMatrix[i, i].Type == GridUnitType.Star)
-                {
-                    _colMatrix[i, i].OfferedSize = 0;
-                }
-                else
-                {
-                    width = Math.Max(width - _colMatrix[i, i].OfferedSize, 0);
-                }
+                ColumnDefinitions[i].ActualWidth = columnResult.LengthList[i];
             }
 
-            AssignSize(_colMatrix, 0, matrixCount - 1, ref width, GridUnitType.Star, false);
-            width = Math.Max(0, width);
-
-            if (columnsCount > 0)
+            // Assign the actual height.
+            for (var i = 0; i < RowDefinitions.Count; i++)
             {
-                for (int i = 0; i < matrixCount; i++)
-                {
-                    if (_colMatrix[i, i].Type == GridUnitType.Star)
-                    {
-                        ColumnDefinitions[i].ActualWidth = _colMatrix[i, i].OfferedSize;
-                    }
-                }
-            }
-        }
-
-        private void ExpandStarRows(Size availableSize)
-        {
-            int matrixCount = _rowMatrix.GetLength(0);
-            int rowCount = RowDefinitions.Count;
-            double height = availableSize.Height;
-
-            // When expanding star rows, we need to zero out their height before
-            // calling AssignSize. AssignSize takes care of distributing the
-            // available size when there are Mins and Maxs applied.
-            for (int i = 0; i < matrixCount; i++)
-            {
-                if (_rowMatrix[i, i].Type == GridUnitType.Star)
-                {
-                    _rowMatrix[i, i].OfferedSize = 0.0;
-                }
-                else
-                {
-                    height = Math.Max(height - _rowMatrix[i, i].OfferedSize, 0);
-                }
+                RowDefinitions[i].ActualHeight = rowResult.LengthList[i];
             }
 
-            AssignSize(_rowMatrix, 0, matrixCount - 1, ref height, GridUnitType.Star, false);
-
-            if (rowCount > 0)
-            {
-                for (int i = 0; i < matrixCount; i++)
-                {
-                    if (_rowMatrix[i, i].Type == GridUnitType.Star)
-                    {
-                        RowDefinitions[i].ActualHeight = _rowMatrix[i, i].OfferedSize;
-                    }
-                }
-            }
+            // Return the render size.
+            return finalSize;
         }
 
-        private void AssignSize(
-            Segment[,] matrix,
-            int start,
-            int end,
-            ref double size,
-            GridUnitType type,
-            bool desiredSize)
+        /// <summary>
+        /// Get the safe column/columnspan and safe row/rowspan.
+        /// This method ensures that none of the children has a column/row outside the bounds of the definitions.
+        /// </summary>
+        [Pure]
+        private (Dictionary<Control, (int index, int span)> safeColumns,
+            Dictionary<Control, (int index, int span)> safeRows) GetSafeColumnRows()
         {
-            double count = 0;
-            bool assigned;
-
-            // Count how many segments are of the correct type. If we're measuring Star rows/cols
-            // we need to count the number of stars instead.
-            for (int i = start; i <= end; i++)
-            {
-                double segmentSize = desiredSize ? matrix[i, i].DesiredSize : matrix[i, i].OfferedSize;
-                if (segmentSize < matrix[i, i].Max)
-                {
-                    count += type == GridUnitType.Star ? matrix[i, i].Stars : 1;
-                }
-            }
-
-            do
-            {
-                double contribution = size / count;
-
-                assigned = false;
-
-                for (int i = start; i <= end; i++)
-                {
-                    double segmentSize = desiredSize ? matrix[i, i].DesiredSize : matrix[i, i].OfferedSize;
-
-                    if (!(matrix[i, i].Type == type && segmentSize < matrix[i, i].Max))
-                    {
-                        continue;
-                    }
-
-                    double newsize = segmentSize;
-                    newsize += contribution * (type == GridUnitType.Star ? matrix[i, i].Stars : 1);
-                    newsize = Math.Min(newsize, matrix[i, i].Max);
-                    assigned |= newsize > segmentSize;
-                    size -= newsize - segmentSize;
-
-                    if (desiredSize)
-                    {
-                        matrix[i, i].DesiredSize = newsize;
-                    }
-                    else
-                    {
-                        matrix[i, i].OfferedSize = newsize;
-                    }
-                }
-            }
-            while (assigned);
+            var columnCount = ColumnDefinitions.Count;
+            var rowCount = RowDefinitions.Count;
+            columnCount = columnCount == 0 ? 1 : columnCount;
+            rowCount = rowCount == 0 ? 1 : rowCount;
+            var safeColumns = Children.OfType<Control>().ToDictionary(child => child,
+                child => GetSafeSpan(columnCount, GetColumn(child), GetColumnSpan(child)));
+            var safeRows = Children.OfType<Control>().ToDictionary(child => child,
+                child => GetSafeSpan(rowCount, GetRow(child), GetRowSpan(child)));
+            return (safeColumns, safeRows);
         }
 
-        private void AllocateDesiredSize(int rowCount, int colCount)
+        /// <summary>
+        /// Gets the safe row/column and rowspan/columnspan for a specified range.
+        /// The user may assign row/column properties outside the bounds of the row/column count, this method coerces them inside.
+        /// </summary>
+        /// <param name="length">The row or column count.</param>
+        /// <param name="userIndex">The row or column that the user assigned.</param>
+        /// <param name="userSpan">The rowspan or columnspan that the user assigned.</param>
+        /// <returns>The safe row/column and rowspan/columnspan.</returns>
+        [Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static (int index, int span) GetSafeSpan(int length, int userIndex, int userSpan)
         {
-            // First allocate the heights of the RowDefinitions, then allocate
-            // the widths of the ColumnDefinitions.
-            for (int i = 0; i < 2; i++)
-            {
-                Segment[,] matrix = i == 0 ? _rowMatrix : _colMatrix;
-                int count = i == 0 ? rowCount : colCount;
-
-                for (int row = count - 1; row >= 0; row--)
-                {
-                    for (int col = row; col >= 0; col--)
-                    {
-                        bool spansStar = false;
-                        for (int j = row; j >= col; j--)
-                        {
-                            spansStar |= matrix[j, j].Type == GridUnitType.Star;
-                        }
-
-                        // This is the amount of pixels which must be available between the grid rows
-                        // at index 'col' and 'row'. i.e. if 'row' == 0 and 'col' == 2, there must
-                        // be at least 'matrix [row][col].size' pixels of height allocated between
-                        // all the rows in the range col -> row.
-                        double current = matrix[row, col].DesiredSize;
-
-                        // Count how many pixels have already been allocated between the grid rows
-                        // in the range col -> row. The amount of pixels allocated to each grid row/column
-                        // is found on the diagonal of the matrix.
-                        double totalAllocated = 0;
-
-                        for (int k = row; k >= col; k--)
-                        {
-                            totalAllocated += matrix[k, k].DesiredSize;
-                        }
-
-                        // If the size requirement has not been met, allocate the additional required
-                        // size between 'pixel' rows, then 'star' rows, finally 'auto' rows, until all
-                        // height has been assigned.
-                        if (totalAllocated < current)
-                        {
-                            double additional = current - totalAllocated;
-
-                            if (spansStar)
-                            {
-                                AssignSize(matrix, col, row, ref additional, GridUnitType.Star, true);
-                            }
-                            else
-                            {
-                                AssignSize(matrix, col, row, ref additional, GridUnitType.Pixel, true);
-                                AssignSize(matrix, col, row, ref additional, GridUnitType.Auto, true);
-                            }
-                        }
-                    }
-                }
-            }
-
-            int rowMatrixDim = _rowMatrix.GetLength(0);
-            int colMatrixDim = _colMatrix.GetLength(0);
+            var index = userIndex;
+            var span = userSpan;
 
-            for (int r = 0; r < rowMatrixDim; r++)
+            if (index < 0)
             {
-                _rowMatrix[r, r].OfferedSize = _rowMatrix[r, r].DesiredSize;
+                span = index + span;
+                index = 0;
             }
 
-            for (int c = 0; c < colMatrixDim; c++)
+            if (span <= 0)
             {
-                _colMatrix[c, c].OfferedSize = _colMatrix[c, c].DesiredSize;
+                span = 1;
             }
-        }
 
-        private void SaveMeasureResults()
-        {
-            int rowMatrixDim = _rowMatrix.GetLength(0);
-            int colMatrixDim = _colMatrix.GetLength(0);
-
-            for (int i = 0; i < rowMatrixDim; i++)
+            if (userIndex >= length)
             {
-                for (int j = 0; j < rowMatrixDim; j++)
-                {
-                    _rowMatrix[i, j].OriginalSize = _rowMatrix[i, j].OfferedSize;
-                }
+                index = length - 1;
+                span = 1;
             }
-
-            for (int i = 0; i < colMatrixDim; i++)
+            else if (userIndex + userSpan > length)
             {
-                for (int j = 0; j < colMatrixDim; j++)
-                {
-                    _colMatrix[i, j].OriginalSize = _colMatrix[i, j].OfferedSize;
-                }
-            }
-        }
-
-        private void RestoreMeasureResults()
-        {
-            int rowMatrixDim = _rowMatrix.GetLength(0);
-            int colMatrixDim = _colMatrix.GetLength(0);
-
-            for (int i = 0; i < rowMatrixDim; i++)
-            {
-                for (int j = 0; j < rowMatrixDim; j++)
-                {
-                    _rowMatrix[i, j].OfferedSize = _rowMatrix[i, j].OriginalSize;
-                }
+                span = length - userIndex;
             }
 
-            for (int i = 0; i < colMatrixDim; i++)
-            {
-                for (int j = 0; j < colMatrixDim; j++)
-                {
-                    _colMatrix[i, j].OfferedSize = _colMatrix[i, j].OriginalSize;
-                }
-            }
+            return (index, span);
         }
 
-        private struct Segment
+        private static int ValidateColumn(AvaloniaObject o, int value)
         {
-            public double OriginalSize;
-            public double Max;
-            public double Min;
-            public double DesiredSize;
-            public double OfferedSize;
-            public double Stars;
-            public GridUnitType Type;
-
-            public Segment(double offeredSize, double min, double max, GridUnitType type)
+            if (value < 0)
             {
-                OriginalSize = 0;
-                Min = min;
-                Max = max;
-                DesiredSize = 0;
-                OfferedSize = offeredSize;
-                Stars = 0;
-                Type = type;
+                throw new ArgumentException("Invalid Grid.Column value.");
             }
-        }
 
-        private struct GridNode
-        {
-            public readonly int Row;
-            public readonly int Column;
-            public readonly double Size;
-            public readonly Segment[,] Matrix;
-
-            public GridNode(Segment[,] matrix, int row, int col, double size)
-            {
-                Matrix = matrix;
-                Row = row;
-                Column = col;
-                Size = size;
-            }
+            return value;
         }
 
-        private class GridWalker
+        private static int ValidateRow(AvaloniaObject o, int value)
         {
-            public GridWalker(Grid grid, Segment[,] rowMatrix, Segment[,] colMatrix)
+            if (value < 0)
             {
-                int rowMatrixDim = rowMatrix.GetLength(0);
-                int colMatrixDim = colMatrix.GetLength(0);
-
-                foreach (Control child in grid.Children)
-                {
-                    bool starCol = false;
-                    bool starRow = false;
-                    bool autoCol = false;
-                    bool autoRow = false;
-
-                    int col = Math.Min(GetColumn(child), colMatrixDim - 1);
-                    int row = Math.Min(GetRow(child), rowMatrixDim - 1);
-                    int colspan = Math.Min(GetColumnSpan(child), colMatrixDim - 1);
-                    int rowspan = Math.Min(GetRowSpan(child), rowMatrixDim - 1);
-
-                    for (int r = row; r < row + rowspan; r++)
-                    {
-                        starRow |= rowMatrix[r, r].Type == GridUnitType.Star;
-                        autoRow |= rowMatrix[r, r].Type == GridUnitType.Auto;
-                    }
-
-                    for (int c = col; c < col + colspan; c++)
-                    {
-                        starCol |= colMatrix[c, c].Type == GridUnitType.Star;
-                        autoCol |= colMatrix[c, c].Type == GridUnitType.Auto;
-                    }
-
-                    HasAutoAuto |= autoRow && autoCol && !starRow && !starCol;
-                    HasStarAuto |= starRow && autoCol;
-                    HasAutoStar |= autoRow && starCol;
-                }
+                throw new ArgumentException("Invalid Grid.Row value.");
             }
 
-            public bool HasAutoAuto { get; }
-
-            public bool HasStarAuto { get; }
-
-            public bool HasAutoStar { get; }
+            return value;
         }
     }
-}
+}

+ 5 - 0
src/Avalonia.Controls/Platform/IWindowImpl.cs

@@ -16,6 +16,11 @@ namespace Avalonia.Platform
         /// </summary>
         WindowState WindowState { get; set; }
 
+        /// <summary>
+        /// Gets or sets a method called when the minimized/maximized state of the window changes.
+        /// </summary>
+        Action<WindowState> WindowStateChanged { get; set; }
+
         /// <summary>
         /// Sets the title of the window.
         /// </summary>

+ 67 - 75
src/Avalonia.Controls/Presenters/ContentPresenter.cs

@@ -35,6 +35,13 @@ namespace Avalonia.Controls.Presenters
         public static readonly StyledProperty<Thickness> BorderThicknessProperty =
             Border.BorderThicknessProperty.AddOwner<ContentPresenter>();
 
+        /// <summary>
+        /// Defines the <see cref="CornerRadius"/> property.
+        /// </summary>
+        public static readonly StyledProperty<CornerRadius> CornerRadiusProperty =
+            Border.CornerRadiusProperty.AddOwner<ContentPresenter>();
+
+
         /// <summary>
         /// Defines the <see cref="Child"/> property.
         /// </summary>
@@ -55,12 +62,6 @@ namespace Avalonia.Controls.Presenters
         public static readonly StyledProperty<IDataTemplate> ContentTemplateProperty =
             ContentControl.ContentTemplateProperty.AddOwner<ContentPresenter>();
 
-        /// <summary>
-        /// Defines the <see cref="CornerRadius"/> property.
-        /// </summary>
-        public static readonly StyledProperty<CornerRadius> CornerRadiusProperty =
-            Border.CornerRadiusProperty.AddOwner<ContentPresenter>();
-
         /// <summary>
         /// Defines the <see cref="HorizontalContentAlignment"/> property.
         /// </summary>
@@ -90,19 +91,12 @@ namespace Avalonia.Controls.Presenters
         static ContentPresenter()
         {
             AffectsRender(BackgroundProperty, BorderBrushProperty, BorderThicknessProperty, CornerRadiusProperty);
-            AffectsMeasure(BorderThicknessProperty);
+            AffectsMeasure(BorderThicknessProperty, PaddingProperty);
             ContentProperty.Changed.AddClassHandler<ContentPresenter>(x => x.ContentChanged);
             ContentTemplateProperty.Changed.AddClassHandler<ContentPresenter>(x => x.ContentChanged);
             TemplatedParentProperty.Changed.AddClassHandler<ContentPresenter>(x => x.TemplatedParentChanged);
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ContentPresenter"/> class.
-        /// </summary>
-        public ContentPresenter()
-        {
-        }
-
         /// <summary>
         /// Gets or sets a brush with which to paint the background.
         /// </summary>
@@ -130,6 +124,15 @@ namespace Avalonia.Controls.Presenters
             set { SetValue(BorderThicknessProperty, value); }
         }
 
+        /// <summary>
+        /// Gets or sets the radius of the border rounded corners.
+        /// </summary>
+        public CornerRadius CornerRadius
+        {
+            get { return GetValue(CornerRadiusProperty); }
+            set { SetValue(CornerRadiusProperty, value); }
+        }
+
         /// <summary>
         /// Gets the control displayed by the presenter.
         /// </summary>
@@ -159,16 +162,7 @@ namespace Avalonia.Controls.Presenters
         }
 
         /// <summary>
-        /// Gets or sets the radius of the border rounded corners.
-        /// </summary>
-        public CornerRadius CornerRadius
-        {
-            get { return GetValue(CornerRadiusProperty); }
-            set { SetValue(CornerRadiusProperty, value); }
-        }
-
-        /// <summary>
-        /// Gets or sets the horizontal alignment of the content within the control.
+        /// Gets or sets the horizontal alignment of the content within the border the control.
         /// </summary>
         public HorizontalAlignment HorizontalContentAlignment
         {
@@ -177,7 +171,7 @@ namespace Avalonia.Controls.Presenters
         }
 
         /// <summary>
-        /// Gets or sets the vertical alignment of the content within the control.
+        /// Gets or sets the vertical alignment of the content within the border of the control.
         /// </summary>
         public VerticalAlignment VerticalContentAlignment
         {
@@ -186,7 +180,7 @@ namespace Avalonia.Controls.Presenters
         }
 
         /// <summary>
-        /// Gets or sets the padding to place around the <see cref="Child"/> control.
+        /// Gets or sets the space between the border and the <see cref="Child"/> control.
         /// </summary>
         public Thickness Padding
         {
@@ -195,7 +189,7 @@ namespace Avalonia.Controls.Presenters
         }
 
         /// <inheritdoc/>
-        public override sealed void ApplyTemplate()
+        public sealed override void ApplyTemplate()
         {
             if (!_createdChild && ((ILogical)this).IsAttachedToLogicalTree)
             {
@@ -328,96 +322,68 @@ namespace Avalonia.Controls.Presenters
         /// <inheritdoc/>
         protected override Size MeasureOverride(Size availableSize)
         {
-            return Border.MeasureOverrideImpl(availableSize, Child, Padding, BorderThickness);
+            return LayoutHelper.MeasureChild(Child, availableSize, Padding, BorderThickness);
         }
 
         /// <inheritdoc/>
         protected override Size ArrangeOverride(Size finalSize)
         {
-            finalSize = ArrangeOverrideImpl(finalSize, new Vector());
-
             _borderRenderer.Update(finalSize, BorderThickness, CornerRadius);
 
-            return finalSize;
-        }
-
-        /// <summary>
-        /// Called when the <see cref="Content"/> property changes.
-        /// </summary>
-        /// <param name="e">The event args.</param>
-        private void ContentChanged(AvaloniaPropertyChangedEventArgs e)
-        {
-            _createdChild = false;
-
-            if (((ILogical)this).IsAttachedToLogicalTree)
-            {
-                UpdateChild();
-            }
-            else if (Child != null)
-            {
-                VisualChildren.Remove(Child);
-                LogicalChildren.Remove(Child);
-                Child = null;
-                _dataTemplate = null;
-            }
-
-            InvalidateMeasure();
+            return ArrangeOverrideImpl(finalSize, new Vector());
         }
 
         internal Size ArrangeOverrideImpl(Size finalSize, Vector offset)
         {
             if (Child == null) return finalSize;
 
-            var padding = Padding;
-            var borderThickness = BorderThickness;
+            var padding = Padding + BorderThickness;
             var horizontalContentAlignment = HorizontalContentAlignment;
             var verticalContentAlignment = VerticalContentAlignment;
             var useLayoutRounding = UseLayoutRounding;
-            var availableSizeMinusMargins = new Size(
-                Math.Max(0, finalSize.Width - padding.Left - padding.Right - borderThickness.Left - borderThickness.Right),
-                Math.Max(0, finalSize.Height - padding.Top - padding.Bottom - borderThickness.Top - borderThickness.Bottom));
-            var size = availableSizeMinusMargins;
+            var availableSize = finalSize;
+            var sizeForChild = availableSize;
             var scale = GetLayoutScale();
-            var originX = offset.X + padding.Left + borderThickness.Left;
-            var originY = offset.Y + padding.Top + borderThickness.Top;
+            var originX = offset.X;
+            var originY = offset.Y;
 
             if (horizontalContentAlignment != HorizontalAlignment.Stretch)
             {
-                size = size.WithWidth(Math.Min(size.Width, DesiredSize.Width - padding.Left - padding.Right));
+                sizeForChild = sizeForChild.WithWidth(Math.Min(sizeForChild.Width, DesiredSize.Width));
             }
 
             if (verticalContentAlignment != VerticalAlignment.Stretch)
             {
-                size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height - padding.Top - padding.Bottom));
+                sizeForChild = sizeForChild.WithHeight(Math.Min(sizeForChild.Height, DesiredSize.Height));
             }
 
             if (useLayoutRounding)
             {
-                size = new Size(
-                    Math.Ceiling(size.Width * scale) / scale,
-                    Math.Ceiling(size.Height * scale) / scale);
-                availableSizeMinusMargins = new Size(
-                    Math.Ceiling(availableSizeMinusMargins.Width * scale) / scale,
-                    Math.Ceiling(availableSizeMinusMargins.Height * scale) / scale);
+                sizeForChild = new Size(
+                    Math.Ceiling(sizeForChild.Width * scale) / scale,
+                    Math.Ceiling(sizeForChild.Height * scale) / scale);
+                availableSize = new Size(
+                    Math.Ceiling(availableSize.Width * scale) / scale,
+                    Math.Ceiling(availableSize.Height * scale) / scale);
             }
 
             switch (horizontalContentAlignment)
             {
                 case HorizontalAlignment.Center:
-                    originX += (availableSizeMinusMargins.Width - size.Width) / 2;
+                    originX += (availableSize.Width - sizeForChild.Width) / 2;
                     break;
                 case HorizontalAlignment.Right:
-                    originX += availableSizeMinusMargins.Width - size.Width;
+                    originX += availableSize.Width - sizeForChild.Width;
                     break;
             }
 
             switch (verticalContentAlignment)
             {
                 case VerticalAlignment.Center:
-                    originY += (availableSizeMinusMargins.Height - size.Height) / 2;
+                    originY += (availableSize.Height - sizeForChild.Height) / 2;
                     break;
                 case VerticalAlignment.Bottom:
-                    originY += availableSizeMinusMargins.Height - size.Height;
+                    originY += availableSize.Height - sizeForChild.Height;
                     break;
             }
 
@@ -427,11 +393,37 @@ namespace Avalonia.Controls.Presenters
                 originY = Math.Floor(originY * scale) / scale;
             }
 
-            Child.Arrange(new Rect(originX, originY, Math.Max(0, size.Width), Math.Max(0, size.Height)));
+            var boundsForChild =
+                new Rect(originX, originY, sizeForChild.Width, sizeForChild.Height).Deflate(padding);
+
+            Child.Arrange(boundsForChild);
 
             return finalSize;
         }
 
+        /// <summary>
+        /// Called when the <see cref="Content"/> property changes.
+        /// </summary>
+        /// <param name="e">The event args.</param>
+        private void ContentChanged(AvaloniaPropertyChangedEventArgs e)
+        {
+            _createdChild = false;
+
+            if (((ILogical)this).IsAttachedToLogicalTree)
+            {
+                UpdateChild();
+            }
+            else if (Child != null)
+            {
+                VisualChildren.Remove(Child);
+                LogicalChildren.Remove(Child);
+                Child = null;
+                _dataTemplate = null;
+            }
+
+            InvalidateMeasure();
+        }
+
         private double GetLayoutScale()
         {
             var result = (VisualRoot as ILayoutRoot)?.LayoutScaling ?? 1.0;

+ 27 - 2
src/Avalonia.Controls/Presenters/TextPresenter.cs

@@ -17,6 +17,9 @@ namespace Avalonia.Controls.Presenters
                 o => o.CaretIndex,
                 (o, v) => o.CaretIndex = v);
 
+        public static readonly StyledProperty<char> PasswordCharProperty =
+            AvaloniaProperty.Register<TextPresenter, char>(nameof(PasswordChar));
+
         public static readonly DirectProperty<TextPresenter, int> SelectionStartProperty =
             TextBox.SelectionStartProperty.AddOwner<TextPresenter>(
                 o => o.SelectionStart,
@@ -63,6 +66,12 @@ namespace Avalonia.Controls.Presenters
             }
         }
 
+        public char PasswordChar
+        {
+            get => GetValue(PasswordCharProperty);
+            set => SetValue(PasswordCharProperty, value);
+        }
+
         public int SelectionStart
         {
             get
@@ -202,9 +211,25 @@ namespace Avalonia.Controls.Presenters
             }
         }
 
-        protected override FormattedText CreateFormattedText(Size constraint)
+        /// <summary>
+        /// Creates the <see cref="FormattedText"/> used to render the text.
+        /// </summary>
+        /// <param name="constraint">The constraint of the text.</param>
+        /// <param name="text">The text to generated the <see cref="FormattedText"/> for.</param>
+        /// <returns>A <see cref="FormattedText"/> object.</returns>
+        protected override FormattedText CreateFormattedText(Size constraint, string text)
         {
-            var result = base.CreateFormattedText(constraint);
+            FormattedText result = null;
+
+            if (PasswordChar != default(char))
+            {
+                result = base.CreateFormattedText(constraint, new string(PasswordChar, text?.Length ?? 0));
+            }
+            else
+            {
+                result = base.CreateFormattedText(constraint, text);
+            }
+
             var selectionStart = SelectionStart;
             var selectionEnd = SelectionEnd;
             var start = Math.Min(selectionStart, selectionEnd);

+ 3 - 14
src/Avalonia.Controls/Primitives/AccessText.cs

@@ -78,21 +78,10 @@ namespace Avalonia.Controls.Primitives
             }
         }
 
-        /// <summary>
-        /// Creates the <see cref="FormattedText"/> used to render the text.
-        /// </summary>
-        /// <param name="constraint">The constraint of the text.</param>
-        /// <returns>A <see cref="FormattedText"/> object.</returns>
-        protected override FormattedText CreateFormattedText(Size constraint)
+        /// <inheritdoc/>
+        protected override FormattedText CreateFormattedText(Size constraint, string text)
         {
-            return new FormattedText
-            {
-                Constraint = constraint,
-                Typeface = new Typeface(FontFamily, FontSize, FontStyle, FontWeight),
-                Text = StripAccessKey(Text),
-                TextAlignment = TextAlignment,
-                Wrapping = TextWrapping,
-            };
+            return base.CreateFormattedText(constraint, StripAccessKey(text));
         }
 
         /// <summary>

+ 0 - 1
src/Avalonia.Controls/Properties/AssemblyInfo.cs

@@ -5,7 +5,6 @@ using System.Reflection;
 using System.Runtime.CompilerServices;
 using Avalonia.Metadata;
 
-[assembly: AssemblyTitle("Avalonia.Controls")]
 [assembly: InternalsVisibleTo("Avalonia.Controls.UnitTests")]
 [assembly: InternalsVisibleTo("Avalonia.DesignerSupport")]
 

+ 6 - 3
src/Avalonia.Controls/TextBlock.cs

@@ -111,6 +111,8 @@ namespace Avalonia.Controls
         /// </summary>
         public TextBlock()
         {
+            _text = string.Empty;
+
             Observable.Merge(
                 this.GetObservable(TextProperty).Select(_ => Unit.Default),
                 this.GetObservable(TextAlignmentProperty).Select(_ => Unit.Default),
@@ -197,7 +199,7 @@ namespace Avalonia.Controls
             {
                 if (_formattedText == null)
                 {
-                    _formattedText = CreateFormattedText(_constraint);
+                    _formattedText = CreateFormattedText(_constraint, Text);
                 }
 
                 return _formattedText;
@@ -348,14 +350,15 @@ namespace Avalonia.Controls
         /// Creates the <see cref="FormattedText"/> used to render the text.
         /// </summary>
         /// <param name="constraint">The constraint of the text.</param>
+        /// <param name="text">The text to format.</param>
         /// <returns>A <see cref="FormattedText"/> object.</returns>
-        protected virtual FormattedText CreateFormattedText(Size constraint)
+        protected virtual FormattedText CreateFormattedText(Size constraint, string text)
         {
             return new FormattedText
             {
                 Constraint = constraint,
                 Typeface = new Typeface(FontFamily, FontSize, FontStyle, FontWeight),
-                Text = Text ?? string.Empty,
+                Text = text ?? string.Empty,
                 TextAlignment = TextAlignment,
                 Wrapping = TextWrapping,
             };

+ 26 - 9
src/Avalonia.Controls/TextBox.cs

@@ -30,10 +30,13 @@ namespace Avalonia.Controls
                 nameof(CaretIndex),
                 o => o.CaretIndex,
                 (o, v) => o.CaretIndex = v);
-        
+
         public static readonly StyledProperty<bool> IsReadOnlyProperty =
             AvaloniaProperty.Register<TextBox, bool>(nameof(IsReadOnly));
 
+        public static readonly StyledProperty<char> PasswordCharProperty =
+            AvaloniaProperty.Register<TextBox, char>(nameof(PasswordChar));
+
         public static readonly DirectProperty<TextBox, int> SelectionStartProperty =
             AvaloniaProperty.RegisterDirect<TextBox, int>(
                 nameof(SelectionStart),
@@ -87,7 +90,7 @@ namespace Avalonia.Controls
         private UndoRedoHelper<UndoRedoState> _undoRedoHelper;
         private bool _isUndoingRedoing;
         private bool _ignoreTextChanges;
-        private static readonly string[] invalidCharacters = new String[1]{"\u007f"};
+        private static readonly string[] invalidCharacters = new String[1] { "\u007f" };
 
         static TextBox()
         {
@@ -116,7 +119,7 @@ namespace Avalonia.Controls
                 ScrollViewer.HorizontalScrollBarVisibilityProperty,
                 horizontalScrollBarVisibility,
                 BindingPriority.Style);
-            _undoRedoHelper = new UndoRedoHelper<UndoRedoState>(this);
+            _undoRedoHelper = new UndoRedoHelper<UndoRedoState>(this);            
         }
 
         public bool AcceptsReturn
@@ -147,13 +150,19 @@ namespace Avalonia.Controls
                     _undoRedoHelper.UpdateLastState();
             }
         }
-        
+
         public bool IsReadOnly
         {
             get { return GetValue(IsReadOnlyProperty); }
             set { SetValue(IsReadOnlyProperty, value); }
         }
 
+        public char PasswordChar
+        {
+            get => GetValue(PasswordCharProperty);
+            set => SetValue(PasswordCharProperty, value);
+        }
+
         public int SelectionStart
         {
             get
@@ -237,7 +246,7 @@ namespace Avalonia.Controls
             _presenter = e.NameScope.Get<TextPresenter>("PART_TextPresenter");
             _presenter.Cursor = new Cursor(StandardCursorType.Ibeam);
 
-            if(IsFocused)
+            if (IsFocused)
             {
                 _presenter.ShowCaret();
             }
@@ -349,7 +358,10 @@ namespace Avalonia.Controls
                 case Key.C:
                     if (modifiers == InputModifiers.Control)
                     {
-                        Copy();
+                        if (!IsPasswordBox)
+                        {
+                            Copy();
+                        }
                         handled = true;
                     }
                     break;
@@ -357,8 +369,11 @@ namespace Avalonia.Controls
                 case Key.X:
                     if (modifiers == InputModifiers.Control)
                     {
-                        Copy();
-                        DeleteSelection();
+                        if (!IsPasswordBox)
+                        {
+                            Copy();
+                            DeleteSelection();
+                        }
                         handled = true;
                     }
                     break;
@@ -578,7 +593,7 @@ namespace Avalonia.Controls
                 DataValidationErrors.SetError(this, status.Error);
             }
         }
-        
+
         private int CoerceCaretIndex(int value) => CoerceCaretIndex(value, Text?.Length ?? 0);
 
         private int CoerceCaretIndex(int value, int length)
@@ -856,6 +871,8 @@ namespace Avalonia.Controls
             SelectionEnd = CaretIndex;
         }
 
+        private bool IsPasswordBox => PasswordChar != default(char);
+
         UndoRedoState UndoRedoHelper<UndoRedoState>.IUndoRedoHost.UndoRedoState
         {
             get { return new UndoRedoState(Text, CaretIndex); }

+ 4 - 4
src/Avalonia.Controls/ToolTip.cs

@@ -34,25 +34,25 @@ namespace Avalonia.Controls
         /// Defines the ToolTip.Placement property.
         /// </summary>
         public static readonly AttachedProperty<PlacementMode> PlacementProperty =
-            AvaloniaProperty.RegisterAttached<Popup, Control, PlacementMode>("Placement", defaultValue: PlacementMode.Pointer);
+            AvaloniaProperty.RegisterAttached<ToolTip, Control, PlacementMode>("Placement", defaultValue: PlacementMode.Pointer);
 
         /// <summary>
         /// Defines the ToolTip.HorizontalOffset property.
         /// </summary>
         public static readonly AttachedProperty<double> HorizontalOffsetProperty =
-            AvaloniaProperty.RegisterAttached<Popup, Control, double>("HorizontalOffset");
+            AvaloniaProperty.RegisterAttached<ToolTip, Control, double>("HorizontalOffset");
 
         /// <summary>
         /// Defines the ToolTip.VerticalOffset property.
         /// </summary>
         public static readonly AttachedProperty<double> VerticalOffsetProperty =
-            AvaloniaProperty.RegisterAttached<Popup, Control, double>("VerticalOffset", 20);
+            AvaloniaProperty.RegisterAttached<ToolTip, Control, double>("VerticalOffset", 20);
 
         /// <summary>
         /// Defines the ToolTip.ShowDelay property.
         /// </summary>
         public static readonly AttachedProperty<int> ShowDelayProperty =
-            AvaloniaProperty.RegisterAttached<Popup, Control, int>("ShowDelay", 400);
+            AvaloniaProperty.RegisterAttached<ToolTip, Control, int>("ShowDelay", 400);
 
         /// <summary>
         /// Stores the curernt <see cref="ToolTip"/> instance in the control.

+ 117 - 137
src/Avalonia.Controls/Utils/BorderRenderHelper.cs

@@ -26,17 +26,17 @@ namespace Avalonia.Controls.Utils
 
                 var boundRect = new Rect(finalSize);
                 var innerRect = boundRect.Deflate(borderThickness);
-                var innerCoordinates = new BorderCoordinates(cornerRadius, borderThickness, false);
-
+                BorderGeometryKeypoints backgroundKeypoints = null;
                 StreamGeometry backgroundGeometry = null;
 
                 if (innerRect.Width != 0 && innerRect.Height != 0)
                 {
                     backgroundGeometry = new StreamGeometry();
+                    backgroundKeypoints = new BorderGeometryKeypoints(innerRect, borderThickness, cornerRadius, true);
 
                     using (var ctx = backgroundGeometry.Open())
                     {
-                        CreateGeometry(ctx, innerRect, innerCoordinates);
+                        CreateGeometry(ctx, innerRect, backgroundKeypoints);
                     }
 
                     _backgroundGeometryCache = backgroundGeometry;
@@ -48,16 +48,16 @@ namespace Avalonia.Controls.Utils
 
                 if (boundRect.Width != 0 && innerRect.Height != 0)
                 {
-                    var outerCoordinates = new BorderCoordinates(cornerRadius, borderThickness, true);
+                    var borderGeometryKeypoints = new BorderGeometryKeypoints(boundRect, borderThickness, cornerRadius, false);
                     var borderGeometry = new StreamGeometry();
 
                     using (var ctx = borderGeometry.Open())
                     {
-                        CreateGeometry(ctx, boundRect, outerCoordinates);
+                        CreateGeometry(ctx, boundRect, borderGeometryKeypoints);
 
                         if (backgroundGeometry != null)
                         {
-                            CreateGeometry(ctx, innerRect, innerCoordinates);
+                            CreateGeometry(ctx, innerRect, backgroundKeypoints);
                         }
                     }
 
@@ -104,176 +104,156 @@ namespace Avalonia.Controls.Utils
             }
         }
 
-        private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, BorderCoordinates borderCoordinates)
-        {
-            var topLeft = new Point(borderCoordinates.LeftTop, 0);
-            var topRight = new Point(boundRect.Width - borderCoordinates.RightTop, 0);
-            var rightTop = new Point(boundRect.Width, borderCoordinates.TopRight);
-            var rightBottom = new Point(boundRect.Width, boundRect.Height - borderCoordinates.BottomRight);
-            var bottomRight = new Point(boundRect.Width - borderCoordinates.RightBottom, boundRect.Height);
-            var bottomLeft = new Point(borderCoordinates.LeftBottom, boundRect.Height);
-            var leftBottom = new Point(0, boundRect.Height - borderCoordinates.BottomLeft);
-            var leftTop = new Point(0, borderCoordinates.TopLeft);
+        private class BorderGeometryKeypoints
+        {           
+            internal BorderGeometryKeypoints(Rect boundRect, Thickness borderThickness, CornerRadius cornerRadius, bool inner)
+            {
+                var left = 0.5 * borderThickness.Left;
+                var top = 0.5 * borderThickness.Top;
+                var right = 0.5 * borderThickness.Right;
+                var bottom = 0.5 * borderThickness.Bottom;
 
+                double leftTopY;
+                double topLeftX;
+                double topRightX;
+                double rightTopY;
+                double rightBottomY;
+                double bottomRightX;
+                double bottomLeftX;
+                double leftBottomY;
 
-            if (topLeft.X > topRight.X)
-            {
-                var scaledX = borderCoordinates.LeftTop / (borderCoordinates.LeftTop + borderCoordinates.RightTop) * boundRect.Width;
-                topLeft = new Point(scaledX, topLeft.Y);
-                topRight = new Point(scaledX, topRight.Y);
-            }
+                if (inner)
+                {
+                    leftTopY = Math.Max(0, cornerRadius.TopLeft - top) + boundRect.TopLeft.Y;
+                    topLeftX = Math.Max(0, cornerRadius.TopLeft - left) + boundRect.TopLeft.X;
+                    topRightX = boundRect.Width - Math.Max(0, cornerRadius.TopRight - top) + boundRect.TopLeft.X;
+                    rightTopY = Math.Max(0, cornerRadius.TopRight - right) + boundRect.TopLeft.Y;
+                    rightBottomY = boundRect.Height - Math.Max(0, cornerRadius.BottomRight - bottom) + boundRect.TopLeft.Y;
+                    bottomRightX = boundRect.Width - Math.Max(0, cornerRadius.BottomRight - right) + boundRect.TopLeft.X;
+                    bottomLeftX = Math.Max(0, cornerRadius.BottomLeft - left) + boundRect.TopLeft.X;
+                    leftBottomY = boundRect.Height - Math.Max(0, cornerRadius.BottomLeft - bottom) + boundRect.TopLeft.Y;
+                }
+                else
+                {
+                   
+                    leftTopY = cornerRadius.TopLeft + top + boundRect.TopLeft.Y;
+                    topLeftX = cornerRadius.TopLeft + left + boundRect.TopLeft.X;                   
+                    topRightX = boundRect.Width - (cornerRadius.TopRight + right) + boundRect.TopLeft.X;
+                    rightTopY = cornerRadius.TopRight + top + boundRect.TopLeft.Y;                                   
+                    rightBottomY = boundRect.Height - (cornerRadius.BottomRight + bottom) + boundRect.TopLeft.Y;
+                    bottomRightX = boundRect.Width - (cornerRadius.BottomRight + right) + boundRect.TopLeft.X;                
+                    bottomLeftX = cornerRadius.BottomLeft + left + boundRect.TopLeft.X;               
+                    leftBottomY = boundRect.Height - (cornerRadius.BottomLeft + bottom) + boundRect.TopLeft.Y;
+                }              
+
+                var leftTopX = boundRect.TopLeft.X;               
+                var topLeftY = boundRect.TopLeft.Y;              
+                var topRightY = boundRect.TopLeft.Y;
+                var rightTopX = boundRect.Width + boundRect.TopLeft.X;              
+                var rightBottomX = boundRect.Width + boundRect.TopLeft.X;                             
+                var bottomRightY = boundRect.Height + boundRect.TopLeft.Y;            
+                var bottomLeftY = boundRect.Height + boundRect.TopLeft.Y;
+                var leftBottomX = boundRect.TopLeft.X;           
+
+                LeftTop = new Point(leftTopX, leftTopY);
+                TopLeft = new Point(topLeftX, topLeftY);
+                TopRight = new Point(topRightX, topRightY);
+                RightTop = new Point(rightTopX, rightTopY);
+                RightBottom = new Point(rightBottomX, rightBottomY);
+                BottomRight = new Point(bottomRightX, bottomRightY);
+                BottomLeft = new Point(bottomLeftX, bottomLeftY);
+                LeftBottom = new Point(leftBottomX, leftBottomY);
+
+                //Fix overlap
+                if (TopLeft.X > TopRight.X)
+                {
+                    var scaledX = topLeftX / (topLeftX + topRightX) * boundRect.Width;
+                    TopLeft = new Point(scaledX, TopLeft.Y);
+                    TopRight = new Point(scaledX, TopRight.Y);
+                }
 
-            if (rightTop.Y > rightBottom.Y)
-            {
-                var scaledY = borderCoordinates.TopRight / (borderCoordinates.TopRight + borderCoordinates.BottomRight) * boundRect.Height;
-                rightTop = new Point(rightTop.X, scaledY);
-                rightBottom = new Point(rightBottom.X, scaledY);
-            }
+                if (RightTop.Y > RightBottom.Y)
+                {
+                    var scaledY = rightBottomY / (rightTopY + rightBottomY) * boundRect.Height;
+                    RightTop = new Point(RightTop.X, scaledY);
+                    RightBottom = new Point(RightBottom.X, scaledY);
+                }
 
-            if (bottomRight.X < bottomLeft.X)
-            {
-                var scaledX = borderCoordinates.LeftBottom / (borderCoordinates.LeftBottom + borderCoordinates.RightBottom) * boundRect.Width;
-                bottomRight = new Point(scaledX, bottomRight.Y);
-                bottomLeft = new Point(scaledX, bottomLeft.Y);
-            }
+                if (BottomRight.X < BottomLeft.X)
+                {
+                    var scaledX = bottomLeftX / (bottomLeftX + bottomRightX) * boundRect.Width;
+                    BottomRight = new Point(scaledX, BottomRight.Y);
+                    BottomLeft = new Point(scaledX, BottomLeft.Y);
+                }
 
-            if (leftBottom.Y < leftTop.Y)
-            {
-                var scaledY = borderCoordinates.TopLeft / (borderCoordinates.TopLeft + borderCoordinates.BottomLeft) * boundRect.Height;
-                leftBottom = new Point(leftBottom.X, scaledY);
-                leftTop = new Point(leftTop.X, scaledY);
+                if (LeftBottom.Y < LeftTop.Y)
+                {
+                    var scaledY = leftTopY / (leftTopY + leftBottomY) * boundRect.Height;
+                    LeftBottom = new Point(LeftBottom.X, scaledY);
+                    LeftTop = new Point(LeftTop.X, scaledY);
+                }
             }
 
-            var offset = new Vector(boundRect.TopLeft.X, boundRect.TopLeft.Y);
-            topLeft += offset;
-            topRight += offset;
-            rightTop += offset;
-            rightBottom += offset;
-            bottomRight += offset;
-            bottomLeft += offset;
-            leftBottom += offset;
-            leftTop += offset;
+            internal Point LeftTop { get; private set; }
+            internal Point TopLeft { get; private set; }
+            internal Point TopRight { get; private set; }
+            internal Point RightTop { get; private set; }
+            internal Point RightBottom { get; private set; }
+            internal Point BottomRight { get; private set; }
+            internal Point BottomLeft { get; private set; }
+            internal Point LeftBottom { get; private set; }
+        }
 
-            context.BeginFigure(topLeft, true);
+        private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, BorderGeometryKeypoints keypoints)
+        {
+            context.BeginFigure(keypoints.TopLeft, true);
 
             //Top
-            context.LineTo(topRight);
+            context.LineTo(keypoints.TopRight);
 
             //TopRight corner
-            var radiusX = boundRect.TopRight.X - topRight.X;
-            var radiusY = rightTop.Y - boundRect.TopRight.Y;
+            var radiusX = boundRect.TopRight.X - keypoints.TopRight.X;
+            var radiusY = keypoints.RightTop.Y - boundRect.TopRight.Y;
             if (radiusX != 0 || radiusY != 0)
             {
-                context.ArcTo(rightTop, new Size(radiusY, radiusY), 0, false, SweepDirection.Clockwise);
+                context.ArcTo(keypoints.RightTop, new Size(radiusY, radiusY), 0, false, SweepDirection.Clockwise);
             }
 
             //Right
-            context.LineTo(rightBottom);
+            context.LineTo(keypoints.RightBottom);
 
             //BottomRight corner
-            radiusX = boundRect.BottomRight.X - bottomRight.X;
-            radiusY = boundRect.BottomRight.Y - rightBottom.Y;
+            radiusX = boundRect.BottomRight.X - keypoints.BottomRight.X;
+            radiusY = boundRect.BottomRight.Y - keypoints.RightBottom.Y;
             if (radiusX != 0 || radiusY != 0)
             {
-                context.ArcTo(bottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
+                context.ArcTo(keypoints.BottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
             }
 
             //Bottom
-            context.LineTo(bottomLeft);
+            context.LineTo(keypoints.BottomLeft);
 
             //BottomLeft corner
-            radiusX = bottomLeft.X - boundRect.BottomLeft.X;
-            radiusY = boundRect.BottomLeft.Y - leftBottom.Y;
+            radiusX = keypoints.BottomLeft.X - boundRect.BottomLeft.X;
+            radiusY = boundRect.BottomLeft.Y - keypoints.LeftBottom.Y;
             if (radiusX != 0 || radiusY != 0)
             {
-                context.ArcTo(leftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
+                context.ArcTo(keypoints.LeftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
             }
 
             //Left
-            context.LineTo(leftTop);
+            context.LineTo(keypoints.LeftTop);
 
             //TopLeft corner
-            radiusX = topLeft.X - boundRect.TopLeft.X;
-            radiusY = leftTop.Y - boundRect.TopLeft.Y;
+            radiusX = keypoints.TopLeft.X - boundRect.TopLeft.X;
+            radiusY = keypoints.LeftTop.Y - boundRect.TopLeft.Y;
 
             if (radiusX != 0 || radiusY != 0)
             {
-                context.ArcTo(topLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
+                context.ArcTo(keypoints.TopLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise);
             }
 
             context.EndFigure(true);
         }
-
-        private struct BorderCoordinates
-        {
-            internal BorderCoordinates(CornerRadius cornerRadius, Thickness borderThickness, bool isOuter)
-            {
-                var left = 0.5 * borderThickness.Left;
-                var top = 0.5 * borderThickness.Top;
-                var right = 0.5 * borderThickness.Right;
-                var bottom = 0.5 * borderThickness.Bottom;
-
-                if (isOuter)
-                {
-                    if (cornerRadius.TopLeft == 0)
-                    {
-                        LeftTop = TopLeft = 0.0;
-                    }
-                    else
-                    {
-                        LeftTop = cornerRadius.TopLeft + left;
-                        TopLeft = cornerRadius.TopLeft + top;
-                    }
-                    if (cornerRadius.TopRight == 0)
-                    {
-                        TopRight = RightTop = 0;
-                    }
-                    else
-                    {
-                        TopRight = cornerRadius.TopRight + top;
-                        RightTop = cornerRadius.TopRight + right;
-                    }
-                    if (cornerRadius.BottomRight == 0)
-                    {
-                        RightBottom = BottomRight = 0;
-                    }
-                    else
-                    {
-                        RightBottom = cornerRadius.BottomRight + right;
-                        BottomRight = cornerRadius.BottomRight + bottom;
-                    }
-                    if (cornerRadius.BottomLeft == 0)
-                    {
-                        BottomLeft = LeftBottom = 0;
-                    }
-                    else
-                    {
-                        BottomLeft = cornerRadius.BottomLeft + bottom;
-                        LeftBottom = cornerRadius.BottomLeft + left;
-                    }
-                }
-                else
-                {
-                    LeftTop = Math.Max(0, cornerRadius.TopLeft - left);
-                    TopLeft = Math.Max(0, cornerRadius.TopLeft - top);
-                    TopRight = Math.Max(0, cornerRadius.TopRight - top);
-                    RightTop = Math.Max(0, cornerRadius.TopRight - right);
-                    RightBottom = Math.Max(0, cornerRadius.BottomRight - right);
-                    BottomRight = Math.Max(0, cornerRadius.BottomRight - bottom);
-                    BottomLeft = Math.Max(0, cornerRadius.BottomLeft - bottom);
-                    LeftBottom = Math.Max(0, cornerRadius.BottomLeft - left);
-                }
-            }
-
-            internal readonly double LeftTop;
-            internal readonly double TopLeft;
-            internal readonly double TopRight;
-            internal readonly double RightTop;
-            internal readonly double RightBottom;
-            internal readonly double BottomRight;
-            internal readonly double BottomLeft;
-            internal readonly double LeftBottom;
-        }
-
     }
 }

+ 700 - 0
src/Avalonia.Controls/Utils/GridLayout.cs

@@ -0,0 +1,700 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using Avalonia.Layout;
+using JetBrains.Annotations;
+
+namespace Avalonia.Controls.Utils
+{
+    /// <summary>
+    /// Contains algorithms that can help to measure and arrange a Grid.
+    /// </summary>
+    internal class GridLayout
+    {
+        /// <summary>
+        /// Initialize a new <see cref="GridLayout"/> instance from the column definitions.
+        /// The instance doesn't care about whether the definitions are rows or columns.
+        /// It will not calculate the column or row differently.
+        /// </summary>
+        internal GridLayout([NotNull] ColumnDefinitions columns)
+        {
+            if (columns == null) throw new ArgumentNullException(nameof(columns));
+            _conventions = columns.Count == 0
+                ? new List<LengthConvention> { new LengthConvention() }
+                : columns.Select(x => new LengthConvention(x.Width, x.MinWidth, x.MaxWidth)).ToList();
+        }
+
+        /// <summary>
+        /// Initialize a new <see cref="GridLayout"/> instance from the row definitions.
+        /// The instance doesn't care about whether the definitions are rows or columns.
+        /// It will not calculate the column or row differently.
+        /// </summary>
+        internal GridLayout([NotNull] RowDefinitions rows)
+        {
+            if (rows == null) throw new ArgumentNullException(nameof(rows));
+            _conventions = rows.Count == 0
+                ? new List<LengthConvention> { new LengthConvention() }
+                : rows.Select(x => new LengthConvention(x.Height, x.MinHeight, x.MaxHeight)).ToList();
+        }
+
+        /// <summary>
+        /// Gets the layout tolerance. If any length offset is less than this value, we will treat them the same.
+        /// </summary>
+        private const double LayoutTolerance = 1.0 / 256.0;
+
+        /// <summary>
+        /// Gets all the length conventions that come from column/row definitions.
+        /// These conventions provide cell limitations, such as the expected pixel length, the min/max pixel length and the * count.
+        /// </summary>
+        [NotNull]
+        private readonly List<LengthConvention> _conventions;
+
+        /// <summary>
+        /// Gets all the length conventions that come from the grid children.
+        /// </summary>
+        [NotNull]
+        private readonly List<AdditionalLengthConvention> _additionalConventions =
+            new List<AdditionalLengthConvention>();
+
+        /// <summary>
+        /// Appending these elements into the convention list helps lay them out according to their desired sizes.
+        /// <para/>
+        /// Some elements are not only in a single grid cell, they have one or more column/row spans,
+        /// and these elements may affect the grid layout especially the measuring procedure.<para/>
+        /// Append these elements into the convention list can help to layout them correctly through
+        /// their desired size. Only a small subset of children need to be measured before layout starts
+        /// and they will be called via the<paramref name="getDesiredLength"/> callback.
+        /// </summary>
+        /// <typeparam name="T">The grid children type.</typeparam>
+        /// <param name="source">
+        /// Contains the safe column/row index and its span.
+        /// Notice that we will not verify whether the range is in the column/row count,
+        /// so you should get the safe column/row info first.
+        /// </param>
+        /// <param name="getDesiredLength">
+        /// This callback will be called if the <see cref="GridLayout"/> thinks that a child should be
+        /// measured first. Usually, these are the children that have the * or Auto length.
+        /// </param>
+        internal void AppendMeasureConventions<T>([NotNull] IDictionary<T, (int index, int span)> source,
+            [NotNull] Func<T, double> getDesiredLength)
+        {
+            if (source == null) throw new ArgumentNullException(nameof(source));
+            if (getDesiredLength == null) throw new ArgumentNullException(nameof(getDesiredLength));
+
+            // M1/7. Find all the Auto and * length columns/rows. (M1/7 means the 1st procedure of measurement.)
+            // Only these columns/rows' layout can be affected by the child desired size.
+            // 
+            // Find all columns/rows that have Auto or * length. We'll measure the children in advance.
+            // Only these kind of columns/rows will affect the Grid layout.
+            // Please note:
+            // - If the column / row has Auto length, the Grid.DesiredSize and the column width
+            //   will be affected by the child's desired size.
+            // - If the column / row has* length, the Grid.DesiredSize will be affected by the
+            //   child's desired size but the column width not.
+
+            //               +-----------------------------------------------------------+
+            //               |  *  |  A  |  *  |  P  |  A  |  *  |  P  |     *     |  *  |
+            //               +-----------------------------------------------------------+
+            // _conventions: | min | max |     |           | min |     |  min max  | max |
+            // _additionalC:                   |<-   desired   ->|     |< desired >|
+            // _additionalC:       |< desired >|           |<-        desired          ->|
+
+            // 寻找所有行列范围中包含 Auto 和 * 的元素,使用全部可用尺寸提前测量。
+            // 因为只有这部分元素的布局才会被 Grid 的子元素尺寸影响。
+            // 请注意:
+            // - Auto 长度的行列必定会受到子元素布局影响,会影响到行列的布局长度和 Grid 本身的 DesiredSize;
+            // - 而对于 * 长度,只有 Grid.DesiredSize 会受到子元素布局影响,而行列长度不会受影响。
+
+            // Find all the Auto and * length columns/rows.
+            var found = new Dictionary<T, (int index, int span)>();
+            for (var i = 0; i < _conventions.Count; i++)
+            {
+                var index = i;
+                var convention = _conventions[index];
+                if (convention.Length.IsAuto || convention.Length.IsStar)
+                {
+                    foreach (var pair in source.Where(x =>
+                        x.Value.index <= index && index < x.Value.index + x.Value.span))
+                    {
+                        found[pair.Key] = pair.Value;
+                    }
+                }
+            }
+
+            // Append these layout into the additional convention list.
+            foreach (var pair in found)
+            {
+                var t = pair.Key;
+                var (index, span) = pair.Value;
+                var desiredLength = getDesiredLength(t);
+                if (Math.Abs(desiredLength) > LayoutTolerance)
+                {
+                    _additionalConventions.Add(new AdditionalLengthConvention(index, span, desiredLength));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Run measure procedure according to the <paramref name="containerLength"/> and gets the <see cref="MeasureResult"/>.
+        /// </summary>
+        /// <param name="containerLength">
+        /// The container length. Usually, it is the constraint of the <see cref="Layoutable.MeasureOverride"/> method.
+        /// </param>
+        /// <returns>
+        /// The measured result that containing the desired size and all the column/row lengths.
+        /// </returns>
+        [NotNull, Pure]
+        internal MeasureResult Measure(double containerLength)
+        {
+            // Prepare all the variables that this method needs to use.
+            var conventions = _conventions.Select(x => x.Clone()).ToList();
+            var starCount = conventions.Where(x => x.Length.IsStar).Sum(x => x.Length.Value);
+            var aggregatedLength = 0.0;
+            double starUnitLength;
+
+            // M2/7. Aggregate all the pixel lengths. Then we can get the remaining length by `containerLength - aggregatedLength`.
+            // We mark the aggregated length as "fix" because we can completely determine their values. Same as below.
+            //
+            // +-----------------------------------------------------------+
+            // |  *  |  A  |  *  |  P  |  A  |  *  |  P  |     *     |  *  |
+            // +-----------------------------------------------------------+
+            //                   |#fix#|           |#fix#|
+            //
+            // 将全部的固定像素长度的行列长度累加。这样,containerLength - aggregatedLength 便能得到剩余长度。
+            // 我们会将所有能够确定下长度的行列标记为 fix。下同。
+            // 请注意:
+            // - 我们并没有直接从 containerLength 一直减下去,而是使用 aggregatedLength 进行累加,是因为无穷大相减得到的是 NaN,不利于后续计算。
+
+            aggregatedLength += conventions.Where(x => x.Length.IsAbsolute).Sum(x => x.Length.Value);
+
+            // M3/7. Fix all the * lengths that have reached the minimum.
+            //
+            // +-----------------------------------------------------------+
+            // |  *  |  A  |  *  |  P  |  A  |  *  |  P  |     *     |  *  |
+            // +-----------------------------------------------------------+
+            // | min | max |     |           | min |     |  min max  | max |
+            //                   | fix |     |#fix#| fix |
+
+            var shouldTestStarMin = true;
+            while (shouldTestStarMin)
+            {
+                // Calculate the unit * length to estimate the length of each column/row that has * length.
+                // Under this estimated length, check if there is a minimum value that has a length less than its constraint.
+                // If there is such a *, then fix the size of this cell, and then loop it again until there is no * that can be constrained by the minimum value.
+                //
+                // 计算单位 * 的长度,以便预估出每一个 * 行列的长度。
+                // 在此预估的长度下,从前往后寻找是否存在某个 * 长度已经小于其约束的最小值。
+                // 如果发现存在这样的 *,那么将此单元格的尺寸固定下来(Fix),然后循环重来,直至再也没有能被最小值约束的 *。
+                var @fixed = false;
+                starUnitLength = (containerLength - aggregatedLength) / starCount;
+                foreach (var convention in conventions.Where(x => x.Length.IsStar))
+                {
+                    var (star, min) = (convention.Length.Value, convention.MinLength);
+                    var starLength = star * starUnitLength;
+                    if (starLength < min)
+                    {
+                        convention.Fix(min);
+                        starLength = min;
+                        aggregatedLength += starLength;
+                        starCount -= star;
+                        @fixed = true;
+                        break;
+                    }
+                }
+
+                shouldTestStarMin = @fixed;
+            }
+
+            // M4/7. Determine the absolute pixel size of all columns/rows that have an Auto length.
+            //
+            // +-----------------------------------------------------------+
+            // |  *  |  A  |  *  |  P  |  A  |  *  |  P  |     *     |  *  |
+            // +-----------------------------------------------------------+
+            // | min | max |     |           | min |     |  min max  | max |
+            //       |#fix#|     | fix |#fix#| fix | fix |
+
+            var shouldTestAuto = true;
+            while (shouldTestAuto)
+            {
+                var @fixed = false;
+                starUnitLength = (containerLength - aggregatedLength) / starCount;
+                for (var i = 0; i < conventions.Count; i++)
+                {
+                    var convention = conventions[i];
+                    if (!convention.Length.IsAuto)
+                    {
+                        continue;
+                    }
+
+                    var more = ApplyAdditionalConventionsForAuto(conventions, i, starUnitLength);
+                    convention.Fix(more);
+                    aggregatedLength += more;
+                    @fixed = true;
+                    break;
+                }
+
+                shouldTestAuto = @fixed;
+            }
+
+            // M5/7. Expand the stars according to the additional conventions (usually the child desired length).
+            // We can't fix this kind of length, so we just mark them as desired (des).
+            //
+            // +-----------------------------------------------------------+
+            // |  *  |  A  |  *  |  P  |  A  |  *  |  P  |     *     |  *  |
+            // +-----------------------------------------------------------+
+            // | min | max |     |           | min |     |  min max  | max |
+            // |#des#| fix |#des#| fix | fix | fix | fix |   #des#   |#des#|
+
+            var desiredStarMin = AggregateAdditionalConventionsForStars(conventions);
+            aggregatedLength += desiredStarMin;
+
+            // M6/7. Determine the desired length of the grid for current container length. Its value is stored in desiredLength.
+            // Assume if the container has infinite length, the grid desired length is stored in greedyDesiredLength.
+            //
+            // +-----------------------------------------------------------+
+            // |  *  |  A  |  *  |  P  |  A  |  *  |  P  |     *     |  *  |
+            // +-----------------------------------------------------------+
+            // | min | max |     |           | min |     |  min max  | max |
+            // |#des#| fix |#des#| fix | fix | fix | fix |   #des#   |#des#|
+            // Note: This table will be stored as the intermediate result into the MeasureResult and it will be reused by Arrange procedure.
+            // 
+            // desiredLength = Math.Max(0.0, des + fix + des + fix + fix + fix + fix + des + des)
+            // greedyDesiredLength = des + fix + des + fix + fix + fix + fix + des + des
+
+            var desiredLength = containerLength - aggregatedLength >= 0.0 ? aggregatedLength : containerLength;
+            var greedyDesiredLength = aggregatedLength;
+
+            // M7/7. Expand all the rest stars. These stars have no conventions or only have
+            // max value they can be expanded from zero to constraint.
+            //
+            // +-----------------------------------------------------------+
+            // |  *  |  A  |  *  |  P  |  A  |  *  |  P  |     *     |  *  |
+            // +-----------------------------------------------------------+
+            // | min | max |     |           | min |     |  min max  | max |
+            // |#fix#| fix |#fix#| fix | fix | fix | fix |   #fix#   |#fix#|
+            // Note: This table will be stored as the final result into the MeasureResult.
+
+            var dynamicConvention = ExpandStars(conventions, containerLength);
+            Clip(dynamicConvention, containerLength);
+
+            // Returns the measuring result.
+            return new MeasureResult(containerLength, desiredLength, greedyDesiredLength,
+                conventions, dynamicConvention);
+        }
+
+        /// <summary>
+        /// Run arrange procedure according to the <paramref name="measure"/> and gets the <see cref="ArrangeResult"/>.
+        /// </summary>
+        /// <param name="finalLength">
+        /// The container length. Usually, it is the finalSize of the <see cref="Layoutable.ArrangeOverride"/> method.
+        /// </param>
+        /// <param name="measure">
+        /// The result that the measuring procedure returns. If it is null, a new measure procedure will run.
+        /// </param>
+        /// <returns>
+        /// The measured result that containing the desired size and all the column/row length.
+        /// </returns>
+        [NotNull, Pure]
+        public ArrangeResult Arrange(double finalLength, [CanBeNull] MeasureResult measure)
+        {
+            measure = measure ?? Measure(finalLength);
+
+            // If the arrange final length does not equal to the measure length, we should measure again.
+            if (finalLength - measure.ContainerLength > LayoutTolerance)
+            {
+                // If the final length is larger, we will rerun the whole measure.
+                measure = Measure(finalLength);
+            }
+            else if (finalLength - measure.ContainerLength < -LayoutTolerance)
+            {
+                // If the final length is smaller, we measure the M6/6 procedure only.
+                var dynamicConvention = ExpandStars(measure.LeanLengthList, finalLength);
+                measure = new MeasureResult(finalLength, measure.DesiredLength, measure.GreedyDesiredLength,
+                    measure.LeanLengthList, dynamicConvention);
+            }
+
+            return new ArrangeResult(measure.LengthList);
+        }
+
+        /// <summary>
+        /// Use the <see cref="_additionalConventions"/> to calculate the fixed length of the Auto column/row.
+        /// </summary>
+        /// <param name="conventions">The convention list that all the * with minimum length are fixed.</param>
+        /// <param name="index">The column/row index that should be fixed.</param>
+        /// <param name="starUnitLength">The unit * length for the current rest length.</param>
+        /// <returns>The final length of the Auto length column/row.</returns>
+        [Pure]
+        private double ApplyAdditionalConventionsForAuto(IReadOnlyList<LengthConvention> conventions,
+            int index, double starUnitLength)
+        {
+            // 1. Calculate all the * length with starUnitLength.
+            // 2. Exclude all the fixed length and all the * length.
+            // 3. Compare the rest of the desired length and the convention.
+            // +-----------------+
+            // |  *  |  A  |  *  |
+            // +-----------------+
+            // | exl |     | exl |
+            // |< desired >|
+            //       |< desired >|
+
+            var more = 0.0;
+            foreach (var additional in _additionalConventions)
+            {
+                // If the additional convention's last column/row contains the Auto column/row, try to determine the Auto column/row length.
+                if (index == additional.Index + additional.Span - 1)
+                {
+                    var min = Enumerable.Range(additional.Index, additional.Span)
+                        .Select(x =>
+                        {
+                            var c = conventions[x];
+                            if (c.Length.IsAbsolute) return c.Length.Value;
+                            if (c.Length.IsStar) return c.Length.Value * starUnitLength;
+                            return 0.0;
+                        }).Sum();
+                    more = Math.Max(additional.Min - min, more);
+                }
+            }
+
+            return Math.Min(conventions[index].MaxLength, more);
+        }
+
+        /// <summary>
+        /// Calculate the total desired length of all the * length.
+        /// Bug Warning:
+        /// - The behavior of this method is undefined! Different UI Frameworks have different behaviors.
+        /// - We ignore all the span columns/rows and just take single cells into consideration.
+        /// </summary>
+        /// <param name="conventions">All the conventions that have almost been fixed except the rest *.</param>
+        /// <returns>The total desired length of all the * length.</returns>
+        [Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private double AggregateAdditionalConventionsForStars(
+            IReadOnlyList<LengthConvention> conventions)
+        {
+            // 1. Determine all one-span column's desired widths or row's desired heights.
+            // 2. Order the multi-span conventions by its last index
+            //    (Notice that the sorted data is much smaller than the source.)
+            // 3. Determine each multi-span last index by calculating the maximun desired size.
+
+            // Before we determine the behavior of this method, we just aggregate the one-span * columns.
+
+            var fixedLength = conventions.Where(x => x.Length.IsAbsolute).Sum(x => x.Length.Value);
+
+            // Prepare a lengthList variable indicating the fixed length of each column/row.
+            var lengthList = conventions.Select(x => x.Length.IsAbsolute ? x.Length.Value : 0.0).ToList();
+            foreach (var group in _additionalConventions
+                .Where(x => x.Span == 1 && conventions[x.Index].Length.IsStar)
+                .ToLookup(x => x.Index))
+            {
+                lengthList[group.Key] = Math.Max(lengthList[group.Key], group.Max(x => x.Min));
+            }
+
+            // Now the lengthList is fixed by every one-span columns/rows.
+            // Then we should determine the multi-span column's/row's length.
+            foreach (var group in _additionalConventions
+                .Where(x => x.Span > 1)
+                .ToLookup(x => x.Index + x.Span - 1)
+                // Order the multi-span columns/rows by last index.
+                .OrderBy(x => x.Key))
+            {
+                var length = group.Max(x => x.Min - Enumerable.Range(x.Index, x.Span - 1).Sum(r => lengthList[r]));
+                lengthList[group.Key] = Math.Max(lengthList[group.Key], length > 0 ? length : 0);
+            }
+
+            return lengthList.Sum() - fixedLength;
+        }
+
+        /// <summary>
+        /// This method implements the last procedure (M7/7) of measure.
+        /// It expands all the * length to the fixed length according to the <paramref name="constraint"/>.
+        /// </summary>
+        /// <param name="conventions">All the conventions that have almost been fixed except the remaining *.</param>
+        /// <param name="constraint">The container length.</param>
+        /// <returns>The final pixel length list.</returns>
+        [Pure]
+        private static List<double> ExpandStars(IEnumerable<LengthConvention> conventions, double constraint)
+        {
+            // Initial.
+            var dynamicConvention = conventions.Select(x => x.Clone()).ToList();
+            constraint -= dynamicConvention.Where(x => x.Length.IsAbsolute).Sum(x => x.Length.Value);
+            var starUnitLength = 0.0;
+
+            // M6/6.
+            if (constraint >= 0)
+            {
+                var starCount = dynamicConvention.Where(x => x.Length.IsStar).Sum(x => x.Length.Value);
+
+                var shouldTestStarMax = true;
+                while (shouldTestStarMax)
+                {
+                    var @fixed = false;
+                    starUnitLength = constraint / starCount;
+                    foreach (var convention in dynamicConvention.Where(x =>
+                        x.Length.IsStar && !double.IsPositiveInfinity(x.MaxLength)))
+                    {
+                        var (star, max) = (convention.Length.Value, convention.MaxLength);
+                        var starLength = star * starUnitLength;
+                        if (starLength > max)
+                        {
+                            convention.Fix(max);
+                            starLength = max;
+                            constraint -= starLength;
+                            starCount -= star;
+                            @fixed = true;
+                            break;
+                        }
+                    }
+
+                    shouldTestStarMax = @fixed;
+                }
+            }
+
+            Debug.Assert(dynamicConvention.All(x => !x.Length.IsAuto));
+
+            var starUnit = starUnitLength;
+            var result = dynamicConvention.Select(x =>
+            {
+                if (x.Length.IsStar)
+                {
+                    return double.IsInfinity(starUnit) ? double.PositiveInfinity : starUnit * x.Length.Value;
+                }
+
+                return x.Length.Value;
+            }).ToList();
+
+            return result;
+        }
+
+        /// <summary>
+        /// If the container length is not infinity. It may be not enough to contain all the columns/rows.
+        /// We should clip the columns/rows that have been out of the container bounds.
+        /// Note: This method may change the items value of <paramref name="lengthList"/>.
+        /// </summary>
+        /// <param name="lengthList">A list of all the column widths and row heights with a fixed pixel length</param>
+        /// <param name="constraint">the container length. It can be positive infinity.</param>
+        private static void Clip([NotNull] IList<double> lengthList, double constraint)
+        {
+            if (double.IsInfinity(constraint))
+            {
+                return;
+            }
+
+            var measureLength = 0.0;
+            for (var i = 0; i < lengthList.Count; i++)
+            {
+                var length = lengthList[i];
+                if (constraint - measureLength > length)
+                {
+                    measureLength += length;
+                }
+                else
+                {
+                    lengthList[i] = constraint - measureLength;
+                    measureLength = constraint;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Contains the convention of each column/row.
+        /// This is mostly the same as <see cref="RowDefinition"/> or <see cref="ColumnDefinition"/>.
+        /// We use this because we can treat the column and the row the same.
+        /// </summary>
+        [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")]
+        internal class LengthConvention : ICloneable
+        {
+            /// <summary>
+            /// Initialize a new instance of <see cref="LengthConvention"/>.
+            /// </summary>
+            public LengthConvention()
+            {
+                Length = new GridLength(1.0, GridUnitType.Star);
+                MinLength = 0.0;
+                MaxLength = double.PositiveInfinity;
+            }
+
+            /// <summary>
+            /// Initialize a new instance of <see cref="LengthConvention"/>.
+            /// </summary>
+            public LengthConvention(GridLength length, double minLength, double maxLength)
+            {
+                Length = length;
+                MinLength = minLength;
+                MaxLength = maxLength;
+                if (length.IsAbsolute)
+                {
+                    _isFixed = true;
+                }
+            }
+
+            /// <summary>
+            /// Gets the <see cref="GridLength"/> of a column or a row.
+            /// </summary>
+            internal GridLength Length { get; private set; }
+
+            /// <summary>
+            /// Gets the minimum convention for a column or a row.
+            /// </summary>
+            internal double MinLength { get; }
+
+            /// <summary>
+            /// Gets the maximum convention for a column or a row.
+            /// </summary>
+            internal double MaxLength { get; }
+
+            /// <summary>
+            /// Fix the <see cref="LengthConvention"/>.
+            /// If all columns/rows are fixed, we can get the size of all columns/rows in pixels.
+            /// </summary>
+            /// <param name="pixel">
+            /// The pixel length that should be used to fix the convention.
+            /// </param>
+            /// <exception cref="InvalidOperationException">
+            /// If the convention is pixel length, this exception will throw.
+            /// </exception>
+            public void Fix(double pixel)
+            {
+                if (_isFixed)
+                {
+                    throw new InvalidOperationException("Cannot fix the length convention if it is fixed.");
+                }
+
+                Length = new GridLength(pixel);
+                _isFixed = true;
+            }
+
+            /// <summary>
+            /// Gets a value that indicates whether this convention is fixed.
+            /// </summary>
+            private bool _isFixed;
+
+            /// <summary>
+            /// Helps the debugger to display the intermediate column/row calculation result.
+            /// </summary>
+            private string DebuggerDisplay =>
+                $"{(_isFixed ? Length.Value.ToString(CultureInfo.InvariantCulture) : (Length.GridUnitType == GridUnitType.Auto ? "Auto" : $"{Length.Value}*"))}, ∈[{MinLength}, {MaxLength}]";
+
+            /// <inheritdoc />
+            object ICloneable.Clone() => Clone();
+
+            /// <summary>
+            /// Get a deep copy of this convention list.
+            /// We need this because we want to store some intermediate states.
+            /// </summary>
+            internal LengthConvention Clone() => new LengthConvention(Length, MinLength, MaxLength);
+        }
+
+        /// <summary>
+        /// Contains the convention that comes from the grid children.
+        /// Some children span multiple columns or rows, so even a simple column/row can have multiple conventions.
+        /// </summary>
+        [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")]
+        internal struct AdditionalLengthConvention
+        {
+            /// <summary>
+            /// Initialize a new instance of <see cref="AdditionalLengthConvention"/>.
+            /// </summary>
+            public AdditionalLengthConvention(int index, int span, double min)
+            {
+                Index = index;
+                Span = span;
+                Min = min;
+            }
+
+            /// <summary>
+            /// Gets the start index of this additional convention.
+            /// </summary>
+            public int Index { get; }
+
+            /// <summary>
+            /// Gets the span of this additional convention.
+            /// </summary>
+            public int Span { get; }
+
+            /// <summary>
+            /// Gets the minimum length of this additional convention.
+            /// This value is usually provided by the child's desired length.
+            /// </summary>
+            public double Min { get; }
+
+            /// <summary>
+            /// Helps the debugger to display the intermediate column/row calculation result.
+            /// </summary>
+            private string DebuggerDisplay =>
+                $"{{{string.Join(",", Enumerable.Range(Index, Span))}}}, ∈[{Min},∞)";
+        }
+
+        /// <summary>
+        /// Stores the result of the measuring procedure.
+        /// This result can be used to measure children and assign the desired size.
+        /// Passing this result to <see cref="Arrange"/> can reduce calculation.
+        /// </summary>
+        [DebuggerDisplay("{" + nameof(LengthList) + ",nq}")]
+        internal class MeasureResult
+        {
+            /// <summary>
+            /// Initialize a new instance of <see cref="MeasureResult"/>.
+            /// </summary>
+            internal MeasureResult(double containerLength, double desiredLength, double greedyDesiredLength,
+                IReadOnlyList<LengthConvention> leanConventions, IReadOnlyList<double> expandedConventions)
+            {
+                ContainerLength = containerLength;
+                DesiredLength = desiredLength;
+                GreedyDesiredLength = greedyDesiredLength;
+                LeanLengthList = leanConventions;
+                LengthList = expandedConventions;
+            }
+
+            /// <summary>
+            /// Gets the container length for this result.
+            /// This property will be used by <see cref="Arrange"/> to determine whether to measure again or not.
+            /// </summary>
+            public double ContainerLength { get; }
+
+            /// <summary>
+            /// Gets the desired length of this result.
+            /// Just return this value as the desired size in <see cref="Layoutable.MeasureOverride"/>.
+            /// </summary>
+            public double DesiredLength { get; }
+
+            /// <summary>
+            /// Gets the desired length if the container has infinite length.
+            /// </summary>
+            public double GreedyDesiredLength { get; }
+
+            /// <summary>
+            /// Contains the column/row calculation intermediate result.
+            /// This value is used by <see cref="Arrange"/> for reducing repeat calculation.
+            /// </summary>
+            public IReadOnlyList<LengthConvention> LeanLengthList { get; }
+
+            /// <summary>
+            /// Gets the length list for each column/row.
+            /// </summary>
+            public IReadOnlyList<double> LengthList { get; }
+        }
+
+        /// <summary>
+        /// Stores the result of the measuring procedure.
+        /// This result can be used to arrange children and assign the render size.
+        /// </summary>
+        [DebuggerDisplay("{" + nameof(LengthList) + ",nq}")]
+        internal class ArrangeResult
+        {
+            /// <summary>
+            /// Initialize a new instance of <see cref="ArrangeResult"/>.
+            /// </summary>
+            internal ArrangeResult(IReadOnlyList<double> lengthList)
+            {
+                LengthList = lengthList;
+            }
+
+            /// <summary>
+            /// Gets the length list for each column/row.
+            /// </summary>
+            public IReadOnlyList<double> LengthList { get; }
+        }
+    }
+}

+ 20 - 10
src/Avalonia.Controls/Window.cs

@@ -67,13 +67,19 @@ namespace Avalonia.Controls
         /// </summary>
         public static readonly StyledProperty<bool> HasSystemDecorationsProperty =
             AvaloniaProperty.Register<Window, bool>(nameof(HasSystemDecorations), true);
-        
+
         /// <summary>
         /// Enables or disables the taskbar icon
         /// </summary>
         public static readonly StyledProperty<bool> ShowInTaskbarProperty =
             AvaloniaProperty.Register<Window, bool>(nameof(ShowInTaskbar), true);
-        
+
+        /// <summary>
+        /// Enables or disables the taskbar icon
+        /// </summary>
+        public static readonly StyledProperty<WindowState> WindowStateProperty =
+            AvaloniaProperty.Register<Window, WindowState>(nameof(WindowState));
+
         /// <summary>
         /// Defines the <see cref="Title"/> property.
         /// </summary>
@@ -118,6 +124,9 @@ namespace Avalonia.Controls
             IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl?.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
 
             CanResizeProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.CanResize((bool)e.NewValue));
+
+            WindowStateProperty.Changed.AddClassHandler<Window>(
+                (w, e) => { if (w.PlatformImpl != null) w.PlatformImpl.WindowState = (WindowState)e.NewValue; });
         }
 
         /// <summary>
@@ -138,8 +147,11 @@ namespace Avalonia.Controls
             impl.Closing = HandleClosing;
             _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size);
             Screens = new Screens(PlatformImpl?.Screen);
-        }
 
+            if (PlatformImpl != null)
+                PlatformImpl.WindowStateChanged = s => WindowState = s;
+        }
+        
         /// <inheritdoc/>
         event EventHandler<NameScopeEventArgs> INameScope.Registered
         {
@@ -205,16 +217,14 @@ namespace Avalonia.Controls
         /// </summary>
         public WindowState WindowState
         {
-            get { return PlatformImpl?.WindowState ?? WindowState.Normal; }
-            set
-            {
-                if (PlatformImpl != null)
-                    PlatformImpl.WindowState = value;
-            }
+            get { return GetValue(WindowStateProperty); }
+            set { SetValue(WindowStateProperty, value); }
         }
 
         /// <summary>
-        /// Enables or disables resizing of the window
+        /// Enables or disables resizing of the window.
+        /// Note that if <see cref="HasSystemDecorations"/> is set to False then this property
+        /// has no effect and should be treated as a recommendation for the user setting HasSystemDecorations.
         /// </summary>
         public bool CanResize
         {

+ 0 - 8
src/Avalonia.DesignerSupport/Properties/AssemblyInfo.cs

@@ -1,8 +0,0 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System.Reflection;
-using Avalonia.Metadata;
-
-[assembly: AssemblyTitle("Avalonia.Application")]
-[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia")]

+ 1 - 0
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@@ -42,6 +42,7 @@ namespace Avalonia.DesignerSupport.Remote
         public Func<bool> Closing { get; set; }
         public IPlatformHandle Handle { get; }
         public WindowState WindowState { get; set; }
+        public Action<WindowState> WindowStateChanged { get; set; }
         public Size MaxClientSize { get; } = new Size(4096, 4096);
         public event Action LostFocus;
 

+ 1 - 0
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@@ -32,6 +32,7 @@ namespace Avalonia.DesignerSupport.Remote
         public Point Position { get; set; }
         public Action<Point> PositionChanged { get; set; }
         public WindowState WindowState { get; set; }
+        public Action<WindowState> WindowStateChanged { get; set; }
         public IRenderer CreateRenderer(IRenderRoot root) => new ImmediateRenderer(root);
         public void Dispose()
         {

+ 2 - 35
src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj

@@ -1,29 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>TRACE;DEBUG</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Diagnostics.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Diagnostics.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   <ItemGroup>
     <ProjectReference Include="..\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
@@ -37,17 +14,7 @@
     <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
     <ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj" />
     <ProjectReference Include="..\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-    <Compile Update="**\*.xaml.cs">
-      <DependentUpon>%(Filename)</DependentUpon>
-    </Compile>
-    <EmbeddedResource Include="**\*.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-  </ItemGroup>
+  </ItemGroup>  
+  <Import Project="..\..\build\EmbedXaml.props" />
   <Import Project="..\..\build\Rx.props" />
 </Project>

+ 0 - 6
src/Avalonia.Diagnostics/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System.Reflection;
-
-[assembly: AssemblyTitle("Avalonia.Diagnostics")]

+ 1 - 10
src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj

@@ -1,17 +1,8 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netcoreapp2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <DefineConstants>$(DefineConstants);DOTNETCORE</DefineConstants>
   </PropertyGroup>
-  <PropertyGroup>
-    <DocumentationFile>bin\$(Configuration)\Avalonia.DotNetCoreRuntime.xml</DocumentationFile>
-  </PropertyGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-  </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
     <ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" />
@@ -20,7 +11,7 @@
     <ProjectReference Include="..\OSX\Avalonia.MonoMac\Avalonia.MonoMac.csproj" />
     <ProjectReference Include="..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
     <ProjectReference Include="..\Windows\Avalonia.Win32\Avalonia.Win32.csproj" />
-  </ItemGroup>
+  </ItemGroup>  
   <Import Project="..\..\build\NetCore.props" />
   <Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" />
 </Project>

+ 0 - 6
src/Avalonia.DotNetCoreRuntime/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System.Reflection;
-
-[assembly: AssemblyTitle("Avalonia.DotNetCoreRuntime")]

+ 2 - 6
src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj

@@ -1,21 +1,17 @@
 <Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
         <TargetFramework>net461</TargetFramework>
-        <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
         <DocumentationFile>bin\$(Configuration)\Avalonia.DotNetFrameworkRuntime.xml</DocumentationFile>
         <DefineConstants>$(DefineConstants);FULLDOTNET</DefineConstants>
         <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     </PropertyGroup>
     <ItemGroup>
-        <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-            <Link>Properties\SharedAssemblyInfo.cs</Link>
-        </Compile>
         <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
         <ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" />
         <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
         <ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj" />
-    </ItemGroup>
+    </ItemGroup>    
     <Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" Label="Shared" />
     <Import Project="..\..\build\Rx.props" />
     <Import Project="..\..\build\NetFX.props" />
-</Project>
+</Project>

+ 1 - 115
src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj

@@ -3,127 +3,12 @@
     <TargetFramework>netstandard2.0</TargetFramework>
     <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
     <EnableDefaultItems>False</EnableDefaultItems>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <NoWarn>CS0436</NoWarn>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>TRACE;DEBUG;PCL</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE;PCL</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
   <ItemGroup>
     <Content Include="external\Source\HtmlRenderer\Core\Utils\ImageError.png" />
     <Content Include="external\Source\HtmlRenderer\Core\Utils\ImageLoad.png" />
   </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Adapters\BrushAdapter.cs" />
-    <Compile Include="Adapters\ContextMenuAdapter.cs" />
-    <Compile Include="Adapters\ControlAdapter.cs" />
-    <Compile Include="Adapters\FontAdapter.cs" />
-    <Compile Include="Adapters\FontFamilyAdapter.cs" />
-    <Compile Include="Adapters\GraphicsAdapter.cs" />
-    <Compile Include="Adapters\GraphicsPathAdapter.cs" />
-    <Compile Include="Adapters\ImageAdapter.cs" />
-    <Compile Include="Adapters\PenAdapter.cs" />
-    <Compile Include="Adapters\AvaloniaAdapter.cs" />
-    <Compile Include="Compat\Api.cs" />
-    <Compile Include="Compat\Attributes.cs" />
-    <Compile Include="Compat\ThreadPool.cs" />
-    <Compile Include="external\Source\HtmlRenderer.Pcl\PclCompat.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\Entities\RColor.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\Entities\RDashStyle.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\Entities\RFontStyle.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\Entities\RKeyEvent.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\Entities\RMouseEvent.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\Entities\RPoint.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\Entities\RRect.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\Entities\RSize.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\RAdapter.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\RBrush.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\RContextMenu.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\RControl.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\RFont.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\RFontFamily.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\RGraphics.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\RGraphicsPath.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\RImage.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Adapters\RPen.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\CssData.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\CssDefaults.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\Border.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssBox.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssBoxFrame.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssBoxHr.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssBoxImage.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssBoxProperties.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssLayoutEngine.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssLayoutEngineTable.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssLength.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssLineBox.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssRect.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssRectImage.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssRectWord.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssSpacingBox.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\CssUnit.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\HoverBoxBlock.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Dom\HtmlTag.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\CssBlock.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\CssBlockSelectorItem.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\HtmlGenerationStyle.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\HtmlImageLoadEventArgs.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\HtmlLinkClickedEventArgs.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\HtmlLinkClickedException.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\HtmlRefreshEventArgs.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\HtmlRenderErrorEventArgs.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\HtmlRenderErrorType.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\HtmlScrollEventArgs.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\HtmlStylesheetLoadEventArgs.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Entities\LinkElementData.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Handlers\BackgroundImageDrawHandler.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Handlers\BordersDrawHandler.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Handlers\ContextMenuHandler.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Handlers\FontsHandler.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Handlers\ImageDownloader.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Handlers\ImageLoadHandler.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Handlers\SelectionHandler.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Handlers\StylesheetLoadHandler.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\HtmlContainerInt.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\HtmlRendererUtils.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Parse\CssParser.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Parse\CssValueParser.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Parse\DomParser.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Parse\HtmlParser.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Parse\RegexParserHelper.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Parse\RegexParserUtils.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Utils\ArgChecker.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Utils\CommonUtils.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Utils\CssConstants.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Utils\CssUtils.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Utils\DomUtils.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Utils\HtmlConstants.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Utils\HtmlUtils.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Utils\RenderUtils.cs" />
-    <Compile Include="external\Source\HtmlRenderer\Core\Utils\SubString.cs" />
-    <Compile Include="HtmlContainer.cs" />
-    <Compile Include="HtmlControl.cs" />
-    <Compile Include="HtmlLabel.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="PropertyHelper.cs" />
-    <Compile Include="HtmlRendererRoutedEventArgs.cs" />
-    <Compile Include="Utilities\Util.cs" />
-  </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
@@ -134,5 +19,6 @@
     <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
     <ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj" />
   </ItemGroup>
+  
   <Import Project="..\..\build\Rx.props" />
 </Project>

+ 1 - 29
src/Avalonia.Input/Avalonia.Input.csproj

@@ -1,29 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Input.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Input.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
@@ -31,11 +8,6 @@
     <ProjectReference Include="..\Avalonia.Interactivity\Avalonia.Interactivity.csproj" />
     <ProjectReference Include="..\Avalonia.Layout\Avalonia.Layout.csproj" />
     <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-  </ItemGroup>
+  </ItemGroup>  
   <Import Project="..\..\build\Rx.props" />
 </Project>

+ 0 - 1
src/Avalonia.Input/Properties/AssemblyInfo.cs

@@ -4,5 +4,4 @@
 using System.Reflection;
 using Avalonia.Metadata;
 
-[assembly: AssemblyTitle("Avalonia.Input")]
 [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Input")]

+ 3 - 29
src/Avalonia.Interactivity/Avalonia.Interactivity.csproj

@@ -1,29 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Interactivity.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Interactivity.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
@@ -31,10 +8,7 @@
     <ProjectReference Include="..\Avalonia.Layout\Avalonia.Layout.csproj" />
     <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
   </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-  </ItemGroup>
   <Import Project="..\..\build\Rx.props" />
-</Project>
+</Project>
+
+

+ 0 - 6
src/Avalonia.Interactivity/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System.Reflection;
-
-[assembly: AssemblyTitle("Avalonia.Interactive")]

+ 1 - 29
src/Avalonia.Layout/Avalonia.Layout.csproj

@@ -1,39 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Layout.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Layout.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
     <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-  </ItemGroup>
+  </ItemGroup>  
   <Import Project="..\..\build\Rx.props" />
 </Project>

+ 29 - 0
src/Avalonia.Layout/LayoutHelper.cs

@@ -29,5 +29,34 @@ namespace Avalonia.Layout
             height = Math.Max(height, control.MinHeight);
             return new Size(width, height);
         }
+
+        public static Size MeasureChild(ILayoutable control, Size availableSize, Thickness padding,
+            Thickness borderThickness)
+        {
+            return MeasureChild(control, availableSize, padding + borderThickness);
+        }
+
+        public static Size MeasureChild(ILayoutable control, Size availableSize, Thickness padding)
+        {
+            if (control != null)
+            {
+                control.Measure(availableSize.Deflate(padding));
+                return control.DesiredSize.Inflate(padding);
+            }
+
+            return new Size(padding.Left + padding.Right, padding.Bottom + padding.Top);
+        }
+
+        public static Size ArrangeChild(ILayoutable child, Size availableSize, Thickness padding, Thickness borderThickness)
+        {
+            return ArrangeChild(child, availableSize, padding + borderThickness);
+        }
+
+        public static Size ArrangeChild(ILayoutable child, Size availableSize, Thickness padding)
+        {
+            child?.Arrange(new Rect(availableSize).Deflate(padding));
+
+            return availableSize;
+        }
     }
 }

+ 0 - 6
src/Avalonia.Layout/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System.Reflection;
-
-[assembly: AssemblyTitle("Avalonia.Layout")]

+ 1 - 25
src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj

@@ -1,34 +1,10 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Logging.Serilog.xml</DocumentationFile>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Logging.Serilog.xml</DocumentationFile>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-  </PropertyGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
-  </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
     <ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" />
-  </ItemGroup>
+  </ItemGroup>  
   <Import Project="..\..\build\Serilog.props" />
 </Project>

+ 0 - 3
src/Avalonia.Logging.Serilog/Properties/AssemblyInfo.cs

@@ -1,3 +0,0 @@
-using System.Reflection;
-
-[assembly: AssemblyTitle("Avalonia.Serilog")]

+ 0 - 2
src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj

@@ -1,10 +1,8 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
   </PropertyGroup>
   <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
     <ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
     <ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" />

+ 0 - 6
src/Avalonia.ReactiveUI/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System.Reflection;
-
-[assembly: AssemblyTitle("Avalonia.ReactiveUI")]

+ 1 - 28
src/Avalonia.Styling/Avalonia.Styling.csproj

@@ -1,36 +1,9 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+    <AssemblyName>Avalonia.Styling</AssemblyName>
     <RootNamespace>Avalonia</RootNamespace>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Styling.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Styling.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-  </PropertyGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-  </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />

+ 0 - 1
src/Avalonia.Styling/Properties/AssemblyInfo.cs

@@ -5,7 +5,6 @@ using System.Reflection;
 using System.Runtime.CompilerServices;
 using Avalonia.Metadata;
 
-[assembly: AssemblyTitle("Avalonia.Styling")]
 [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")]
 [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.LogicalTree")]
 [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Styling")]

+ 2 - 33
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@@ -1,27 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Themes.Default.xml</DocumentationFile>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Themes.Default.xml</DocumentationFile>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   <ItemGroup>
     <ProjectReference Include="..\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
@@ -33,17 +12,7 @@
     <ProjectReference Include="..\Avalonia.Layout\Avalonia.Layout.csproj" />
     <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
     <ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-    <Compile Update="**\*.xaml.cs">
-      <DependentUpon>%(Filename)</DependentUpon>
-    </Compile>
-    <EmbeddedResource Include="**\*.xaml">
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
-  </ItemGroup>
+  </ItemGroup>  
+  <Import Project="..\..\build\EmbedXaml.props" />
   <Import Project="..\..\build\Rx.props" />
 </Project>

+ 12 - 6
src/Avalonia.Themes.Default/ButtonSpinner.xaml

@@ -46,12 +46,15 @@
                 BorderBrush="{TemplateBinding BorderBrush}"
                 BorderThickness="{TemplateBinding BorderThickness}"
                 Margin="{TemplateBinding Padding}"
-                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
-                VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
+                HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
+                VerticalAlignment="{TemplateBinding VerticalAlignment}">
           <Grid ColumnDefinitions="*,Auto">
             <ContentPresenter Name="PART_ContentPresenter" Grid.Column="0"
                               ContentTemplate="{TemplateBinding ContentTemplate}"
-                              Content="{TemplateBinding Content}"/>
+                              Content="{TemplateBinding Content}"
+                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+                              Padding="{TemplateBinding Padding}"/>
             <Grid Grid.Column="1" RowDefinitions="*,*" IsVisible="{TemplateBinding ShowButtonSpinner}">
               <RepeatButton Grid.Row="0" Name="PART_IncreaseButton"/>
               <RepeatButton Grid.Row="1" Name="PART_DecreaseButton"/>
@@ -68,8 +71,8 @@
                 BorderBrush="{TemplateBinding BorderBrush}"
                 BorderThickness="{TemplateBinding BorderThickness}"
                 Margin="{TemplateBinding Padding}"
-                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
-                VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
+                HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
+                VerticalAlignment="{TemplateBinding VerticalAlignment}">
           <Grid ColumnDefinitions="Auto,*">
             <Grid Grid.Column="0" RowDefinitions="*,*" IsVisible="{TemplateBinding ShowButtonSpinner}">
               <RepeatButton Grid.Row="0" Name="PART_IncreaseButton"/>
@@ -77,7 +80,10 @@
             </Grid>
             <ContentPresenter Name="PART_ContentPresenter" Grid.Column="1"
                               ContentTemplate="{TemplateBinding ContentTemplate}"
-                              Content="{TemplateBinding Content}"/>
+                              Content="{TemplateBinding Content}"
+                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+                              Padding="{TemplateBinding Padding}"/>
           </Grid>
         </Border>
       </ControlTemplate>

+ 1 - 1
src/Avalonia.Themes.Default/CalendarItem.xaml

@@ -27,7 +27,7 @@
                 </Grid.RowDefinitions>
                 <Grid.ColumnDefinitions>
                   <ColumnDefinition Width="Auto" />
-                  <ColumnDefinition Width="Auto" />
+                  <ColumnDefinition Width="*" />
                   <ColumnDefinition Width="Auto" />
                 </Grid.ColumnDefinitions>
 

+ 3 - 1
src/Avalonia.Themes.Default/ContentControl.xaml

@@ -7,7 +7,9 @@
                         BorderThickness="{TemplateBinding BorderThickness}"
                         ContentTemplate="{TemplateBinding ContentTemplate}"
                         Content="{TemplateBinding Content}"
-                        Padding="{TemplateBinding Padding}"/>
+                        Padding="{TemplateBinding Padding}"
+                        VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+                        HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/>
     </ControlTemplate>
   </Setter>
 </Style>

+ 16 - 9
src/Avalonia.Themes.Default/Expander.xaml

@@ -18,8 +18,9 @@
                               IsVisible="{TemplateBinding IsExpanded}"
                               ContentTemplate="{TemplateBinding ContentTemplate}"
                               Content="{TemplateBinding Content}"
-                              HorizontalAlignment="Stretch"
-                              VerticalAlignment="Stretch" />
+                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+                              Padding="{TemplateBinding Padding}" />
           </Grid>
         </Border>
       </ControlTemplate>
@@ -36,8 +37,9 @@
                               IsVisible="{TemplateBinding IsExpanded}"
                               ContentTemplate="{TemplateBinding ContentTemplate}"
                               Content="{TemplateBinding Content}"
-                              HorizontalAlignment="Stretch"
-                              VerticalAlignment="Stretch" />
+                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+                              Padding="{TemplateBinding Padding}" />
           </Grid>
         </Border>
       </ControlTemplate>
@@ -54,8 +56,9 @@
                               IsVisible="{TemplateBinding IsExpanded}"
                               ContentTemplate="{TemplateBinding ContentTemplate}"
                               Content="{TemplateBinding Content}"
-                              HorizontalAlignment="Stretch"
-                              VerticalAlignment="Stretch" />
+                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+                              Padding="{TemplateBinding Padding}" />
           </Grid>
         </Border>
       </ControlTemplate>
@@ -72,8 +75,9 @@
                               IsVisible="{TemplateBinding IsExpanded}"
                               ContentTemplate="{TemplateBinding ContentTemplate}"
                               Content="{TemplateBinding Content}"
-                              HorizontalAlignment="Stretch"
-                              VerticalAlignment="Stretch" />
+                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+                              Padding="{TemplateBinding Padding}" />
           </Grid>
         </Border>
       </ControlTemplate>
@@ -94,7 +98,10 @@
                               Grid.Column="1" 
                               Background="Transparent" 
                               Content="{TemplateBinding Content}" 
-                              VerticalAlignment="Center" />
+                              VerticalAlignment="Center" 
+                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+                              Padding="{TemplateBinding Padding}"/>
           </Grid>
         </Border>
       </ControlTemplate>

+ 3 - 1
src/Avalonia.Themes.Default/ListBoxItem.xaml

@@ -9,7 +9,9 @@
                           BorderThickness="{TemplateBinding BorderThickness}"
                           ContentTemplate="{TemplateBinding ContentTemplate}"
                           Content="{TemplateBinding Content}"
-                          Padding="{TemplateBinding Padding}"/>
+                          Padding="{TemplateBinding Padding}"
+                          VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+                          HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/>
       </ControlTemplate>
     </Setter>
   </Style>

+ 0 - 6
src/Avalonia.Themes.Default/Properties/AssemblyInfo.cs

@@ -1,6 +0,0 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System.Reflection;
-
-[assembly: AssemblyTitle("Avalonia.Themes.Default")]

+ 1 - 1
src/Avalonia.Themes.Default/RepeatButton.xaml

@@ -25,7 +25,7 @@
                                   Padding="{TemplateBinding Padding}"
                                   TextBlock.Foreground="{TemplateBinding Foreground}"
                                   HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
-                                  VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
+                                  VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
             </ControlTemplate>
         </Setter>
     </Style>

+ 2 - 0
src/Avalonia.Themes.Default/TabStripItem.xaml

@@ -11,6 +11,8 @@
                           BorderThickness="{TemplateBinding BorderThickness}"
                           ContentTemplate="{TemplateBinding ContentTemplate}"
                           Content="{TemplateBinding Content}"
+                          HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                          VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                           Padding="{TemplateBinding Padding}"/>
       </ControlTemplate>
     </Setter>

+ 4 - 3
src/Avalonia.Themes.Default/TextBox.xaml

@@ -11,7 +11,7 @@
                 BorderBrush="{TemplateBinding BorderBrush}"
                 BorderThickness="{TemplateBinding BorderThickness}">
           <DockPanel Margin="{TemplateBinding Padding}">
-            
+
             <TextBlock Name="floatingWatermark"
                        Foreground="{DynamicResource ThemeAccentBrush}"
                        FontSize="{DynamicResource FontSizeSmall}"
@@ -31,7 +31,7 @@
             <DataValidationErrors>
               <ScrollViewer HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
                             VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}">
-                
+
                 <Panel>
                   <TextBlock Name="watermark"
                              Opacity="0.5"
@@ -43,7 +43,8 @@
                                  SelectionStart="{TemplateBinding SelectionStart}"
                                  SelectionEnd="{TemplateBinding SelectionEnd}"
                                  TextAlignment="{TemplateBinding TextAlignment}"
-                                 TextWrapping="{TemplateBinding TextWrapping}"/>
+                                 TextWrapping="{TemplateBinding TextWrapping}"
+                                 PasswordChar="{TemplateBinding PasswordChar}"/>
                 </Panel>
               </ScrollViewer>
             </DataValidationErrors>

+ 2 - 0
src/Avalonia.Themes.Default/TreeViewItem.xaml

@@ -13,6 +13,8 @@
                               BorderBrush="{TemplateBinding BorderBrush}"
                               BorderThickness="{TemplateBinding BorderThickness}"
                               Content="{TemplateBinding Header}"
+                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                               Padding="{TemplateBinding Padding}"
                               TemplatedControl.IsTemplateFocusTarget="True"
                               Grid.Column="1"/>

+ 5 - 3
src/Avalonia.Themes.Default/Window.xaml

@@ -6,10 +6,12 @@
     <ControlTemplate>
       <Border Background="{TemplateBinding Background}">
         <AdornerDecorator>
-          <ContentPresenter Name="PART_ContentPresenter" 
+          <ContentPresenter Name="PART_ContentPresenter"
                             ContentTemplate="{TemplateBinding ContentTemplate}"
-                            Content="{TemplateBinding Content}" 
-                            Margin="{TemplateBinding Padding}"/>
+                            Content="{TemplateBinding Content}"
+                            Margin="{TemplateBinding Padding}"
+                            HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
+                            VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>           
         </AdornerDecorator>
       </Border>
     </ControlTemplate>

+ 1 - 29
src/Avalonia.Visuals/Avalonia.Visuals.csproj

@@ -1,39 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <RootNamespace>Avalonia</RootNamespace>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Visuals.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Visuals.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-  </PropertyGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-  </ItemGroup>
+  </ItemGroup>  
   <Import Project="..\..\build\Rx.props" />
 </Project>

+ 1 - 1
src/Avalonia.Visuals/Matrix.cs

@@ -11,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// A 2x3 matrix.
     /// </summary>
-    public struct Matrix
+    public readonly struct Matrix
     {
         private readonly double _m11;
         private readonly double _m12;

+ 1 - 1
src/Avalonia.Visuals/Media/Color.cs

@@ -11,7 +11,7 @@ namespace Avalonia.Media
     /// <summary>
     /// An ARGB color.
     /// </summary>
-    public struct Color
+    public readonly struct Color
     {
         /// <summary>
         /// Gets or sets the Alpha component of the color.

+ 2 - 2
src/Avalonia.Visuals/Media/DrawingContext.cs

@@ -19,7 +19,7 @@ namespace Avalonia.Media
             ? new Stack<TransformContainer>()
             : TransformStackPool.Pop();
 
-        struct TransformContainer
+        readonly struct TransformContainer
         {
             public readonly Matrix LocalTransform;
             public readonly Matrix ContainerTransform;
@@ -147,7 +147,7 @@ namespace Avalonia.Media
             }
         }
 
-        public struct PushedState : IDisposable
+        public readonly struct PushedState : IDisposable
         {
             private readonly int _level;
             private readonly DrawingContext _context;

+ 1 - 1
src/Avalonia.Visuals/Media/Immutable/ImmutableSolidColorBrush.cs

@@ -6,7 +6,7 @@ namespace Avalonia.Media.Immutable
     /// <summary>
     /// Fills an area with a solid color.
     /// </summary>
-    public struct ImmutableSolidColorBrush : ISolidColorBrush
+    public readonly struct ImmutableSolidColorBrush : ISolidColorBrush
     {
         /// <summary>
         /// Initializes a new instance of the <see cref="ImmutableSolidColorBrush"/> class.

+ 1 - 1
src/Avalonia.Visuals/Point.cs

@@ -11,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// Defines a point.
     /// </summary>
-    public struct Point
+    public readonly struct Point
     {
         /// <summary>
         /// The X position.

+ 0 - 1
src/Avalonia.Visuals/Properties/AssemblyInfo.cs

@@ -5,7 +5,6 @@ using System.Reflection;
 using System.Runtime.CompilerServices;
 using Avalonia.Metadata;
 
-[assembly: AssemblyTitle("Avalonia.Visuals")]
 [assembly: InternalsVisibleTo("Avalonia.Visuals.UnitTests")]
 [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation")]
 [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Media")]

+ 1 - 1
src/Avalonia.Visuals/Rect.cs

@@ -11,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// Defines a rectangle.
     /// </summary>
-    public struct Rect
+    public readonly struct Rect
     {
         /// <summary>
         /// An empty rectangle.

+ 2 - 2
src/Avalonia.Visuals/RelativePoint.cs

@@ -28,7 +28,7 @@ namespace Avalonia
     /// <summary>
     /// Defines a point that may be defined relative to a containing element.
     /// </summary>
-    public struct RelativePoint : IEquatable<RelativePoint>
+    public readonly struct RelativePoint : IEquatable<RelativePoint>
     {
         /// <summary>
         /// A point at the top left of the containing element.
@@ -45,7 +45,7 @@ namespace Avalonia
         /// </summary>
         public static readonly RelativePoint BottomRight = new RelativePoint(1, 1, RelativeUnit.Relative);
 
-        private Point _point;
+        private readonly Point _point;
 
         private readonly RelativeUnit _unit;
 

+ 1 - 1
src/Avalonia.Visuals/RelativeRect.cs

@@ -11,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// Defines a rectangle that may be defined relative to a containing element.
     /// </summary>
-    public struct RelativeRect : IEquatable<RelativeRect>
+    public readonly struct RelativeRect : IEquatable<RelativeRect>
     {
         private static readonly char[] PercentChar = { '%' };
 

+ 1 - 1
src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs

@@ -320,7 +320,7 @@ namespace Avalonia.Rendering.SceneGraph
             }
         }
 
-        public struct UpdateState : IDisposable
+        public readonly struct UpdateState : IDisposable
         {
             public UpdateState(
                 DeferredDrawingContextImpl owner,

+ 1 - 1
src/Avalonia.Visuals/Size.cs

@@ -11,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// Defines a size.
     /// </summary>
-    public struct Size
+    public readonly struct Size
     {
         /// <summary>
         /// A size representing infinity.

+ 1 - 1
src/Avalonia.Visuals/Thickness.cs

@@ -11,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// Describes the thickness of a frame around a rectangle.
     /// </summary>
-    public struct Thickness
+    public readonly struct Thickness
     {
         /// <summary>
         /// The thickness on the left.

+ 1 - 1
src/Avalonia.Visuals/Vector.cs

@@ -10,7 +10,7 @@ namespace Avalonia
     /// <summary>
     /// Defines a vector.
     /// </summary>
-    public struct Vector
+    public readonly struct Vector
     {
         /// <summary>
         /// The X vector.

+ 1 - 1
src/Avalonia.Visuals/VisualTree/TransformedBounds.cs

@@ -8,7 +8,7 @@ namespace Avalonia.VisualTree
     /// <summary>
     /// Holds information about the bounds of a control, together with a transform and a clip.
     /// </summary>
-    public struct TransformedBounds
+    public readonly struct TransformedBounds
     {
         /// <summary>
         /// Initializes a new instance of the <see cref="TransformedBounds"/> struct.

+ 3 - 0
src/Directory.Build.props

@@ -0,0 +1,3 @@
+<Project>
+  <Import Project="..\build\SharedVersion.props" />
+</Project>

+ 1 - 22
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj

@@ -1,30 +1,9 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>TRACE;DEBUG;GTK3_PINVOKE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE;GTK3_PINVOKE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DefineConstants>$(DefineConstants);GTK3_PINVOKE</DefineConstants>
   </PropertyGroup>
-  <ItemGroup>
-    <Compile Include="..\..\Shared\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
-  </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />
     <ProjectReference Include="..\..\Avalonia.Controls\Avalonia.Controls.csproj" />

+ 0 - 2
src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs

@@ -5,8 +5,6 @@ using Avalonia.Platform;
 // General Information about an assembly is controlled through the following 
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
-[assembly: AssemblyTitle("Avalonia.Gtk3")]
-
 [assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 2, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]
 [assembly: ExportWindowingSubsystem(OperatingSystemType.Linux, 1, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]
 [assembly: ExportWindowingSubsystem(OperatingSystemType.OSX, 2, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]

+ 1 - 1
src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs

@@ -241,7 +241,7 @@ namespace Avalonia.Gtk3
             return true;
         }
 
-        void ConnectEvent(string name, Native.D.signal_onevent handler) 
+        protected void ConnectEvent(string name, Native.D.signal_onevent handler) 
             => Disposables.Add(Signal.Connect<Native.D.signal_onevent>(GtkWidget, name, handler));
         void Connect<T>(string name, T handler) => Disposables.Add(Signal.Connect(GtkWidget, name, handler));
 

+ 21 - 3
src/Gtk/Avalonia.Gtk3/WindowImpl.cs

@@ -1,18 +1,34 @@
 using System;
-using System.Linq.Expressions;
 using Avalonia.Controls;
 using Avalonia.Gtk3.Interop;
 using Avalonia.Platform;
-using System.Runtime.InteropServices;
 
 namespace Avalonia.Gtk3
 {
     class WindowImpl : WindowBaseImpl, IWindowImpl
     {
+        private WindowState _lastWindowState;
+
         public WindowImpl() : base(Native.GtkWindowNew(GtkWindowType.TopLevel))
         {
         }
 
+        protected unsafe override bool OnStateChanged(IntPtr w, IntPtr pev, IntPtr userData)
+        {
+            var windowStateEvent = (GdkEventWindowState*)pev;
+            var newWindowState = windowStateEvent->new_window_state;
+            var windowState = newWindowState.HasFlag(GdkWindowState.Iconified) ? WindowState.Minimized
+                : (newWindowState.HasFlag(GdkWindowState.Maximized) ? WindowState.Maximized : WindowState.Normal);
+
+            if (windowState != _lastWindowState)
+            {
+                _lastWindowState = windowState;
+                WindowStateChanged?.Invoke(windowState);
+            }
+
+            return base.OnStateChanged(w, pev, userData);
+        }
+
         public void SetTitle(string title)
         {
             using (var t = new Utf8Buffer(title))
@@ -43,7 +59,9 @@ namespace Avalonia.Gtk3
                 }
             }
         }
-        
+
+        public Action<WindowState> WindowStateChanged { get; set; }
+
         public IDisposable ShowDialog()
         {
             Native.GtkWindowSetModal(GtkWidget, true);

+ 1 - 1
src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj

@@ -10,5 +10,5 @@
     <ProjectReference Include="..\..\Avalonia.Interactivity\Avalonia.Interactivity.csproj" />
     <ProjectReference Include="..\..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
     <ProjectReference Include="..\..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
-  </ItemGroup>
+  </ItemGroup>  
 </Project>

+ 0 - 4
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@@ -3,7 +3,6 @@
     <TargetFramework>netstandard2.0</TargetFramework>
     <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
     <EnableDefaultItems>false</EnableDefaultItems>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
@@ -26,9 +25,6 @@
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
     <ItemGroup>
-        <Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
-            <Link>Properties\SharedAssemblyInfo.cs</Link>
-        </Compile>
         <Compile Include="AvaloniaXamlLoader.cs" />
         <Compile Include="Converters\CornerRadiusTypeConverter.cs" />
         <Compile Include="Converters\MatrixTypeConverter.cs" />

+ 0 - 1
src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs

@@ -5,7 +5,6 @@ using System.Reflection;
 using Avalonia.Metadata;
 using System.Runtime.CompilerServices;
 
-[assembly: AssemblyTitle("Avalonia.Markup.Xaml")]
 [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Data")]
 [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.MarkupExtensions")]
 [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Styling")]

+ 0 - 28
src/Markup/Avalonia.Markup/Avalonia.Markup.csproj

@@ -1,35 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Debug\Avalonia.Markup.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <DocumentationFile>bin\Release\Avalonia.Markup.xml</DocumentationFile>
-    <NoWarn>CS1591</NoWarn>
-    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-  </PropertyGroup>
-  <ItemGroup>
-    <Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
-      <Link>Properties\SharedAssemblyInfo.cs</Link>
-    </Compile>
-  </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />
     <ProjectReference Include="..\..\Avalonia.Controls\Avalonia.Controls.csproj" />

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません