Browse Source

Merge remote-tracking branch 'origin/master' into remote2

pull/1105/head
Nikita Tsukanov 9 years ago
parent
commit
151bfb9cec
  1. 8
      .gitignore
  2. 4
      .ncrunch/Avalonia.DotNetCoreRuntime.v3.ncrunchproject
  3. 4
      .ncrunch/Avalonia.Gtk3.v3.ncrunchproject
  4. 4
      .ncrunch/Avalonia.Win32.NetStandard.v3.ncrunchproject
  5. 5
      .ncrunch/ControlCatalog.NetCore.v3.ncrunchproject
  6. 3
      .travis.yml
  7. 4
      appveyor.yml
  8. 4
      build.cake
  9. 2
      build/Moq.props
  10. 19
      build/UnitTests.NetCore.targets
  11. 2
      build/XUnit.props
  12. 13
      docs/guidelines/build.md
  13. 61
      packages.cake
  14. 1
      samples/BindingTest/BindingTest.csproj
  15. 3
      samples/BindingTest/MainWindow.xaml
  16. 8
      samples/BindingTest/ViewModels/MainWindowViewModel.cs
  17. 20
      samples/BindingTest/ViewModels/NestedCommandViewModel.cs
  18. 2
      samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
  19. 2
      samples/ControlCatalog/ControlCatalog.csproj
  20. 53
      samples/ControlCatalog/Pages/ToolTipPage.xaml
  21. 1
      samples/RenderTest/MainWindow.xaml
  22. 132
      samples/RenderTest/Pages/DrawingPage.xaml
  23. 18
      samples/RenderTest/Pages/DrawingPage.xaml.cs
  24. 8
      samples/RenderTest/RenderTest.csproj
  25. 2
      src/Avalonia.Animation/Avalonia.Animation.csproj
  26. 3
      src/Avalonia.Base/Avalonia.Base.csproj
  27. 19
      src/Avalonia.Base/AvaloniaObject.cs
  28. 1
      src/Avalonia.Base/Data/BindingNotification.cs
  29. 53
      src/Avalonia.Base/Logging/LoggerExtensions.cs
  30. 2
      src/Avalonia.Base/PriorityBindingEntry.cs
  31. 9
      src/Avalonia.Base/PriorityValue.cs
  32. 23
      src/Avalonia.Base/Utilities/ExceptionUtilities.cs
  33. 15
      src/Avalonia.Controls/Application.cs
  34. 2
      src/Avalonia.Controls/Avalonia.Controls.csproj
  35. 24
      src/Avalonia.Controls/Button.cs
  36. 22
      src/Avalonia.Controls/Control.cs
  37. 59
      src/Avalonia.Controls/DrawingPresenter.cs
  38. 2
      src/Avalonia.Controls/DropDown.cs
  39. 14
      src/Avalonia.Controls/IControl.cs
  40. 6
      src/Avalonia.Controls/IGlobalDataTemplates.cs
  41. 2
      src/Avalonia.Controls/MenuItem.cs
  42. 26
      src/Avalonia.Controls/Primitives/Popup.cs
  43. 28
      src/Avalonia.Controls/Shapes/Shape.cs
  44. 24
      src/Avalonia.Controls/Templates/DataTemplateExtensions.cs
  45. 27
      src/Avalonia.Controls/Templates/IDataTemplateHost.cs
  46. 236
      src/Avalonia.Controls/ToolTip.cs
  47. 98
      src/Avalonia.Controls/ToolTipService.cs
  48. 2
      src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
  49. 2
      src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
  50. 2
      src/Avalonia.Diagnostics/DevTools.xaml.cs
  51. 2
      src/Avalonia.Diagnostics/Views/ControlDetailsView.cs
  52. 22
      src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj
  53. 13
      src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs
  54. 91
      src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
  55. 36
      src/Avalonia.DotNetFrameworkRuntime/Properties/AssemblyInfo.cs
  56. 3
      src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj
  57. 12
      src/Avalonia.HtmlRenderer/Compat/Api.cs
  58. 2
      src/Avalonia.Input/Avalonia.Input.csproj
  59. 2
      src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
  60. 20
      src/Avalonia.Interactivity/Interactive.cs
  61. 2
      src/Avalonia.Layout/Avalonia.Layout.csproj
  62. 5
      src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
  63. 27
      src/Avalonia.Logging.Serilog/Properties/AssemblyInfo.cs
  64. 3
      src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
  65. 24
      src/Avalonia.ReactiveUI/Properties/AssemblyInfo.cs
  66. 2
      src/Avalonia.Styling/Avalonia.Styling.csproj
  67. 12
      src/Avalonia.Styling/Styling/IStyleHost.cs
  68. 11
      src/Avalonia.Styling/Styling/StyleExtensions.cs
  69. 5
      src/Avalonia.Styling/Styling/Styler.cs
  70. 2
      src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
  71. 2
      src/Avalonia.Visuals/Avalonia.Visuals.csproj
  72. 29
      src/Avalonia.Visuals/Matrix.cs
  73. 9
      src/Avalonia.Visuals/Media/Drawing.cs
  74. 58
      src/Avalonia.Visuals/Media/DrawingGroup.cs
  75. 51
      src/Avalonia.Visuals/Media/EllipseGeometry.cs
  76. 43
      src/Avalonia.Visuals/Media/GeometryDrawing.cs
  77. 80
      src/Avalonia.Visuals/Media/LineGeometry.cs
  78. 3
      src/Avalonia.Visuals/Media/PathMarkupParser.cs
  79. 115
      src/Avalonia.Visuals/Media/PolylineGeometry.cs
  80. 51
      src/Avalonia.Visuals/Media/RectangleGeometry.cs
  81. 2
      src/Avalonia.Visuals/Point.cs
  82. 9
      src/Avalonia.Visuals/Points.cs
  83. 26
      src/Avalonia.Visuals/Rect.cs
  84. 2
      src/Avalonia.Visuals/RelativeRect.cs
  85. 63
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  86. 6
      src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs
  87. 3
      src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj
  88. 20
      src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs
  89. 3
      src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
  90. 13
      src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs
  91. 3
      src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
  92. 16
      src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs
  93. 2
      src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs
  94. 25
      src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs
  95. 2
      src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
  96. 1
      src/Linux/Avalonia.LinuxFramebuffer/NativeUnsafeMethods.cs
  97. 5
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  98. 23
      src/Markup/Avalonia.Markup.Xaml/Converters/MatrixTypeConverter.cs
  99. 23
      src/Markup/Avalonia.Markup.Xaml/Converters/RectTypeConverter.cs
  100. 2
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaDefaultTypeConverters.cs

8
.gitignore

@ -108,7 +108,7 @@ AppPackages/
# NCrunch # NCrunch
_NCrunch_*/ _NCrunch_*/
*.ncrunchsolution.user *.ncrunchsolution.user
nCrunchTemp_*/ nCrunchTemp_*
# Others # Others
sql/ sql/
@ -159,6 +159,12 @@ $RECYCLE.BIN/
*.userprefs *.userprefs
*.nugetreferenceswitcher *.nugetreferenceswitcher
#################
## Rider
#################
.idea
################# #################
## Cake ## Cake
################# #################

4
.ncrunch/Avalonia.DotNetCoreRuntime.v3.ncrunchproject

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

4
.ncrunch/Avalonia.Gtk3.v3.ncrunchproject

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

4
.ncrunch/Avalonia.Win32.NetStandard.v3.ncrunchproject

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

5
.ncrunch/ControlCatalog.NetCore.v3.ncrunchproject

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

3
.travis.yml

@ -3,13 +3,14 @@ os:
- linux - linux
- osx - osx
dist: trusty dist: trusty
osx_image: xcode8.3
env: env:
global: global:
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 - DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
- DOTNET_CLI_TELEMETRY_OPTOUT=1 - DOTNET_CLI_TELEMETRY_OPTOUT=1
mono: mono:
- latest - latest
dotnet: 1.0.1 dotnet: 2.0.0
script: script:
- ./build.sh --target "Travis" --platform "Mono" --configuration "Release" - ./build.sh --target "Travis" --platform "Mono" --configuration "Release"
notifications: notifications:

4
appveyor.yml

@ -17,9 +17,9 @@ init:
- ps: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")} - ps: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")}
install: install:
- if not exist gtk-sharp-2.12.26.msi appveyor DownloadFile http://download.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.26.msi - if not exist gtk-sharp-2.12.26.msi appveyor DownloadFile http://download.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.26.msi
- if not exist dotnet-1.0.1.exe appveyor DownloadFile https://go.microsoft.com/fwlink/?linkid=843448 -FileName "dotnet-1.0.1.exe" - if not exist dotnet-2.0.0.exe appveyor DownloadFile https://download.microsoft.com/download/0/F/D/0FD852A4-7EA1-4E2A-983A-0484AC19B92C/dotnet-sdk-2.0.0-win-x64.exe -FileName "dotnet-2.0.0.exe"
- ps: Start-Process -FilePath "msiexec" -ArgumentList "/i gtk-sharp-2.12.26.msi /quiet /qn /norestart" -Wait - ps: Start-Process -FilePath "msiexec" -ArgumentList "/i gtk-sharp-2.12.26.msi /quiet /qn /norestart" -Wait
- ps: Start-Process -FilePath "dotnet-1.0.1.exe" -ArgumentList "/quiet" -Wait - ps: Start-Process -FilePath "dotnet-2.0.0.exe" -ArgumentList "/quiet" -Wait
- cmd: set PATH=%programfiles(x86)%\GtkSharp\2.12\bin\;%PATH% - cmd: set PATH=%programfiles(x86)%\GtkSharp\2.12\bin\;%PATH%
before_build: before_build:
- git submodule update --init - git submodule update --init

4
build.cake

@ -6,7 +6,7 @@
#addin "nuget:?package=NuGet.Core&version=2.12.0" #addin "nuget:?package=NuGet.Core&version=2.12.0"
#tool "nuget:?package=xunit.runner.console&version=2.2.0" #tool "nuget:?package=xunit.runner.console&version=2.2.0"
#tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease" #tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease"
#tool "JetBrains.ReSharper.CommandLineTools" #tool "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2017.1.20170613.162720"
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// TOOLS // TOOLS
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -162,7 +162,7 @@ void RunCoreTest(string project, Parameters parameters, bool coreOnly = false)
project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj"); project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj");
Information("Running tests from " + project); Information("Running tests from " + project);
DotNetCoreRestore(project); DotNetCoreRestore(project);
var frameworks = new List<string>(){"netcoreapp1.1"}; var frameworks = new List<string>(){"netcoreapp2.0"};
if(parameters.IsRunningOnWindows) if(parameters.IsRunningOnWindows)
frameworks.Add("net461"); frameworks.Add("net461");
foreach(var fw in frameworks) foreach(var fw in frameworks)

2
build/Moq.props

@ -1,5 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="Moq" Version="4.7.25" /> <PackageReference Include="Moq" Version="4.7.99" />
</ItemGroup> </ItemGroup>
</Project> </Project>

19
build/UnitTests.NetCore.targets

@ -3,25 +3,6 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup> </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>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</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>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Threading.Thread" Version="4.3.0" /> <PackageReference Include="System.Threading.Thread" Version="4.3.0" />
</ItemGroup> </ItemGroup>

2
build/XUnit.props

@ -9,7 +9,7 @@
<PackageReference Include="xunit.runner.console" Version="2.2.0" /> <PackageReference Include="xunit.runner.console" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp1.1'"> <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>

13
docs/guidelines/build.md

@ -80,10 +80,11 @@ mono ./samples/ControlCatalog.Desktop/bin/Debug/ControlCatalog.Desktop.exe
### Building Avalonia in MonoDevelop ### Building Avalonia in MonoDevelop
Unless you have a very current version of monodevelop (6.1.x or newer), it is necessary to manually Flatpak version will *NOT* work. Version from https://github.com/cra0zy/monodevelop-run-installer/ might work if you are very lucky. Make sure that you have the latest version of Mono (from alpha update channel) and .NET Core SDK. Make sure to follow `FrameworkPathOverride` workaround from https://github.com/dotnet/sdk/issues/335
restore the Nuget depdendencies as [mentioned above](#restore-nuget-packages). You must then
disable MonoDevelop's inbuilt NuGet package manager add-in by going to `Tools -> Add-in Manager` or ### Building and running Avalonia in Rider
it will complain that a newer version of NuGet is needed.
For Linux/OSX you'll probably need to apply workaround from https://github.com/dotnet/sdk/issues/335
Just add `export FrameworkPathOverride=/usr/lib/mono/4.6.1-api` (or `export FrameworkPathOverride=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api` for OSX)
Finally, select the `Debug | Mono` or `Release | Mono` build configuration and you should be good to
go!

61
packages.cake

@ -43,7 +43,6 @@ public class Packages
} }
} }
//new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp1.0", Version = "4.3.0" },
public Packages(ICakeContext context, Parameters parameters) public Packages(ICakeContext context, Parameters parameters)
{ {
// NUGET NUSPECS // NUGET NUSPECS
@ -186,12 +185,12 @@ public class Packages
}; };
var coreLibrariesFiles = coreLibraries.Select((lib) => { var coreLibrariesFiles = coreLibraries.Select((lib) => {
return (FilePath)context.File(lib[0] + lib[1] + "/bin/" + parameters.DirSuffix + "/netstandard1.3/" + lib[1] + lib[2]); return (FilePath)context.File(lib[0] + lib[1] + "/bin/" + parameters.DirSuffix + "/netstandard2.0/" + lib[1] + lib[2]);
}).ToList(); }).ToList();
var coreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => { var coreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
return new NuSpecContent { return new NuSpecContent {
Source = file.FullPath, Target = "lib/netstandard1.3" Source = file.FullPath, Target = "lib/netstandard2.0"
}; };
}); });
@ -203,14 +202,14 @@ public class Packages
var netcoreappCoreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => { var netcoreappCoreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
return new NuSpecContent { return new NuSpecContent {
Source = file.FullPath, Target = "lib/netcoreapp1.0" Source = file.FullPath, Target = "lib/netcoreapp2.0"
}; };
}); });
var net45RuntimePlatformExtensions = new [] {".xml", ".dll"}; var net45RuntimePlatformExtensions = new [] {".xml", ".dll"};
var net45RuntimePlatform = net45RuntimePlatformExtensions.Select(libSuffix => { var net45RuntimePlatform = net45RuntimePlatformExtensions.Select(libSuffix => {
return new NuSpecContent { return new NuSpecContent {
Source = ((FilePath)context.File("./src/Avalonia.DotNetFrameworkRuntime/bin/" + parameters.DirSuffix + "/Avalonia.DotNetFrameworkRuntime" + libSuffix)).FullPath, Source = ((FilePath)context.File("./src/Avalonia.DotNetFrameworkRuntime/bin/" + parameters.DirSuffix + "/net461/Avalonia.DotNetFrameworkRuntime" + libSuffix)).FullPath,
Target = "lib/net45" Target = "lib/net45"
}; };
}); });
@ -218,8 +217,8 @@ public class Packages
var netCoreRuntimePlatformExtensions = new [] {".xml", ".dll"}; var netCoreRuntimePlatformExtensions = new [] {".xml", ".dll"};
var netCoreRuntimePlatform = netCoreRuntimePlatformExtensions.Select(libSuffix => { var netCoreRuntimePlatform = netCoreRuntimePlatformExtensions.Select(libSuffix => {
return new NuSpecContent { return new NuSpecContent {
Source = ((FilePath)context.File("./src/Avalonia.DotNetCoreRuntime/bin/" + parameters.DirSuffix + "/netcoreapp1.0/Avalonia.DotNetCoreRuntime" + libSuffix)).FullPath, Source = ((FilePath)context.File("./src/Avalonia.DotNetCoreRuntime/bin/" + parameters.DirSuffix + "/netcoreapp2.0/Avalonia.DotNetCoreRuntime" + libSuffix)).FullPath,
Target = "lib/netcoreapp1.0" Target = "lib/netcoreapp2.0"
}; };
}); });
@ -238,15 +237,15 @@ public class Packages
new NuSpecDependency() { Id = "Sprache", Version = SpracheVersion }, new NuSpecDependency() { Id = "Sprache", Version = SpracheVersion },
new NuSpecDependency() { Id = "System.Reactive", Version = SystemReactiveVersion }, new NuSpecDependency() { Id = "System.Reactive", Version = SystemReactiveVersion },
//.NET Core //.NET Core
new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp1.0", Version = "4.3.0" }, new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp2.0", Version = "4.3.0" },
new NuSpecDependency() { Id = "Microsoft.Extensions.DependencyModel", TargetFramework = "netcoreapp1.0", Version = "1.1.0" }, new NuSpecDependency() { Id = "Microsoft.Extensions.DependencyModel", TargetFramework = "netcoreapp2.0", Version = "1.1.0" },
new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp1.0", Version = "1.6.0" }, new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp2.0", Version = "1.6.0" },
new NuSpecDependency() { Id = "Splat", TargetFramework = "netcoreapp1.0", Version = SplatVersion }, new NuSpecDependency() { Id = "Splat", TargetFramework = "netcoreapp2.0", Version = SplatVersion },
new NuSpecDependency() { Id = "Serilog", TargetFramework = "netcoreapp1.0", Version = SerilogVersion }, new NuSpecDependency() { Id = "Serilog", TargetFramework = "netcoreapp2.0", Version = SerilogVersion },
new NuSpecDependency() { Id = "Sprache", TargetFramework = "netcoreapp1.0", Version = SpracheVersion }, new NuSpecDependency() { Id = "Sprache", TargetFramework = "netcoreapp2.0", Version = SpracheVersion },
new NuSpecDependency() { Id = "System.Reactive", TargetFramework = "netcoreapp1.0", Version = SystemReactiveVersion }, new NuSpecDependency() { Id = "System.Reactive", TargetFramework = "netcoreapp2.0", Version = SystemReactiveVersion },
} }
.Deps(new string[]{null, "netcoreapp1.0"}, .Deps(new string[]{null, "netcoreapp2.0"},
"System.ValueTuple", "System.ComponentModel.TypeConverter", "System.ComponentModel.Primitives", "System.ValueTuple", "System.ComponentModel.TypeConverter", "System.ComponentModel.Primitives",
"System.Runtime.Serialization.Primitives", "System.Xml.XmlDocument", "System.Xml.ReaderWriter") "System.Runtime.Serialization.Primitives", "System.Xml.XmlDocument", "System.Xml.ReaderWriter")
.ToArray(), .ToArray(),
@ -269,9 +268,9 @@ public class Packages
}, },
Files = new [] Files = new []
{ {
new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/netstandard1.3" } new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/netstandard2.0" }
}, },
BasePath = context.Directory("./src/Avalonia.HtmlRenderer/bin/" + parameters.DirSuffix + "/netstandard1.3"), BasePath = context.Directory("./src/Avalonia.HtmlRenderer/bin/" + parameters.DirSuffix + "/netstandard2.0"),
OutputDirectory = parameters.NugetRoot OutputDirectory = parameters.NugetRoot
} }
}; };
@ -331,7 +330,7 @@ public class Packages
Files = new [] Files = new []
{ {
new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/Avalonia.Win32.dll", Target = "lib/net45" }, new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/Avalonia.Win32.dll", Target = "lib/net45" },
new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/netstandard1.3/Avalonia.Win32.dll", Target = "lib/netstandard1.3" } new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/netstandard2.0/Avalonia.Win32.dll", Target = "lib/netstandard2.0" }
}, },
BasePath = context.Directory("./src/Windows"), BasePath = context.Directory("./src/Windows"),
OutputDirectory = parameters.NugetRoot OutputDirectory = parameters.NugetRoot
@ -352,9 +351,9 @@ public class Packages
}, },
Files = new [] Files = new []
{ {
new NuSpecContent { Source = "Avalonia.Direct2D1.dll", Target = "lib/netstandard1.3" } new NuSpecContent { Source = "Avalonia.Direct2D1.dll", Target = "lib/netstandard2.0" }
}, },
BasePath = context.Directory("./src/Windows/Avalonia.Direct2D1/bin/" + parameters.DirSuffix + "/netstandard1.3"), BasePath = context.Directory("./src/Windows/Avalonia.Direct2D1/bin/" + parameters.DirSuffix + "/netstandard2.0"),
OutputDirectory = parameters.NugetRoot OutputDirectory = parameters.NugetRoot
}, },
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -386,9 +385,9 @@ public class Packages
}, },
Files = new [] Files = new []
{ {
new NuSpecContent { Source = "Avalonia.Gtk3.dll", Target = "lib/netstandard1.3" } new NuSpecContent { Source = "Avalonia.Gtk3.dll", Target = "lib/netstandard2.0" }
}, },
BasePath = context.Directory("./src/Gtk/Avalonia.Gtk3/bin/" + parameters.DirSuffix + "/netstandard1.3"), BasePath = context.Directory("./src/Gtk/Avalonia.Gtk3/bin/" + parameters.DirSuffix + "/netstandard2.0"),
OutputDirectory = parameters.NugetRoot OutputDirectory = parameters.NugetRoot
}, },
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -418,18 +417,18 @@ public class Packages
{ {
new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version }, new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version },
new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }, new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion },
new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version, TargetFramework="netcoreapp1.1" }, new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version, TargetFramework="netcoreapp2.0" },
new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion, TargetFramework="netcoreapp1.1" }, new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion, TargetFramework="netcoreapp2.0" },
new NuSpecDependency() { Id = "Avalonia.Skia.Linux.Natives", Version = SkiaSharpLinuxVersion, TargetFramework="netcoreapp1.1" }, new NuSpecDependency() { Id = "Avalonia.Skia.Linux.Natives", Version = SkiaSharpLinuxVersion, TargetFramework="netcoreapp2.0" },
new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version, TargetFramework="net461" }, new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version, TargetFramework="net461" },
new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion, TargetFramework="net461" }, new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion, TargetFramework="net461" },
new NuSpecDependency() { Id = "Avalonia.Skia.Linux.Natives", Version = SkiaSharpLinuxVersion, TargetFramework="net461" } new NuSpecDependency() { Id = "Avalonia.Skia.Linux.Natives", Version = SkiaSharpLinuxVersion, TargetFramework="net461" }
}, },
Files = new [] Files = new []
{ {
new NuSpecContent { Source = "Avalonia.Skia.dll", Target = "lib/netstandard1.3" } new NuSpecContent { Source = "Avalonia.Skia.dll", Target = "lib/netstandard2.0" }
}, },
BasePath = context.Directory("./src/Skia/Avalonia.Skia/bin/" + parameters.DirSuffix + "/netstandard1.3"), BasePath = context.Directory("./src/Skia/Avalonia.Skia/bin/" + parameters.DirSuffix + "/netstandard2.0"),
OutputDirectory = parameters.NugetRoot OutputDirectory = parameters.NugetRoot
}, },
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -448,9 +447,9 @@ public class Packages
new NuSpecDependency() { Id = "Avalonia.Skia", TargetFramework="net45", Version = parameters.Version }, new NuSpecDependency() { Id = "Avalonia.Skia", TargetFramework="net45", Version = parameters.Version },
new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="net45", Version = parameters.Version }, new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="net45", Version = parameters.Version },
//.NET Core //.NET Core
new NuSpecDependency() { Id = "Avalonia.Win32", TargetFramework="netcoreapp1.0", Version = parameters.Version }, new NuSpecDependency() { Id = "Avalonia.Win32", TargetFramework="netcoreapp2.0", Version = parameters.Version },
new NuSpecDependency() { Id = "Avalonia.Skia", TargetFramework="netcoreapp1.0", Version = parameters.Version }, new NuSpecDependency() { Id = "Avalonia.Skia", TargetFramework="netcoreapp2.0", Version = parameters.Version },
new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="netcoreapp1.0", Version = parameters.Version } new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="netcoreapp2.0", Version = parameters.Version }
}, },
Files = new NuSpecContent[] Files = new NuSpecContent[]
{ {
@ -488,7 +487,7 @@ public class Packages
}, },
Files = new [] Files = new []
{ {
new NuSpecContent { Source = "Avalonia.LinuxFramebuffer/bin/" + parameters.DirSuffix + "/netstandard1.3/Avalonia.LinuxFramebuffer.dll", Target = "lib/netstandard1.3" } new NuSpecContent { Source = "Avalonia.LinuxFramebuffer/bin/" + parameters.DirSuffix + "/netstandard2.0/Avalonia.LinuxFramebuffer.dll", Target = "lib/netstandard2.0" }
}, },
BasePath = context.Directory("./src/Linux/"), BasePath = context.Directory("./src/Linux/"),
OutputDirectory = parameters.NugetRoot OutputDirectory = parameters.NugetRoot

1
samples/BindingTest/BindingTest.csproj

@ -66,6 +66,7 @@
<Compile Include="ViewModels\IndeiErrorViewModel.cs" /> <Compile Include="ViewModels\IndeiErrorViewModel.cs" />
<Compile Include="ViewModels\ExceptionErrorViewModel.cs" /> <Compile Include="ViewModels\ExceptionErrorViewModel.cs" />
<Compile Include="ViewModels\MainWindowViewModel.cs" /> <Compile Include="ViewModels\MainWindowViewModel.cs" />
<Compile Include="ViewModels\NestedCommandViewModel.cs" />
<Compile Include="ViewModels\TestItem.cs" /> <Compile Include="ViewModels\TestItem.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

3
samples/BindingTest/MainWindow.xaml

@ -97,8 +97,9 @@
<Button Content="Button" Command="{Binding StringValueCommand}" CommandParameter="Button"/> <Button Content="Button" Command="{Binding StringValueCommand}" CommandParameter="Button"/>
<ToggleButton Content="ToggleButton" IsChecked="{Binding BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="ToggleButton"/> <ToggleButton Content="ToggleButton" IsChecked="{Binding BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="ToggleButton"/>
<CheckBox Content="CheckBox" IsChecked="{Binding !BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="CheckBox"/> <CheckBox Content="CheckBox" IsChecked="{Binding !BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="CheckBox"/>
<RadioButton Content="RadionButton" IsChecked="{Binding !!BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="RadioButton"/> <RadioButton Content="Radio Button" IsChecked="{Binding !!BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="RadioButton"/>
<TextBox Text="{Binding Path=StringValue}"/> <TextBox Text="{Binding Path=StringValue}"/>
<Button Content="Nested View Model Button" Name="NestedTest" Command="{Binding NestedModel.Command}" />
</StackPanel> </StackPanel>
</TabItem> </TabItem>
</TabControl> </TabControl>

8
samples/BindingTest/ViewModels/MainWindowViewModel.cs

@ -15,6 +15,7 @@ namespace BindingTest.ViewModels
private string _stringValue = "Simple Binding"; private string _stringValue = "Simple Binding";
private bool _booleanFlag = false; private bool _booleanFlag = false;
private string _currentTime; private string _currentTime;
private NestedCommandViewModel _nested;
public MainWindowViewModel() public MainWindowViewModel()
{ {
@ -39,6 +40,7 @@ namespace BindingTest.ViewModels
{ {
BooleanFlag = !BooleanFlag; BooleanFlag = !BooleanFlag;
StringValue = param.ToString(); StringValue = param.ToString();
NestedModel = _nested ?? new NestedCommandViewModel();
}); });
Task.Run(() => Task.Run(() =>
@ -94,5 +96,11 @@ namespace BindingTest.ViewModels
public DataAnnotationsErrorViewModel DataAnnotationsValidation { get; } = new DataAnnotationsErrorViewModel(); public DataAnnotationsErrorViewModel DataAnnotationsValidation { get; } = new DataAnnotationsErrorViewModel();
public ExceptionErrorViewModel ExceptionDataValidation { get; } = new ExceptionErrorViewModel(); public ExceptionErrorViewModel ExceptionDataValidation { get; } = new ExceptionErrorViewModel();
public IndeiErrorViewModel IndeiDataValidation { get; } = new IndeiErrorViewModel(); public IndeiErrorViewModel IndeiDataValidation { get; } = new IndeiErrorViewModel();
public NestedCommandViewModel NestedModel
{
get { return _nested; }
private set { this.RaiseAndSetIfChanged(ref _nested, value); }
}
} }
} }

20
samples/BindingTest/ViewModels/NestedCommandViewModel.cs

@ -0,0 +1,20 @@
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace BindingTest.ViewModels
{
public class NestedCommandViewModel : ReactiveObject
{
public NestedCommandViewModel()
{
Command = ReactiveCommand.Create();
}
public ICommand Command { get; }
}
}

2
samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework> <TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

2
samples/ControlCatalog/ControlCatalog.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems> <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>

53
samples/ControlCatalog/Pages/ToolTipPage.xaml

@ -1,22 +1,41 @@
<UserControl xmlns="https://github.com/avaloniaui"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4"> <StackPanel Orientation="Vertical"
<TextBlock Classes="h1">ToolTip</TextBlock> Gap="4">
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock> <TextBlock Classes="h1">ToolTip</TextBlock>
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock>
<StackPanel Orientation="Horizontal" <Grid RowDefinitions="Auto,Auto"
ColumnDefinitions="Auto,Auto"
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Center" HorizontalAlignment="Center">
Gap="16"> <Border Grid.Column="0"
<Border Background="{StyleResource ThemeAccentBrush}" Grid.Row="1"
Padding="48,48,48,48"> Background="{StyleResource ThemeAccentBrush}"
<ToolTip.Tip> Margin="5"
<StackPanel> Padding="50"
<TextBlock Classes="h1">ToolTip</TextBlock> ToolTip.Tip="This is a ToolTip">
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock> <TextBlock>Hover Here</TextBlock>
</StackPanel> </Border>
</ToolTip.Tip> <CheckBox Grid.Column="1"
<TextBlock>Hover Here</TextBlock> Margin="5"
</Border> Grid.Row="0"
IsChecked="{Binding ElementName=Border, Path=(ToolTip.IsOpen)}"
Content="ToolTip Open" />
<Border Name="Border"
Grid.Column="1"
Grid.Row="1"
Background="{StyleResource ThemeAccentBrush}"
Margin="5"
Padding="50"
ToolTip.Placement="Bottom">
<ToolTip.Tip>
<StackPanel>
<TextBlock Classes="h1">ToolTip</TextBlock>
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock>
</StackPanel>
</ToolTip.Tip>
<TextBlock>ToolTip bottom placement</TextBlock>
</Border>
</Grid>
</StackPanel> </StackPanel>
</StackPanel>
</UserControl> </UserControl>

1
samples/RenderTest/MainWindow.xaml

@ -27,6 +27,7 @@
</TabControl.Transition> </TabControl.Transition>
<TabItem Header="Animations"><pages:AnimationsPage/></TabItem> <TabItem Header="Animations"><pages:AnimationsPage/></TabItem>
<TabItem Header="Clipping"><pages:ClippingPage/></TabItem> <TabItem Header="Clipping"><pages:ClippingPage/></TabItem>
<TabItem Header="Drawing"><pages:DrawingPage/></TabItem>
</TabControl> </TabControl>
</DockPanel> </DockPanel>
</Window> </Window>

132
samples/RenderTest/Pages/DrawingPage.xaml

@ -0,0 +1,132 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Styles>
<Style>
<Style.Resources>
<DrawingGroup x:Key="Bulb">
<DrawingGroup.Transform>
<MatrixTransform Matrix="1,0,0,1,0,-1028.4" />
</DrawingGroup.Transform>
<DrawingGroup>
<DrawingGroup.Transform>
<MatrixTransform Matrix="1,0,0,1.25,-10,1031.4" />
</DrawingGroup.Transform>
<GeometryDrawing Brush="#FF7F8C8D"
Geometry="F1 M24,14 A2,2,0,1,1,20,14 A2,2,0,1,1,24,14 z" />
</DrawingGroup>
<GeometryDrawing Brush="#FFF39C12"
Geometry="F1 M12,1030.4 C8.134,1030.4 5,1033.6 5,1037.6 5,1040.7 8.125,1043.5 9,1045.4 9.875,1047.2 9,1050.4 9,1050.4 L12,1049.9 15,1050.4 C15,1050.4 14.125,1047.2 15,1045.4 15.875,1043.5 19,1040.7 19,1037.6 19,1033.6 15.866,1030.4 12,1030.4 z" />
<GeometryDrawing Brush="#FFF1C40F"
Geometry="F1 M12,1030.4 C15.866,1030.4 19,1033.6 19,1037.6 19,1040.7 15.875,1043.5 15,1045.4 14.125,1047.2 15,1050.4 15,1050.4 L12,1049.9 12,1030.4 z" />
<GeometryDrawing Brush="#FFE67E22"
Geometry="F1 M9,1036.4 L8,1037.4 12,1049.4 16,1037.4 15,1036.4 14,1037.4 13,1036.4 12,1037.4 11,1036.4 10,1037.4 9,1036.4 z M9,1037.4 L10,1038.4 10.5,1037.9 11,1037.4 11.5,1037.9 12,1038.4 12.5,1037.9 13,1037.4 13.5,1037.9 14,1038.4 15,1037.4 15.438,1037.8 12,1048.1 8.5625,1037.8 9,1037.4 z" />
<DrawingGroup>
<DrawingGroup.Transform>
<MatrixTransform Matrix="1,0,0,1,9,1045.4" />
</DrawingGroup.Transform>
<GeometryDrawing Brush="#FFBDC3C7">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,6,5" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
<GeometryDrawing Brush="#FF95A5A6"
Geometry="F1 M9,1045.4 L9,1050.4 12,1050.4 12,1049.4 15,1049.4 15,1048.4 12,1048.4 12,1047.4 15,1047.4 15,1046.4 12,1046.4 12,1045.4 9,1045.4 z" />
<GeometryDrawing Brush="#FF7F8C8D"
Geometry="F1 M9,1046.4 L9,1047.4 12,1047.4 12,1046.4 9,1046.4 z M9,1048.4 L9,1049.4 12,1049.4 12,1048.4 9,1048.4 z" />
</DrawingGroup>
</Style.Resources>
</Style>
</UserControl.Styles>
<Grid RowDefinitions="Auto,Auto,Auto"
ColumnDefinitions="Auto,Auto,Auto,Auto">
<TextBlock Text="None"
Margin="3" />
<Border Grid.Column="0"
Grid.Row="1"
VerticalAlignment="Top"
HorizontalAlignment="Left"
BorderThickness="1"
BorderBrush="Gray"
Margin="5">
<DrawingPresenter Drawing="{StyleResource Bulb}" />
</Border>
<TextBlock Text="Fill"
Margin="3"
Grid.Column="1" />
<Border Grid.Column="1"
Grid.Row="1"
VerticalAlignment="Top"
HorizontalAlignment="Left"
BorderThickness="1"
BorderBrush="Gray"
Margin="5">
<DrawingPresenter Drawing="{StyleResource Bulb}"
Width="100"
Height="50"
Stretch="Fill" />
</Border>
<TextBlock Text="Uniform"
Margin="3"
Grid.Column="2" />
<Border Grid.Column="2"
Grid.Row="1"
VerticalAlignment="Top"
HorizontalAlignment="Left"
BorderThickness="1"
BorderBrush="Gray"
Margin="5">
<DrawingPresenter Drawing="{StyleResource Bulb}"
Width="100"
Height="50"
Stretch="Uniform" />
</Border>
<TextBlock Text="UniformToFill"
Margin="3"
Grid.Column="3" />
<Border Grid.Column="3"
Grid.Row="1"
VerticalAlignment="Top"
HorizontalAlignment="Left"
BorderThickness="1"
BorderBrush="Gray"
Margin="5">
<DrawingPresenter Drawing="{StyleResource Bulb}"
Width="100"
Height="50"
Stretch="UniformToFill" />
</Border>
<!-- For comparison -->
<Ellipse Grid.Row="2"
Grid.Column="0"
Width="100"
Height="50"
Stretch="None"
Fill="Blue"
Margin="5"/>
<Ellipse Grid.Row="2"
Grid.Column="1"
Width="100"
Height="50"
Stretch="Fill"
Fill="Blue"
Margin="5" />
<Ellipse Grid.Row="2"
Grid.Column="2"
Width="100"
Height="50"
Stretch="Uniform"
Fill="Blue"
Margin="5" />
<Ellipse Grid.Row="2"
Grid.Column="3"
Width="100"
Height="50"
Stretch="UniformToFill"
Fill="Blue"
Margin="5" />
</Grid>
</UserControl>

18
samples/RenderTest/Pages/DrawingPage.xaml.cs

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

8
samples/RenderTest/RenderTest.csproj

@ -51,6 +51,9 @@
<Compile Include="App.xaml.cs"> <Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon> <DependentUpon>App.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Pages\DrawingPage.xaml.cs">
<DependentUpon>DrawingPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\ClippingPage.xaml.cs"> <Compile Include="Pages\ClippingPage.xaml.cs">
<DependentUpon>ClippingPage.xaml</DependentUpon> <DependentUpon>ClippingPage.xaml</DependentUpon>
</Compile> </Compile>
@ -178,6 +181,11 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Pages\DrawingPage.xaml">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\build\Serilog.props" /> <Import Project="..\..\build\Serilog.props" />
<Import Project="..\..\build\Serilog.Sinks.Trace.props" /> <Import Project="..\..\build\Serilog.Sinks.Trace.props" />

2
src/Avalonia.Animation/Avalonia.Animation.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

3
src/Avalonia.Base/Avalonia.Base.csproj

@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RootNamespace>Avalonia</RootNamespace>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>

19
src/Avalonia.Base/AvaloniaObject.cs

@ -665,24 +665,11 @@ namespace Avalonia
if (notification != null) if (notification != null)
{ {
if (notification.ErrorType == BindingErrorType.Error) notification.LogIfError(this, property);
{ value = notification.Value;
Logger.Error(
LogArea.Binding,
this,
"Error in binding to {Target}.{Property}: {Message}",
this,
property,
ExceptionUtilities.GetMessage(notification.Error));
}
if (notification.HasValue)
{
value = notification.Value;
}
} }
if (notification == null || notification.HasValue) if (notification == null || notification.ErrorType == BindingErrorType.Error || notification.HasValue)
{ {
var metadata = (IDirectPropertyMetadata)property.GetMetadata(GetType()); var metadata = (IDirectPropertyMetadata)property.GetMetadata(GetType());
var accessor = (IDirectPropertyAccessor)GetRegistered(property); var accessor = (IDirectPropertyAccessor)GetRegistered(property);

1
src/Avalonia.Base/Data/BindingNotification.cs

@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System; using System;
using Avalonia.Logging;
namespace Avalonia.Data namespace Avalonia.Data
{ {

53
src/Avalonia.Base/Logging/LoggerExtensions.cs

@ -0,0 +1,53 @@
using System;
using Avalonia.Data;
namespace Avalonia.Logging
{
internal static class LoggerExtensions
{
public static void LogIfError(
this BindingNotification notification,
object source,
AvaloniaProperty property)
{
if (notification.ErrorType == BindingErrorType.Error)
{
if (notification.Error is AggregateException aggregate)
{
foreach (var inner in aggregate.InnerExceptions)
{
LogError(source, property, inner);
}
}
else
{
LogError(source, property, notification.Error);
}
}
}
private static void LogError(object source, AvaloniaProperty property, Exception e)
{
var level = LogEventLevel.Warning;
if (e is BindingChainException b &&
!string.IsNullOrEmpty(b.Expression) &&
string.IsNullOrEmpty(b.ExpressionErrorPoint))
{
// The error occurred at the root of the binding chain: it's possible that the
// DataContext isn't set up yet, so log at Information level instead of Warning
// to prevent spewing hundreds of errors.
level = LogEventLevel.Information;
}
Logger.Log(
level,
LogArea.Binding,
source,
"Error in binding to {Target}.{Property}: {Message}",
source,
property,
e.Message);
}
}
}

2
src/Avalonia.Base/PriorityBindingEntry.cs

@ -98,7 +98,7 @@ namespace Avalonia
if (notification != null) if (notification != null)
{ {
if (notification.HasValue) if (notification.HasValue || notification.ErrorType == BindingErrorType.Error)
{ {
Value = notification.Value; Value = notification.Value;
_owner.Changed(this); _owner.Changed(this);

9
src/Avalonia.Base/PriorityValue.cs

@ -189,14 +189,7 @@ namespace Avalonia
/// <param name="error">The binding error.</param> /// <param name="error">The binding error.</param>
public void LevelError(PriorityLevel level, BindingNotification error) public void LevelError(PriorityLevel level, BindingNotification error)
{ {
Logger.Log( error.LogIfError(Owner, Property);
LogEventLevel.Error,
LogArea.Binding,
Owner,
"Error in binding to {Target}.{Property}: {Message}",
Owner,
Property,
error.Error.Message);
} }
/// <summary> /// <summary>

23
src/Avalonia.Base/Utilities/ExceptionUtilities.cs

@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Utilities
{
internal static class ExceptionUtilities
{
public static string GetMessage(Exception e)
{
var aggregate = e as AggregateException;
if (aggregate != null)
{
return string.Join(" | ", aggregate.InnerExceptions.Select(x => x.Message));
}
return e.Message;
}
}
}

15
src/Avalonia.Controls/Application.cs

@ -39,6 +39,7 @@ namespace Avalonia
private readonly Lazy<IClipboard> _clipboard = private readonly Lazy<IClipboard> _clipboard =
new Lazy<IClipboard>(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard))); new Lazy<IClipboard>(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard)));
private readonly Styler _styler = new Styler(); private readonly Styler _styler = new Styler();
private Styles _styles;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Application"/> class. /// Initializes a new instance of the <see cref="Application"/> class.
@ -65,11 +66,7 @@ namespace Avalonia
/// <value> /// <value>
/// The application's global data templates. /// The application's global data templates.
/// </value> /// </value>
public DataTemplates DataTemplates public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
{
get { return _dataTemplates ?? (_dataTemplates = new DataTemplates()); }
set { _dataTemplates = value; }
}
/// <summary> /// <summary>
/// Gets the application's focus manager. /// Gets the application's focus manager.
@ -109,13 +106,19 @@ namespace Avalonia
/// <remarks> /// <remarks>
/// Global styles apply to all windows in the application. /// Global styles apply to all windows in the application.
/// </remarks> /// </remarks>
public Styles Styles { get; } = new Styles(); public Styles Styles => _styles ?? (_styles = new Styles());
/// <inheritdoc/>
bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
/// <summary> /// <summary>
/// Gets the styling parent of the application, which is null. /// Gets the styling parent of the application, which is null.
/// </summary> /// </summary>
IStyleHost IStyleHost.StylingParent => null; IStyleHost IStyleHost.StylingParent => null;
/// <inheritdoc/>
bool IStyleHost.IsStylesInitialized => _styles != null;
/// <summary> /// <summary>
/// Initializes the application by loading XAML etc. /// Initializes the application by loading XAML etc.
/// </summary> /// </summary>

2
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

24
src/Avalonia.Controls/Button.cs

@ -4,6 +4,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Windows.Input; using System.Windows.Input;
using Avalonia.Data;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Rendering; using Avalonia.Rendering;
@ -41,8 +42,9 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Defines the <see cref="Command"/> property. /// Defines the <see cref="Command"/> property.
/// </summary> /// </summary>
public static readonly StyledProperty<ICommand> CommandProperty = public static readonly DirectProperty<Button, ICommand> CommandProperty =
AvaloniaProperty.Register<Button, ICommand>(nameof(Command)); AvaloniaProperty.RegisterDirect<Button, ICommand>(nameof(Command),
button => button.Command, (button, command) => button.Command = command, enableDataValidation: true);
/// <summary> /// <summary>
/// Defines the <see cref="HotKey"/> property. /// Defines the <see cref="HotKey"/> property.
@ -68,6 +70,8 @@ namespace Avalonia.Controls
public static readonly RoutedEvent<RoutedEventArgs> ClickEvent = public static readonly RoutedEvent<RoutedEventArgs> ClickEvent =
RoutedEvent.Register<Button, RoutedEventArgs>("Click", RoutingStrategies.Bubble); RoutedEvent.Register<Button, RoutedEventArgs>("Click", RoutingStrategies.Bubble);
private ICommand _command;
/// <summary> /// <summary>
/// Initializes static members of the <see cref="Button"/> class. /// Initializes static members of the <see cref="Button"/> class.
/// </summary> /// </summary>
@ -102,8 +106,8 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public ICommand Command public ICommand Command
{ {
get { return GetValue(CommandProperty); } get { return _command; }
set { SetValue(CommandProperty, value); } set { SetAndRaise(CommandProperty, ref _command, value); }
} }
/// <summary> /// <summary>
@ -250,6 +254,18 @@ namespace Avalonia.Controls
} }
} }
protected override void UpdateDataValidation(AvaloniaProperty property, BindingNotification status)
{
base.UpdateDataValidation(property, status);
if(property == CommandProperty)
{
if(status?.ErrorType == BindingErrorType.Error)
{
IsEnabled = false;
}
}
}
/// <summary> /// <summary>
/// Called when the <see cref="Command"/> property changes. /// Called when the <see cref="Command"/> property changes.
/// </summary> /// </summary>

22
src/Avalonia.Controls/Control.cs

@ -97,8 +97,8 @@ namespace Avalonia.Controls
private bool _isAttachedToLogicalTree; private bool _isAttachedToLogicalTree;
private IAvaloniaList<ILogical> _logicalChildren; private IAvaloniaList<ILogical> _logicalChildren;
private INameScope _nameScope; private INameScope _nameScope;
private Styles _styles;
private bool _styled; private bool _styled;
private Styles _styles;
private Subject<IStyleable> _styleDetach = new Subject<IStyleable>(); private Subject<IStyleable> _styleDetach = new Subject<IStyleable>();
/// <summary> /// <summary>
@ -243,11 +243,7 @@ namespace Avalonia.Controls
/// Each control may define data templates which are applied to the control itself and its /// Each control may define data templates which are applied to the control itself and its
/// children. /// children.
/// </remarks> /// </remarks>
public DataTemplates DataTemplates public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
{
get { return _dataTemplates ?? (_dataTemplates = new DataTemplates()); }
set { _dataTemplates = value; }
}
/// <summary> /// <summary>
/// Gets a value that indicates whether the element has finished initialization. /// Gets a value that indicates whether the element has finished initialization.
@ -259,18 +255,14 @@ namespace Avalonia.Controls
public bool IsInitialized { get; private set; } public bool IsInitialized { get; private set; }
/// <summary> /// <summary>
/// Gets or sets the styles for the control. /// Gets the styles for the control.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Styles for the entire application are added to the Application.Styles collection, but /// Styles for the entire application are added to the Application.Styles collection, but
/// each control may in addition define its own styles which are applied to the control /// each control may in addition define its own styles which are applied to the control
/// itself and its children. /// itself and its children.
/// </remarks> /// </remarks>
public Styles Styles public Styles Styles => _styles ?? (_styles = new Styles());
{
get { return _styles ?? (_styles = new Styles()); }
set { _styles = value; }
}
/// <summary> /// <summary>
/// Gets the control's logical parent. /// Gets the control's logical parent.
@ -304,6 +296,9 @@ namespace Avalonia.Controls
internal set { SetValue(TemplatedParentProperty, value); } internal set { SetValue(TemplatedParentProperty, value); }
} }
/// <inheritdoc/>
bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
/// <summary> /// <summary>
/// Gets a value indicating whether the element is attached to a rooted logical tree. /// Gets a value indicating whether the element is attached to a rooted logical tree.
/// </summary> /// </summary>
@ -336,6 +331,9 @@ namespace Avalonia.Controls
/// <inheritdoc/> /// <inheritdoc/>
IObservable<IStyleable> IStyleable.StyleDetach => _styleDetach; IObservable<IStyleable> IStyleable.StyleDetach => _styleDetach;
/// <inheritdoc/>
bool IStyleHost.IsStylesInitialized => _styles != null;
/// <inheritdoc/> /// <inheritdoc/>
IStyleHost IStyleHost.StylingParent => (IStyleHost)InheritanceParent; IStyleHost IStyleHost.StylingParent => (IStyleHost)InheritanceParent;

59
src/Avalonia.Controls/DrawingPresenter.cs

@ -0,0 +1,59 @@
using Avalonia.Controls.Shapes;
using Avalonia.Media;
using Avalonia.Metadata;
namespace Avalonia.Controls
{
public class DrawingPresenter : Control
{
static DrawingPresenter()
{
AffectsMeasure(DrawingProperty);
AffectsRender(DrawingProperty);
}
public static readonly StyledProperty<Drawing> DrawingProperty =
AvaloniaProperty.Register<DrawingPresenter, Drawing>(nameof(Drawing));
public static readonly StyledProperty<Stretch> StretchProperty =
AvaloniaProperty.Register<DrawingPresenter, Stretch>(nameof(Stretch), Stretch.Uniform);
[Content]
public Drawing Drawing
{
get => GetValue(DrawingProperty);
set => SetValue(DrawingProperty, value);
}
public Stretch Stretch
{
get => GetValue(StretchProperty);
set => SetValue(StretchProperty, value);
}
private Matrix _transform = Matrix.Identity;
protected override Size MeasureOverride(Size availableSize)
{
if (Drawing == null) return new Size();
var (size, transform) = Shape.CalculateSizeAndTransform(availableSize, Drawing.GetBounds(), Stretch);
_transform = transform;
return size;
}
public override void Render(DrawingContext context)
{
if (Drawing != null)
{
using (context.PushPreTransform(_transform))
using (context.PushClip(Bounds))
{
Drawing.Draw(context);
}
}
}
}
}

2
src/Avalonia.Controls/DropDown.cs

@ -120,7 +120,7 @@ namespace Avalonia.Controls
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnPointerPressed(PointerPressedEventArgs e) protected override void OnPointerPressed(PointerPressedEventArgs e)
{ {
if (!IsDropDownOpen && ((IVisual)e.Source).GetVisualRoot() != typeof(PopupRoot)) if (!IsDropDownOpen && ((IVisual)e.Source).GetVisualRoot() is PopupRoot)
{ {
IsDropDownOpen = true; IsDropDownOpen = true;
e.Handled = true; e.Handled = true;

14
src/Avalonia.Controls/IControl.cs

@ -14,7 +14,14 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Interface for Avalonia controls. /// Interface for Avalonia controls.
/// </summary> /// </summary>
public interface IControl : IVisual, ILogical, ILayoutable, IInputElement, INamed, IStyleable, IStyleHost public interface IControl : IVisual,
IDataTemplateHost,
ILogical,
ILayoutable,
IInputElement,
INamed,
IStyleable,
IStyleHost
{ {
/// <summary> /// <summary>
/// Occurs when the control has finished initialization. /// Occurs when the control has finished initialization.
@ -31,11 +38,6 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
object DataContext { get; set; } object DataContext { get; set; }
/// <summary>
/// Gets the data templates for the control.
/// </summary>
DataTemplates DataTemplates { get; }
/// <summary> /// <summary>
/// Gets a value that indicates whether the element has finished initialization. /// Gets a value that indicates whether the element has finished initialization.
/// </summary> /// </summary>

6
src/Avalonia.Controls/IGlobalDataTemplates.cs

@ -8,11 +8,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Defines the application-global data templates. /// Defines the application-global data templates.
/// </summary> /// </summary>
public interface IGlobalDataTemplates public interface IGlobalDataTemplates : IDataTemplateHost
{ {
/// <summary>
/// Gets the application-global data templates.
/// </summary>
DataTemplates DataTemplates { get; }
} }
} }

2
src/Avalonia.Controls/MenuItem.cs

@ -24,7 +24,7 @@ namespace Avalonia.Controls
/// Defines the <see cref="Command"/> property. /// Defines the <see cref="Command"/> property.
/// </summary> /// </summary>
public static readonly StyledProperty<ICommand> CommandProperty = public static readonly StyledProperty<ICommand> CommandProperty =
Button.CommandProperty.AddOwner<MenuItem>(); AvaloniaProperty.Register<MenuItem, ICommand>(nameof(Command));
/// <summary> /// <summary>
/// Defines the <see cref="HotKey"/> property. /// Defines the <see cref="HotKey"/> property.

26
src/Avalonia.Controls/Primitives/Popup.cs

@ -277,7 +277,7 @@ namespace Avalonia.Controls.Primitives
{ {
base.OnDetachedFromLogicalTree(e); base.OnDetachedFromLogicalTree(e);
_topLevel = null; _topLevel = null;
if (_popupRoot != null) if (_popupRoot != null)
{ {
((ISetLogicalParent)_popupRoot).SetParent(null); ((ISetLogicalParent)_popupRoot).SetParent(null);
@ -327,34 +327,40 @@ namespace Avalonia.Controls.Primitives
/// </summary> /// </summary>
/// <returns>The popup's position in screen coordinates.</returns> /// <returns>The popup's position in screen coordinates.</returns>
protected virtual Point GetPosition() protected virtual Point GetPosition()
{
return GetPosition(PlacementTarget ?? this.GetVisualParent<Control>(), PlacementMode, PopupRoot,
HorizontalOffset, VerticalOffset);
}
internal static Point GetPosition(Control target, PlacementMode placement, PopupRoot popupRoot, double horizontalOffset, double verticalOffset)
{ {
var zero = default(Point); var zero = default(Point);
var mode = PlacementMode; var mode = placement;
var target = PlacementTarget ?? this.GetVisualParent<Control>();
if (target?.GetVisualRoot() == null) if (target?.GetVisualRoot() == null)
{ {
mode = PlacementMode.Pointer; mode = PlacementMode.Pointer;
} }
switch (mode) switch (mode)
{ {
case PlacementMode.Pointer: case PlacementMode.Pointer:
if(PopupRoot != null) if (popupRoot != null)
{ {
// Scales the Horizontal and Vertical offset to screen co-ordinates. // Scales the Horizontal and Vertical offset to screen co-ordinates.
var screenOffset = new Point(HorizontalOffset * (PopupRoot as ILayoutRoot).LayoutScaling, VerticalOffset * (PopupRoot as ILayoutRoot).LayoutScaling); var screenOffset = new Point(horizontalOffset * (popupRoot as ILayoutRoot).LayoutScaling,
return (((IInputRoot)PopupRoot)?.MouseDevice?.Position ?? default(Point)) + screenOffset; verticalOffset * (popupRoot as ILayoutRoot).LayoutScaling);
return (((IInputRoot)popupRoot)?.MouseDevice?.Position ?? default(Point)) + screenOffset;
} }
return default(Point); return default(Point);
case PlacementMode.Bottom: case PlacementMode.Bottom:
return target?.PointToScreen(new Point(0 + horizontalOffset, target.Bounds.Height + verticalOffset)) ??
return target?.PointToScreen(new Point(0 + HorizontalOffset, target.Bounds.Height + VerticalOffset)) ?? zero; zero;
case PlacementMode.Right: case PlacementMode.Right:
return target?.PointToScreen(new Point(target.Bounds.Width + HorizontalOffset, 0 + VerticalOffset)) ?? zero; return target?.PointToScreen(new Point(target.Bounds.Width + horizontalOffset, 0 + verticalOffset)) ?? zero;
default: default:
throw new InvalidOperationException("Invalid value for Popup.PlacementMode"); throw new InvalidOperationException("Invalid value for Popup.PlacementMode");

28
src/Avalonia.Controls/Shapes/Shape.cs

@ -155,11 +155,21 @@ namespace Avalonia.Controls.Shapes
{ {
// This should probably use GetRenderBounds(strokeThickness) but then the calculations // This should probably use GetRenderBounds(strokeThickness) but then the calculations
// will multiply the stroke thickness as well, which isn't correct. // will multiply the stroke thickness as well, which isn't correct.
Rect shapeBounds = DefiningGeometry.Bounds; var (size, transform) = CalculateSizeAndTransform(availableSize, DefiningGeometry.Bounds, Stretch);
if (_transform != transform)
{
_transform = transform;
_renderedGeometry = null;
}
return size;
}
internal static (Size, Matrix) CalculateSizeAndTransform(Size availableSize, Rect shapeBounds, Stretch Stretch)
{
Size shapeSize = new Size(shapeBounds.Right, shapeBounds.Bottom); Size shapeSize = new Size(shapeBounds.Right, shapeBounds.Bottom);
Matrix translate = Matrix.Identity; Matrix translate = Matrix.Identity;
double width = Width;
double height = Height;
double desiredX = availableSize.Width; double desiredX = availableSize.Width;
double desiredY = availableSize.Height; double desiredY = availableSize.Height;
double sx = 0.0; double sx = 0.0;
@ -226,15 +236,9 @@ namespace Avalonia.Controls.Shapes
break; break;
} }
var t = translate * Matrix.CreateScale(sx, sy); var transform = translate * Matrix.CreateScale(sx, sy);
var size = new Size(shapeSize.Width * sx, shapeSize.Height * sy);
if (_transform != t) return (size, transform);
{
_transform = t;
_renderedGeometry = null;
}
return new Size(shapeSize.Width * sx, shapeSize.Height * sy);
} }
private static void AffectsGeometryInvalidate(AvaloniaPropertyChangedEventArgs e) private static void AffectsGeometryInvalidate(AvaloniaPropertyChangedEventArgs e)

24
src/Avalonia.Controls/Templates/DataTemplateExtensions.cs

@ -17,8 +17,8 @@ namespace Avalonia.Controls.Templates
/// <param name="control">The control searching for the data template.</param> /// <param name="control">The control searching for the data template.</param>
/// <param name="data">The data.</param> /// <param name="data">The data.</param>
/// <param name="primary"> /// <param name="primary">
/// An optional primary template that can will be tried before the /// An optional primary template that can will be tried before the DataTemplates in the
/// <see cref="IControl.DataTemplates"/> in the tree are searched. /// tree are searched.
/// </param> /// </param>
/// <returns>The data template or null if no matching data template was found.</returns> /// <returns>The data template or null if no matching data template was found.</returns>
public static IDataTemplate FindDataTemplate( public static IDataTemplate FindDataTemplate(
@ -31,13 +31,16 @@ namespace Avalonia.Controls.Templates
return primary; return primary;
} }
foreach (var i in control.GetSelfAndLogicalAncestors().OfType<IControl>()) foreach (var i in control.GetSelfAndLogicalAncestors().OfType<IDataTemplateHost>())
{ {
foreach (IDataTemplate dt in i.DataTemplates) if (i.IsDataTemplatesInitialized)
{ {
if (dt.Match(data)) foreach (IDataTemplate dt in i.DataTemplates)
{ {
return dt; if (dt.Match(data))
{
return dt;
}
} }
} }
} }
@ -46,11 +49,14 @@ namespace Avalonia.Controls.Templates
if (global != null) if (global != null)
{ {
foreach (IDataTemplate dt in global.DataTemplates) if (global.IsDataTemplatesInitialized)
{ {
if (dt.Match(data)) foreach (IDataTemplate dt in global.DataTemplates)
{ {
return dt; if (dt.Match(data))
{
return dt;
}
} }
} }
} }

27
src/Avalonia.Controls/Templates/IDataTemplateHost.cs

@ -0,0 +1,27 @@
// 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;
namespace Avalonia.Controls.Templates
{
/// <summary>
/// Defines an element that has a <see cref="DataTemplates"/> collection.
/// </summary>
public interface IDataTemplateHost
{
/// <summary>
/// Gets the data templates for the element.
/// </summary>
DataTemplates DataTemplates { get; }
/// <summary>
/// Gets a value indicating whether <see cref="DataTemplates"/> is initialized.
/// </summary>
/// <remarks>
/// The <see cref="DataTemplates"/> property may be lazily initialized, if so this property
/// indicates whether it has been initialized.
/// </remarks>
bool IsDataTemplatesInitialized { get; }
}
}

236
src/Avalonia.Controls/ToolTip.cs

@ -3,11 +3,7 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive.Subjects;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Threading;
using Avalonia.VisualTree;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -29,29 +25,50 @@ namespace Avalonia.Controls
AvaloniaProperty.RegisterAttached<ToolTip, Control, object>("Tip"); AvaloniaProperty.RegisterAttached<ToolTip, Control, object>("Tip");
/// <summary> /// <summary>
/// The popup window used to display the active tooltip. /// Defines the ToolTip.IsOpen attached property.
/// </summary> /// </summary>
private static PopupRoot s_popup; public static readonly AttachedProperty<bool> IsOpenProperty =
AvaloniaProperty.RegisterAttached<ToolTip, Control, bool>("IsOpen");
/// <summary> /// <summary>
/// The control that the currently visible tooltip is attached to. /// Defines the ToolTip.Placement property.
/// </summary> /// </summary>
private static Control s_current; public static readonly AttachedProperty<PlacementMode> PlacementProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, PlacementMode>("Placement", defaultValue: PlacementMode.Pointer);
/// <summary> /// <summary>
/// Observable fired when a tooltip should be displayed for a control. The output from this /// Defines the ToolTip.HorizontalOffset property.
/// observable is throttled and calls <see cref="ShowToolTip(Control)"/> when the time
/// period expires.
/// </summary> /// </summary>
private static readonly Subject<Control> s_show = new Subject<Control>(); public static readonly AttachedProperty<double> HorizontalOffsetProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, double>("HorizontalOffset");
/// <summary>
/// Defines the ToolTip.VerticalOffset property.
/// </summary>
public static readonly AttachedProperty<double> VerticalOffsetProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, double>("VerticalOffset", 20);
/// <summary>
/// Defines the ToolTip.ShowDelay property.
/// </summary>
public static readonly AttachedProperty<int> ShowDelayProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, int>("ShowDelay", 400);
/// <summary>
/// Stores the curernt <see cref="ToolTip"/> instance in the control.
/// </summary>
private static readonly AttachedProperty<ToolTip> ToolTipProperty =
AvaloniaProperty.RegisterAttached<ToolTip, Control, ToolTip>("ToolTip");
private PopupRoot _popup;
/// <summary> /// <summary>
/// Initializes static members of the <see cref="ToolTip"/> class. /// Initializes static members of the <see cref="ToolTip"/> class.
/// </summary> /// </summary>
static ToolTip() static ToolTip()
{ {
TipProperty.Changed.Subscribe(TipChanged); TipProperty.Changed.Subscribe(ToolTipService.Instance.TipChanged);
s_show.Throttle(TimeSpan.FromSeconds(0.5), AvaloniaScheduler.Instance).Subscribe(ShowToolTip); IsOpenProperty.Changed.Subscribe(IsOpenChanged);
} }
/// <summary> /// <summary>
@ -77,101 +94,160 @@ namespace Avalonia.Controls
} }
/// <summary> /// <summary>
/// called when the <see cref="TipProperty"/> property changes on a control. /// Gets the value of the ToolTip.IsOpen attached property.
/// </summary> /// </summary>
/// <param name="e">The event args.</param> /// <param name="element">The control to get the property from.</param>
private static void TipChanged(AvaloniaPropertyChangedEventArgs e) /// <returns>
/// A value indicating whether the tool tip is visible.
/// </returns>
public static bool GetIsOpen(Control element)
{ {
var control = (Control)e.Sender; return element.GetValue(IsOpenProperty);
}
if (e.OldValue != null) /// <summary>
{ /// Sets the value of the ToolTip.IsOpen attached property.
control.PointerEnter -= ControlPointerEnter; /// </summary>
control.PointerLeave -= ControlPointerLeave; /// <param name="element">The control to get the property from.</param>
} /// <param name="value">A value indicating whether the tool tip is visible.</param>
public static void SetIsOpen(Control element, bool value)
{
element.SetValue(IsOpenProperty, value);
}
if (e.NewValue != null) /// <summary>
{ /// Gets the value of the ToolTip.Placement attached property.
control.PointerEnter += ControlPointerEnter; /// </summary>
control.PointerLeave += ControlPointerLeave; /// <param name="element">The control to get the property from.</param>
} /// <returns>
/// A value indicating how the tool tip is positioned.
/// </returns>
public static PlacementMode GetPlacement(Control element)
{
return element.GetValue(PlacementProperty);
} }
/// <summary> /// <summary>
/// Shows a tooltip for the specified control. /// Sets the value of the ToolTip.Placement attached property.
/// </summary> /// </summary>
/// <param name="control">The control.</param> /// <param name="element">The control to get the property from.</param>
private static void ShowToolTip(Control control) /// <param name="value">A value indicating how the tool tip is positioned.</param>
public static void SetPlacement(Control element, PlacementMode value)
{ {
if (control != null && control.IsVisible && control.GetVisualRoot() != null) element.SetValue(PlacementProperty, value);
{ }
var cp = (control.GetVisualRoot() as IInputRoot)?.MouseDevice?.GetPosition(control);
if (cp.HasValue && control.IsVisible && new Rect(control.Bounds.Size).Contains(cp.Value)) /// <summary>
{ /// Gets the value of the ToolTip.HorizontalOffset attached property.
var position = control.PointToScreen(cp.Value) + new Vector(0, 22); /// </summary>
/// <param name="element">The control to get the property from.</param>
if (s_popup == null) /// <returns>
{ /// A value indicating how the tool tip is positioned.
s_popup = new PopupRoot(); /// </returns>
s_popup.Content = new ToolTip(); public static double GetHorizontalOffset(Control element)
} {
else return element.GetValue(HorizontalOffsetProperty);
{ }
((ISetLogicalParent)s_popup).SetParent(null);
} /// <summary>
/// Sets the value of the ToolTip.HorizontalOffset attached property.
((ISetLogicalParent)s_popup).SetParent(control); /// </summary>
((ToolTip)s_popup.Content).Content = GetTip(control); /// <param name="element">The control to get the property from.</param>
s_popup.Position = position; /// <param name="value">A value indicating how the tool tip is positioned.</param>
s_popup.Show(); public static void SetHorizontalOffset(Control element, double value)
{
s_current = control; element.SetValue(HorizontalOffsetProperty, value);
} }
}
/// <summary>
/// Gets the value of the ToolTip.VerticalOffset attached property.
/// </summary>
/// <param name="element">The control to get the property from.</param>
/// <returns>
/// A value indicating how the tool tip is positioned.
/// </returns>
public static double GetVerticalOffset(Control element)
{
return element.GetValue(VerticalOffsetProperty);
}
/// <summary>
/// Sets the value of the ToolTip.VerticalOffset attached property.
/// </summary>
/// <param name="element">The control to get the property from.</param>
/// <param name="value">A value indicating how the tool tip is positioned.</param>
public static void SetVerticalOffset(Control element, double value)
{
element.SetValue(VerticalOffsetProperty, value);
} }
/// <summary> /// <summary>
/// Called when the pointer enters a control with an attached tooltip. /// Gets the value of the ToolTip.ShowDelay attached property.
/// </summary> /// </summary>
/// <param name="sender">The event sender.</param> /// <param name="element">The control to get the property from.</param>
/// <param name="e">The event args.</param> /// <returns>
private static void ControlPointerEnter(object sender, PointerEventArgs e) /// A value indicating the time, in milliseconds, before a tool tip opens.
/// </returns>
public static int GetShowDelay(Control element)
{ {
s_current = (Control)sender; return element.GetValue(ShowDelayProperty);
s_show.OnNext(s_current);
} }
/// <summary> /// <summary>
/// Called when the pointer leaves a control with an attached tooltip. /// Sets the value of the ToolTip.ShowDelay attached property.
/// </summary> /// </summary>
/// <param name="sender">The event sender.</param> /// <param name="element">The control to get the property from.</param>
/// <param name="e">The event args.</param> /// <param name="value">A value indicating the time, in milliseconds, before a tool tip opens.</param>
private static void ControlPointerLeave(object sender, PointerEventArgs e) public static void SetShowDelay(Control element, int value)
{ {
var control = (Control)sender; element.SetValue(ShowDelayProperty, value);
}
private static void IsOpenChanged(AvaloniaPropertyChangedEventArgs e)
{
var control = (Control)e.Sender;
if (control == s_current) if ((bool)e.NewValue)
{ {
if (s_popup != null) var tip = GetTip(control);
if (tip == null) return;
var toolTip = control.GetValue(ToolTipProperty);
if (toolTip == null || (tip != toolTip && tip != toolTip.Content))
{ {
DisposeTooltip(); toolTip?.Close();
s_show.OnNext(null);
toolTip = tip as ToolTip ?? new ToolTip { Content = tip };
control.SetValue(ToolTipProperty, toolTip);
} }
toolTip.Open(control);
}
else
{
var toolTip = control.GetValue(ToolTipProperty);
toolTip?.Close();
} }
} }
private static void DisposeTooltip() private void Open(Control control)
{ {
if (s_popup != null) Close();
{
// Clear the ToolTip's Content in case it has control content: this will _popup = new PopupRoot { Content = this };
// reset its visual parent allowing it to be used again. ((ISetLogicalParent)_popup).SetParent(control);
((ToolTip)s_popup.Content).Content = null; _popup.Position = Popup.GetPosition(control, GetPlacement(control), _popup,
GetHorizontalOffset(control), GetVerticalOffset(control));
_popup.Show();
}
// Dispose of the popup. private void Close()
s_popup.Dispose(); {
s_popup = null; if (_popup != null)
{
_popup.Content = null;
_popup.Hide();
_popup = null;
} }
} }
} }

98
src/Avalonia.Controls/ToolTipService.cs

@ -0,0 +1,98 @@
using System;
using Avalonia.Input;
using Avalonia.Threading;
namespace Avalonia.Controls
{
/// <summary>
/// Handeles <see cref="ToolTip"/> interaction with controls.
/// </summary>
internal sealed class ToolTipService
{
public static ToolTipService Instance { get; } = new ToolTipService();
private DispatcherTimer _timer;
private ToolTipService() { }
/// <summary>
/// called when the <see cref="ToolTip.TipProperty"/> property changes on a control.
/// </summary>
/// <param name="e">The event args.</param>
internal void TipChanged(AvaloniaPropertyChangedEventArgs e)
{
var control = (Control)e.Sender;
if (e.OldValue != null)
{
control.PointerEnter -= ControlPointerEnter;
control.PointerLeave -= ControlPointerLeave;
}
if (e.NewValue != null)
{
control.PointerEnter += ControlPointerEnter;
control.PointerLeave += ControlPointerLeave;
}
}
/// <summary>
/// Called when the pointer enters a control with an attached tooltip.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void ControlPointerEnter(object sender, PointerEventArgs e)
{
StopTimer();
var control = (Control)sender;
var showDelay = ToolTip.GetShowDelay(control);
if (showDelay == 0)
{
Open(control);
}
else
{
StartShowTimer(showDelay, control);
}
}
/// <summary>
/// Called when the pointer leaves a control with an attached tooltip.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void ControlPointerLeave(object sender, PointerEventArgs e)
{
var control = (Control)sender;
Close(control);
}
private void StartShowTimer(int showDelay, Control control)
{
_timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(showDelay) };
_timer.Tick += (o, e) => Open(control);
_timer.Start();
}
private void Open(Control control)
{
StopTimer();
ToolTip.SetIsOpen(control, true);
}
private void Close(Control control)
{
StopTimer();
ToolTip.SetIsOpen(control, false);
}
private void StopTimer()
{
_timer?.Stop();
_timer = null;
}
}
}

2
src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

2
src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

2
src/Avalonia.Diagnostics/DevTools.xaml.cs

@ -71,7 +71,7 @@ namespace Avalonia.Diagnostics
Width = 1024, Width = 1024,
Height = 512, Height = 512,
Content = devTools, Content = devTools,
DataTemplates = new DataTemplates DataTemplates =
{ {
new ViewLocator<ViewModelBase>(), new ViewLocator<ViewModelBase>(),
} }

2
src/Avalonia.Diagnostics/Views/ControlDetailsView.cs

@ -42,7 +42,7 @@ namespace Avalonia.Diagnostics.Views
{ {
Content = _grid = new SimpleGrid Content = _grid = new SimpleGrid
{ {
Styles = new Styles Styles =
{ {
new Style(x => x.Is<Control>()) new Style(x => x.Is<Control>())
{ {

22
src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj

@ -1,26 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework> <TargetFramework>netcoreapp2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup>
<DebugSymbols>true</DebugSymbols> <DocumentationFile>bin\$(Configuration)\Avalonia.DotNetCoreRuntime.XML</DocumentationFile>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NETSTANDARD</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Avalonia.DotNetCoreRuntime.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NETSTANDARD</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Avalonia.DotNetCoreRuntime.XML</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Shared\SharedAssemblyInfo.cs"> <Compile Include="..\Shared\SharedAssemblyInfo.cs">

13
src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs

@ -59,7 +59,11 @@ namespace Avalonia
from attribute in assembly.GetCustomAttributes<ExportWindowingSubsystemAttribute>() from attribute in assembly.GetCustomAttributes<ExportWindowingSubsystemAttribute>()
where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker) where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker)
orderby attribute.Priority ascending orderby attribute.Priority ascending
select attribute).First(); select attribute).FirstOrDefault();
if (windowingSubsystemAttribute == null)
{
throw new InvalidOperationException("No windowing subsystem found. Are you missing assembly references?");
}
var renderingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies() var renderingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies()
from attribute in assembly.GetCustomAttributes<ExportRenderingSubsystemAttribute>() from attribute in assembly.GetCustomAttributes<ExportRenderingSubsystemAttribute>()
@ -67,7 +71,12 @@ namespace Avalonia
where attribute.RequiresWindowingSubsystem == null where attribute.RequiresWindowingSubsystem == null
|| attribute.RequiresWindowingSubsystem == windowingSubsystemAttribute.Name || attribute.RequiresWindowingSubsystem == windowingSubsystemAttribute.Name
orderby attribute.Priority ascending orderby attribute.Priority ascending
select attribute).First(); select attribute).FirstOrDefault();
if (renderingSubsystemAttribute == null)
{
throw new InvalidOperationException("No rendering subsystem found. Are you missing assembly references?");
}
UseWindowingSubsystem(() => windowingSubsystemAttribute.InitializationType UseWindowingSubsystem(() => windowingSubsystemAttribute.InitializationType
.GetRuntimeMethod(windowingSubsystemAttribute.InitializationMethod, Type.EmptyTypes).Invoke(null, null), .GetRuntimeMethod(windowingSubsystemAttribute.InitializationMethod, Type.EmptyTypes).Invoke(null, null),

91
src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj

@ -1,72 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <Project Sdk="Microsoft.NET.Sdk">
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <TargetFramework>net461</TargetFramework>
<PropertyGroup> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <DocumentationFile>bin\$(Configuration)\Avalonia.DotNetFrameworkRuntime.xml</DocumentationFile>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <DefineConstants>$(DefineConstants);FULLDOTNET</DefineConstants>
<ProjectGuid>{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}</ProjectGuid> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<OutputType>Library</OutputType> </PropertyGroup>
<AppDesignerFolder>Properties</AppDesignerFolder> <ItemGroup>
<RootNamespace>Avalonia.DotNetFrameworkRuntime</RootNamespace> <Compile Include="..\Shared\SharedAssemblyInfo.cs">
<AssemblyName>Avalonia.DotNetFrameworkRuntime</AssemblyName> <Link>Properties\SharedAssemblyInfo.cs</Link>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> </Compile>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile /> <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
</PropertyGroup> <ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" />
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
<DebugSymbols>true</DebugSymbols> <ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj" />
<DebugType>full</DebugType> </ItemGroup>
<Optimize>false</Optimize> <Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" Label="Shared" />
<OutputPath>bin\Debug\</OutputPath> <Import Project="..\..\build\Rx.props" />
<DefineConstants>TRACE;DEBUG;FULLDOTNET</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Avalonia.DotNetFrameworkRuntime.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;FULLDOTNET</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Avalonia.DotNetFrameworkRuntime.xml</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</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="AppBuilder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RuntimeInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj">
<Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project>
<Name>Avalonia.Base</Name>
</ProjectReference>
<ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj">
<Project>{D2221C82-4A25-4583-9B43-D791E3F6820C}</Project>
<Name>Avalonia.Controls</Name>
</ProjectReference>
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj">
<Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
<Name>Avalonia.Visuals</Name>
</ProjectReference>
<ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj">
<Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project>
<Name>Avalonia.Styling</Name>
</ProjectReference>
</ItemGroup>
<Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\build\Rx.props" />
</Project> </Project>

36
src/Avalonia.DotNetFrameworkRuntime/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("Avalonia.DotNetFrameworkRuntime")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Avalonia.DotNetFrameworkRuntime")]
[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("4a1abb09-9047-4bd5-a4ad-a055e52c5ee0")]
// 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")]

3
src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj

@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems> <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<EnableDefaultItems>False</EnableDefaultItems> <EnableDefaultItems>False</EnableDefaultItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<NoWarn>CS0436</NoWarn>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>

12
src/Avalonia.HtmlRenderer/Compat/Api.cs

@ -4,18 +4,6 @@ using System.Text;
namespace System.Net namespace System.Net
{ {
internal class AsyncCompletedEventArgs
{
public object UserState { get; set; }
public Exception Error { get; set; }
public bool Cancelled { get; set; }
public AsyncCompletedEventArgs(Exception error, bool cancelled, object userState)
{
}
}
class WebException : Exception class WebException : Exception
{ {
public object Response { get; set; } public object Response { get; set; }

2
src/Avalonia.Input/Avalonia.Input.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

2
src/Avalonia.Interactivity/Avalonia.Interactivity.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

20
src/Avalonia.Interactivity/Interactive.cs

@ -16,14 +16,18 @@ namespace Avalonia.Interactivity
/// </summary> /// </summary>
public class Interactive : Layoutable, IInteractive public class Interactive : Layoutable, IInteractive
{ {
private readonly Dictionary<RoutedEvent, List<EventSubscription>> _eventHandlers = private Dictionary<RoutedEvent, List<EventSubscription>> _eventHandlers;
new Dictionary<RoutedEvent, List<EventSubscription>>();
/// <summary> /// <summary>
/// Gets the interactive parent of the object for bubbling and tunnelling events. /// Gets the interactive parent of the object for bubbling and tunnelling events.
/// </summary> /// </summary>
IInteractive IInteractive.InteractiveParent => ((IVisual)this).VisualParent as IInteractive; IInteractive IInteractive.InteractiveParent => ((IVisual)this).VisualParent as IInteractive;
private Dictionary<RoutedEvent, List<EventSubscription>> EventHandlers
{
get { return _eventHandlers ?? (_eventHandlers = new Dictionary<RoutedEvent, List<EventSubscription>>()); }
}
/// <summary> /// <summary>
/// Adds a handler for the specified routed event. /// Adds a handler for the specified routed event.
/// </summary> /// </summary>
@ -43,10 +47,10 @@ namespace Avalonia.Interactivity
List<EventSubscription> subscriptions; List<EventSubscription> subscriptions;
if (!_eventHandlers.TryGetValue(routedEvent, out subscriptions)) if (!EventHandlers.TryGetValue(routedEvent, out subscriptions))
{ {
subscriptions = new List<EventSubscription>(); subscriptions = new List<EventSubscription>();
_eventHandlers.Add(routedEvent, subscriptions); EventHandlers.Add(routedEvent, subscriptions);
} }
var sub = new EventSubscription var sub = new EventSubscription
@ -89,9 +93,9 @@ namespace Avalonia.Interactivity
Contract.Requires<ArgumentNullException>(routedEvent != null); Contract.Requires<ArgumentNullException>(routedEvent != null);
Contract.Requires<ArgumentNullException>(handler != null); Contract.Requires<ArgumentNullException>(handler != null);
List<EventSubscription> subscriptions; List<EventSubscription> subscriptions = null;
if (_eventHandlers.TryGetValue(routedEvent, out subscriptions)) if (_eventHandlers?.TryGetValue(routedEvent, out subscriptions) == true)
{ {
subscriptions.RemoveAll(x => x.Handler == handler); subscriptions.RemoveAll(x => x.Handler == handler);
} }
@ -181,9 +185,9 @@ namespace Avalonia.Interactivity
e.RoutedEvent.InvokeRaised(this, e); e.RoutedEvent.InvokeRaised(this, e);
List<EventSubscription> subscriptions; List<EventSubscription> subscriptions = null;
if (_eventHandlers.TryGetValue(e.RoutedEvent, out subscriptions)) if (_eventHandlers?.TryGetValue(e.RoutedEvent, out subscriptions) == true)
{ {
foreach (var sub in subscriptions.ToList()) foreach (var sub in subscriptions.ToList())
{ {

2
src/Avalonia.Layout/Avalonia.Layout.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

5
src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
@ -23,6 +23,9 @@
<DocumentationFile>bin\Release\Avalonia.Logging.Serilog.XML</DocumentationFile> <DocumentationFile>bin\Release\Avalonia.Logging.Serilog.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Include="..\Shared\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" /> <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
</ItemGroup> </ItemGroup>

27
src/Avalonia.Logging.Serilog/Properties/AssemblyInfo.cs

@ -1,30 +1,3 @@
using System.Resources;
using System.Reflection; 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("Avalonia.Serilog")] [assembly: AssemblyTitle("Avalonia.Serilog")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Avalonia.Serilog")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]
// 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")]

3
src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems> <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
@ -25,6 +25,7 @@
<None Remove="Shims.cs" /> <None Remove="Shims.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Shared\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

24
src/Avalonia.ReactiveUI/Properties/AssemblyInfo.cs

@ -1,33 +1,9 @@
// Copyright (c) The Avalonia Project. All rights reserved. // 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. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Resources;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("Avalonia.ReactiveUI")] [assembly: AssemblyTitle("Avalonia.ReactiveUI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Avalonia.ReactiveUI")]
[assembly: AssemblyCopyright("Copyright \u00A9 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]
// 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")]

2
src/Avalonia.Styling/Avalonia.Styling.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

12
src/Avalonia.Styling/Styling/IStyleHost.cs

@ -1,6 +1,8 @@
// Copyright (c) The Avalonia Project. All rights reserved. // 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. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Styling namespace Avalonia.Styling
{ {
/// <summary> /// <summary>
@ -8,6 +10,15 @@ namespace Avalonia.Styling
/// </summary> /// </summary>
public interface IStyleHost public interface IStyleHost
{ {
/// <summary>
/// Gets a value indicating whether <see cref="Styles"/> is initialized.
/// </summary>
/// <remarks>
/// The <see cref="Styles"/> property may be lazily initialized, if so this property
/// indicates whether it has been initialized.
/// </remarks>
bool IsStylesInitialized { get; }
/// <summary> /// <summary>
/// Gets the styles for the element. /// Gets the styles for the element.
/// </summary> /// </summary>
@ -17,6 +28,5 @@ namespace Avalonia.Styling
/// Gets the parent style host element. /// Gets the parent style host element.
/// </summary> /// </summary>
IStyleHost StylingParent { get; } IStyleHost StylingParent { get; }
} }
} }

11
src/Avalonia.Styling/Styling/StyleExtensions.cs

@ -23,11 +23,14 @@ namespace Avalonia.Styling
while (control != null) while (control != null)
{ {
var result = control.Styles.FindResource(name); if (control.IsStylesInitialized)
if (result != AvaloniaProperty.UnsetValue)
{ {
return result; var result = control.Styles.FindResource(name);
if (result != AvaloniaProperty.UnsetValue)
{
return result;
}
} }
control = control.StylingParent; control = control.StylingParent;

5
src/Avalonia.Styling/Styling/Styler.cs

@ -29,7 +29,10 @@ namespace Avalonia.Styling
ApplyStyles(control, parentContainer); ApplyStyles(control, parentContainer);
} }
styleHost.Styles.Attach(control, styleHost); if (styleHost.IsStylesInitialized)
{
styleHost.Styles.Attach(control, styleHost);
}
} }
} }
} }

2
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

2
src/Avalonia.Visuals/Avalonia.Visuals.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RootNamespace>Avalonia</RootNamespace> <RootNamespace>Avalonia</RootNamespace>
</PropertyGroup> </PropertyGroup>

29
src/Avalonia.Visuals/Matrix.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Linq;
namespace Avalonia namespace Avalonia
{ {
@ -295,5 +296,33 @@ namespace Avalonia
((_m21 * _m32) - (_m22 * _m31)) / d, ((_m21 * _m32) - (_m22 * _m31)) / d,
((_m12 * _m31) - (_m11 * _m32)) / d); ((_m12 * _m31) - (_m11 * _m32)) / d);
} }
/// <summary>
/// Parses a <see cref="Matrix"/> string.
/// </summary>
/// <param name="s">The string.</param>
/// <param name="culture">The current culture.</param>
/// <returns>The <see cref="Matrix"/>.</returns>
public static Matrix Parse(string s, CultureInfo culture)
{
var parts = s.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim())
.ToArray();
if (parts.Length == 6)
{
return new Matrix(
double.Parse(parts[0], culture),
double.Parse(parts[1], culture),
double.Parse(parts[2], culture),
double.Parse(parts[3], culture),
double.Parse(parts[4], culture),
double.Parse(parts[5], culture));
}
else
{
throw new FormatException("Invalid Matrix.");
}
}
} }
} }

9
src/Avalonia.Visuals/Media/Drawing.cs

@ -0,0 +1,9 @@
namespace Avalonia.Media
{
public abstract class Drawing : AvaloniaObject
{
public abstract void Draw(DrawingContext context);
public abstract Rect GetBounds();
}
}

58
src/Avalonia.Visuals/Media/DrawingGroup.cs

@ -0,0 +1,58 @@
using Avalonia.Collections;
using Avalonia.Metadata;
namespace Avalonia.Media
{
public class DrawingGroup : Drawing
{
public static readonly StyledProperty<double> OpacityProperty =
AvaloniaProperty.Register<DrawingGroup, double>(nameof(Opacity), 1);
public static readonly StyledProperty<Transform> TransformProperty =
AvaloniaProperty.Register<DrawingGroup, Transform>(nameof(Transform));
public double Opacity
{
get => GetValue(OpacityProperty);
set => SetValue(OpacityProperty, value);
}
public Transform Transform
{
get => GetValue(TransformProperty);
set => SetValue(TransformProperty, value);
}
[Content]
public AvaloniaList<Drawing> Children { get; } = new AvaloniaList<Drawing>();
public override void Draw(DrawingContext context)
{
using (context.PushPreTransform(Transform?.Value ?? Matrix.Identity))
using (context.PushOpacity(Opacity))
{
foreach (var drawing in Children)
{
drawing.Draw(context);
}
}
}
public override Rect GetBounds()
{
var rect = new Rect();
foreach (var drawing in Children)
{
rect = rect.Union(drawing.GetBounds());
}
if (Transform != null)
{
rect = rect.TransformToAABB(Transform.Value);
}
return rect;
}
}
}

51
src/Avalonia.Visuals/Media/EllipseGeometry.cs

@ -11,16 +11,51 @@ namespace Avalonia.Media
/// </summary> /// </summary>
public class EllipseGeometry : Geometry public class EllipseGeometry : Geometry
{ {
/// <summary>
/// Defines the <see cref="Rect"/> property.
/// </summary>
public static readonly StyledProperty<Rect> RectProperty =
AvaloniaProperty.Register<EllipseGeometry, Rect>(nameof(Rect));
public Rect Rect
{
get => GetValue(RectProperty);
set => SetValue(RectProperty, value);
}
static EllipseGeometry()
{
RectProperty.Changed.AddClassHandler<EllipseGeometry>(x => x.RectChanged);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="EllipseGeometry"/> class. /// Initializes a new instance of the <see cref="EllipseGeometry"/> class.
/// </summary> /// </summary>
/// <param name="rect">The rectangle that the ellipse should fill.</param> public EllipseGeometry()
public EllipseGeometry(Rect rect)
{ {
IPlatformRenderInterface factory = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>(); IPlatformRenderInterface factory = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
IStreamGeometryImpl impl = factory.CreateStreamGeometry(); PlatformImpl = factory.CreateStreamGeometry();
}
/// <summary>
/// Initializes a new instance of the <see cref="EllipseGeometry"/> class.
/// </summary>
/// <param name="rect">The rectangle that the ellipse should fill.</param>
public EllipseGeometry(Rect rect) : this()
{
Rect = rect;
}
/// <inheritdoc/>
public override Geometry Clone()
{
return new EllipseGeometry(Rect);
}
using (IStreamGeometryContextImpl ctx = impl.Open()) private void RectChanged(AvaloniaPropertyChangedEventArgs e)
{
var rect = (Rect)e.NewValue;
using (var ctx = ((IStreamGeometryImpl)PlatformImpl).Open())
{ {
double controlPointRatio = (Math.Sqrt(2) - 1) * 4 / 3; double controlPointRatio = (Math.Sqrt(2) - 1) * 4 / 3;
var center = rect.Center; var center = rect.Center;
@ -45,14 +80,6 @@ namespace Avalonia.Media
ctx.CubicBezierTo(new Point(x0, y1), new Point(x1, y0), new Point(x2, y0)); ctx.CubicBezierTo(new Point(x0, y1), new Point(x1, y0), new Point(x2, y0));
ctx.EndFigure(true); ctx.EndFigure(true);
} }
PlatformImpl = impl;
}
/// <inheritdoc/>
public override Geometry Clone()
{
return new EllipseGeometry(Bounds);
} }
} }
} }

43
src/Avalonia.Visuals/Media/GeometryDrawing.cs

@ -0,0 +1,43 @@
namespace Avalonia.Media
{
public class GeometryDrawing : Drawing
{
public static readonly StyledProperty<Geometry> GeometryProperty =
AvaloniaProperty.Register<GeometryDrawing, Geometry>(nameof(Geometry));
public Geometry Geometry
{
get => GetValue(GeometryProperty);
set => SetValue(GeometryProperty, value);
}
public static readonly StyledProperty<IBrush> BrushProperty =
AvaloniaProperty.Register<GeometryDrawing, IBrush>(nameof(Brush), Brushes.Transparent);
public IBrush Brush
{
get => GetValue(BrushProperty);
set => SetValue(BrushProperty, value);
}
public static readonly StyledProperty<Pen> PenProperty =
AvaloniaProperty.Register<GeometryDrawing, Pen>(nameof(Pen));
public Pen Pen
{
get => GetValue(PenProperty);
set => SetValue(PenProperty, value);
}
public override void Draw(DrawingContext context)
{
context.DrawGeometry(Brush, Pen, Geometry);
}
public override Rect GetBounds()
{
// adding the Pen's stroke thickness here could yield wrong results due to transforms
return Geometry?.GetRenderBounds(0) ?? new Rect();
}
}
}

80
src/Avalonia.Visuals/Media/LineGeometry.cs

@ -10,35 +10,89 @@ namespace Avalonia.Media
/// </summary> /// </summary>
public class LineGeometry : Geometry public class LineGeometry : Geometry
{ {
private Point _startPoint; /// <summary>
private Point _endPoint; /// Defines the <see cref="StartPoint"/> property.
/// </summary>
public static readonly StyledProperty<Point> StartPointProperty =
AvaloniaProperty.Register<LineGeometry, Point>(nameof(StartPoint));
public Point StartPoint
{
get => GetValue(StartPointProperty);
set => SetValue(StartPointProperty, value);
}
/// <summary>
/// Defines the <see cref="EndPoint"/> property.
/// </summary>
public static readonly StyledProperty<Point> EndPointProperty =
AvaloniaProperty.Register<LineGeometry, Point>(nameof(EndPoint));
private bool _isDirty;
public Point EndPoint
{
get => GetValue(EndPointProperty);
set => SetValue(EndPointProperty, value);
}
static LineGeometry()
{
StartPointProperty.Changed.AddClassHandler<LineGeometry>(x => x.PointsChanged);
EndPointProperty.Changed.AddClassHandler<LineGeometry>(x => x.PointsChanged);
}
/// <summary>
/// Initializes a new instance of the <see cref="LineGeometry"/> class.
/// </summary>
public LineGeometry()
{
IPlatformRenderInterface factory = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
PlatformImpl = factory.CreateStreamGeometry();
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LineGeometry"/> class. /// Initializes a new instance of the <see cref="LineGeometry"/> class.
/// </summary> /// </summary>
/// <param name="startPoint">The start point.</param> /// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param> /// <param name="endPoint">The end point.</param>
public LineGeometry(Point startPoint, Point endPoint) public LineGeometry(Point startPoint, Point endPoint) : this()
{ {
_startPoint = startPoint; StartPoint = startPoint;
_endPoint = endPoint; EndPoint = endPoint;
IPlatformRenderInterface factory = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>(); }
IStreamGeometryImpl impl = factory.CreateStreamGeometry();
using (IStreamGeometryContextImpl context = impl.Open()) public override IGeometryImpl PlatformImpl
{
get
{ {
context.BeginFigure(_startPoint, false); PrepareIfNeeded();
context.LineTo(_endPoint); return base.PlatformImpl;
context.EndFigure(false);
} }
protected set => base.PlatformImpl = value;
}
PlatformImpl = impl; public void PrepareIfNeeded()
{
if (_isDirty)
{
_isDirty = false;
using (var context = ((IStreamGeometryImpl)PlatformImpl).Open())
{
context.BeginFigure(StartPoint, false);
context.LineTo(EndPoint);
context.EndFigure(false);
}
}
} }
/// <inheritdoc/> /// <inheritdoc/>
public override Geometry Clone() public override Geometry Clone()
{ {
return new LineGeometry(_startPoint, _endPoint); PrepareIfNeeded();
return new LineGeometry(StartPoint, EndPoint);
} }
private void PointsChanged(AvaloniaPropertyChangedEventArgs e) => _isDirty = true;
} }
} }

3
src/Avalonia.Visuals/Media/PathMarkupParser.cs

@ -126,7 +126,9 @@ namespace Avalonia.Media
case Command.CubicBezierCurve: case Command.CubicBezierCurve:
{ {
Point point1 = ReadPoint(reader, point, relative); Point point1 = ReadPoint(reader, point, relative);
ReadSeparator(reader);
Point point2 = ReadPoint(reader, point, relative); Point point2 = ReadPoint(reader, point, relative);
ReadSeparator(reader);
point = ReadPoint(reader, point, relative); point = ReadPoint(reader, point, relative);
_context.CubicBezierTo(point1, point2, point); _context.CubicBezierTo(point1, point2, point);
break; break;
@ -141,6 +143,7 @@ namespace Avalonia.Media
bool isLargeArc = ReadBool(reader); bool isLargeArc = ReadBool(reader);
ReadSeparator(reader); ReadSeparator(reader);
SweepDirection sweepDirection = ReadBool(reader) ? SweepDirection.Clockwise : SweepDirection.CounterClockwise; SweepDirection sweepDirection = ReadBool(reader) ? SweepDirection.Clockwise : SweepDirection.CounterClockwise;
ReadSeparator(reader);
point = ReadPoint(reader, point, relative); point = ReadPoint(reader, point, relative);
_context.ArcTo(point, size, rotationAngle, isLargeArc, sweepDirection); _context.ArcTo(point, size, rotationAngle, isLargeArc, sweepDirection);

115
src/Avalonia.Visuals/Media/PolylineGeometry.cs

@ -3,10 +3,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Metadata;
using Avalonia.Collections;
namespace Avalonia.Media namespace Avalonia.Media
{ {
@ -15,36 +14,118 @@ namespace Avalonia.Media
/// </summary> /// </summary>
public class PolylineGeometry : Geometry public class PolylineGeometry : Geometry
{ {
private IList<Point> _points; /// <summary>
private bool _isFilled; /// Defines the <see cref="Points"/> property.
/// </summary>
public static readonly DirectProperty<PolylineGeometry, Points> PointsProperty =
AvaloniaProperty.RegisterDirect<PolylineGeometry, Points>(nameof(Points), g => g.Points, (g, f) => g.Points = f);
public PolylineGeometry(IList<Point> points, bool isFilled) /// <summary>
/// Defines the <see cref="IsFilled"/> property.
/// </summary>
public static readonly AvaloniaProperty<bool> IsFilledProperty =
AvaloniaProperty.Register<PolylineGeometry, bool>(nameof(IsFilled));
private Points _points;
private bool _isDirty;
private IDisposable _pointsObserver;
static PolylineGeometry()
{
PointsProperty.Changed.AddClassHandler<PolylineGeometry>((s, e) =>
s.OnPointsChanged(e.OldValue as Points, e.NewValue as Points));
IsFilledProperty.Changed.AddClassHandler<PolylineGeometry>((s, _) => s.NotifyChanged());
}
/// <summary>
/// Initializes a new instance of the <see cref="PolylineGeometry"/> class.
/// </summary>
public PolylineGeometry()
{ {
_points = points;
_isFilled = isFilled;
IPlatformRenderInterface factory = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>(); IPlatformRenderInterface factory = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
IStreamGeometryImpl impl = factory.CreateStreamGeometry(); PlatformImpl = factory.CreateStreamGeometry();
Points = new Points();
}
using (IStreamGeometryContextImpl context = impl.Open()) /// <summary>
/// Initializes a new instance of the <see cref="PolylineGeometry"/> class.
/// </summary>
public PolylineGeometry(IEnumerable<Point> points, bool isFilled) : this()
{
Points.AddRange(points);
IsFilled = isFilled;
}
public void PrepareIfNeeded()
{
if (_isDirty)
{ {
if (points.Count > 0) _isDirty = false;
using (var context = ((IStreamGeometryImpl)PlatformImpl).Open())
{ {
context.BeginFigure(points[0], isFilled); var points = Points;
for (int i = 1; i < points.Count; i++) var isFilled = IsFilled;
if (points.Count > 0)
{ {
context.LineTo(points[i]); context.BeginFigure(points[0], isFilled);
for (int i = 1; i < points.Count; i++)
{
context.LineTo(points[i]);
}
context.EndFigure(isFilled);
} }
context.EndFigure(isFilled);
} }
} }
}
PlatformImpl = impl; /// <summary>
/// Gets or sets the figures.
/// </summary>
/// <value>
/// The points.
/// </value>
[Content]
public Points Points
{
get => _points;
set => SetAndRaise(PointsProperty, ref _points, value);
}
public bool IsFilled
{
get => GetValue(IsFilledProperty);
set => SetValue(IsFilledProperty, value);
}
public override IGeometryImpl PlatformImpl
{
get
{
PrepareIfNeeded();
return base.PlatformImpl;
}
protected set => base.PlatformImpl = value;
} }
/// <inheritdoc/> /// <inheritdoc/>
public override Geometry Clone() public override Geometry Clone()
{ {
return new PolylineGeometry(new List<Point>(_points), _isFilled); PrepareIfNeeded();
return new PolylineGeometry(Points, IsFilled);
}
private void OnPointsChanged(Points oldValue, Points newValue)
{
_pointsObserver?.Dispose();
_pointsObserver = newValue?.ForEachItem(f => NotifyChanged(), f => NotifyChanged(), () => NotifyChanged());
}
internal void NotifyChanged()
{
_isDirty = true;
} }
} }
} }

51
src/Avalonia.Visuals/Media/RectangleGeometry.cs

@ -10,16 +10,51 @@ namespace Avalonia.Media
/// </summary> /// </summary>
public class RectangleGeometry : Geometry public class RectangleGeometry : Geometry
{ {
/// <summary>
/// Defines the <see cref="Rect"/> property.
/// </summary>
public static readonly StyledProperty<Rect> RectProperty =
AvaloniaProperty.Register<RectangleGeometry, Rect>(nameof(Rect));
public Rect Rect
{
get => GetValue(RectProperty);
set => SetValue(RectProperty, value);
}
static RectangleGeometry()
{
RectProperty.Changed.AddClassHandler<RectangleGeometry>(x => x.RectChanged);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RectangleGeometry"/> class. /// Initializes a new instance of the <see cref="RectangleGeometry"/> class.
/// </summary> /// </summary>
/// <param name="rect">The rectangle bounds.</param> public RectangleGeometry()
public RectangleGeometry(Rect rect)
{ {
IPlatformRenderInterface factory = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>(); IPlatformRenderInterface factory = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
IStreamGeometryImpl impl = factory.CreateStreamGeometry(); PlatformImpl = factory.CreateStreamGeometry();
}
/// <summary>
/// Initializes a new instance of the <see cref="RectangleGeometry"/> class.
/// </summary>
/// <param name="rect">The rectangle bounds.</param>
public RectangleGeometry(Rect rect) : this()
{
Rect = rect;
}
/// <inheritdoc/>
public override Geometry Clone()
{
return new RectangleGeometry(Rect);
}
using (IStreamGeometryContextImpl context = impl.Open()) private void RectChanged(AvaloniaPropertyChangedEventArgs e)
{
var rect = (Rect)e.NewValue;
using (var context = ((IStreamGeometryImpl)PlatformImpl).Open())
{ {
context.BeginFigure(rect.TopLeft, true); context.BeginFigure(rect.TopLeft, true);
context.LineTo(rect.TopRight); context.LineTo(rect.TopRight);
@ -27,14 +62,6 @@ namespace Avalonia.Media
context.LineTo(rect.BottomLeft); context.LineTo(rect.BottomLeft);
context.EndFigure(true); context.EndFigure(true);
} }
PlatformImpl = impl;
}
/// <inheritdoc/>
public override Geometry Clone()
{
return new RectangleGeometry(Bounds);
} }
} }
} }

2
src/Avalonia.Visuals/Point.cs

@ -183,7 +183,7 @@ namespace Avalonia
} }
else else
{ {
throw new FormatException("Invalid Thickness."); throw new FormatException("Invalid Point.");
} }
} }

9
src/Avalonia.Visuals/Points.cs

@ -0,0 +1,9 @@
// 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.Collections;
namespace Avalonia
{
public sealed class Points : AvaloniaList<Point> { }
}

26
src/Avalonia.Visuals/Rect.cs

@ -481,5 +481,31 @@ namespace Avalonia
_width, _width,
_height); _height);
} }
/// <summary>
/// Parses a <see cref="Rect"/> string.
/// </summary>
/// <param name="s">The string.</param>
/// <param name="culture">The current culture.</param>
/// <returns>The parsed <see cref="Rect"/>.</returns>
public static Rect Parse(string s, CultureInfo culture)
{
var parts = s.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim())
.ToList();
if (parts.Count == 4)
{
return new Rect(
double.Parse(parts[0], culture),
double.Parse(parts[1], culture),
double.Parse(parts[2], culture),
double.Parse(parts[3], culture));
}
else
{
throw new FormatException("Invalid Rect.");
}
}
} }
} }

2
src/Avalonia.Visuals/RelativeRect.cs

@ -203,7 +203,7 @@ namespace Avalonia
} }
else else
{ {
throw new FormatException("Invalid Rect."); throw new FormatException("Invalid RelativeRect.");
} }
} }
} }

63
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using Avalonia.Media.Immutable; using Avalonia.Media.Immutable;
using System.Threading; using System.Threading;
using System.Linq;
namespace Avalonia.Rendering namespace Avalonia.Rendering
{ {
@ -58,7 +59,6 @@ namespace Avalonia.Rendering
_dispatcher = dispatcher ?? Dispatcher.UIThread; _dispatcher = dispatcher ?? Dispatcher.UIThread;
_root = root; _root = root;
_sceneBuilder = sceneBuilder ?? new SceneBuilder(); _sceneBuilder = sceneBuilder ?? new SceneBuilder();
_scene = new Scene(root);
_layerFactory = layerFactory ?? new DefaultRenderLayerFactory(); _layerFactory = layerFactory ?? new DefaultRenderLayerFactory();
_layers = new RenderLayers(_layerFactory); _layers = new RenderLayers(_layerFactory);
_renderLoop = renderLoop; _renderLoop = renderLoop;
@ -86,7 +86,6 @@ namespace Avalonia.Rendering
_root = root; _root = root;
_renderTarget = renderTarget; _renderTarget = renderTarget;
_sceneBuilder = sceneBuilder ?? new SceneBuilder(); _sceneBuilder = sceneBuilder ?? new SceneBuilder();
_scene = new Scene(root);
_layerFactory = layerFactory ?? new DefaultRenderLayerFactory(); _layerFactory = layerFactory ?? new DefaultRenderLayerFactory();
_layers = new RenderLayers(_layerFactory); _layers = new RenderLayers(_layerFactory);
} }
@ -122,7 +121,7 @@ namespace Avalonia.Rendering
UpdateScene(); UpdateScene();
} }
return _scene.HitTest(p, filter); return _scene?.HitTest(p, filter) ?? Enumerable.Empty<IVisual>();
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -178,9 +177,15 @@ namespace Avalonia.Rendering
private void Render(Scene scene) private void Render(Scene scene)
{ {
_dirtyRectsDisplay.Tick(); bool renderOverlay = DrawDirtyRects || DrawFps;
bool composite = false;
if (scene.Size != Size.Empty) if (renderOverlay)
{
_dirtyRectsDisplay.Tick();
}
if (scene != null && scene.Size != Size.Empty)
{ {
if (scene.Generation != _lastSceneId) if (scene.Generation != _lastSceneId)
{ {
@ -193,10 +198,19 @@ namespace Avalonia.Rendering
} }
_lastSceneId = scene.Generation; _lastSceneId = scene.Generation;
composite = true;
} }
RenderOverlay(scene); if (renderOverlay)
RenderComposite(scene); {
RenderOverlay(scene);
RenderComposite(scene);
}
else if(composite)
{
RenderComposite(scene);
}
} }
} }
@ -351,25 +365,32 @@ namespace Avalonia.Rendering
try try
{ {
var scene = _scene.Clone(); if (_root.IsVisible)
if (_dirty == null)
{
_dirty = new DirtyVisuals();
_sceneBuilder.UpdateAll(scene);
}
else if (_dirty.Count > 0)
{ {
foreach (var visual in _dirty) var scene = _scene?.Clone() ?? new Scene(_root);
if (_dirty == null)
{ {
_sceneBuilder.Update(scene, visual); _dirty = new DirtyVisuals();
_sceneBuilder.UpdateAll(scene);
}
else if (_dirty.Count > 0)
{
foreach (var visual in _dirty)
{
_sceneBuilder.Update(scene, visual);
}
} }
}
Interlocked.Exchange(ref _scene, scene); Interlocked.Exchange(ref _scene, scene);
_dirty.Clear(); _dirty.Clear();
(_root as IRenderRoot)?.Invalidate(new Rect(scene.Size)); (_root as IRenderRoot)?.Invalidate(new Rect(scene.Size));
}
else
{
Interlocked.Exchange(ref _scene, null);
}
} }
finally finally
{ {

6
src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs

@ -36,8 +36,14 @@ namespace Avalonia.Rendering.SceneGraph
{ {
Contract.Requires<ArgumentNullException>(scene != null); Contract.Requires<ArgumentNullException>(scene != null);
Contract.Requires<ArgumentNullException>(visual != null); Contract.Requires<ArgumentNullException>(visual != null);
Dispatcher.UIThread.VerifyAccess(); Dispatcher.UIThread.VerifyAccess();
if (!scene.Root.Visual.IsVisible)
{
throw new AvaloniaInternalException("Cannot update the scene for an invisible root visual.");
}
var node = (VisualNode)scene.FindNode(visual); var node = (VisualNode)scene.FindNode(visual);
if (visual == scene.Root.Visual) if (visual == scene.Root.Visual)

3
src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj

@ -47,6 +47,9 @@
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" /> <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="CairoPlatform.cs" /> <Compile Include="CairoPlatform.cs" />
<Compile Include="Media\DrawingContext.cs" /> <Compile Include="Media\DrawingContext.cs" />
<Compile Include="Media\FormattedTextImpl.cs" /> <Compile Include="Media\FormattedTextImpl.cs" />

20
src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs

@ -11,13 +11,6 @@ using System.Runtime.InteropServices;
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("Avalonia.Cairo")] [assembly: AssemblyTitle("Avalonia.Cairo")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Avalonia.Cairo")]
[assembly: AssemblyCopyright("Copyright \u00A9 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible // 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 // to COM components. If you need to access a type in this assembly from
@ -27,19 +20,6 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM // The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f999ba8b-64e7-40cc-98a4-003f1852d2a3")] [assembly: Guid("f999ba8b-64e7-40cc-98a4-003f1852d2a3")]
// 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")]
[assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 3, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")] [assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 3, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")]
[assembly: ExportRenderingSubsystem(OperatingSystemType.Linux, 2, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")] [assembly: ExportRenderingSubsystem(OperatingSystemType.Linux, 2, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")]
[assembly: ExportRenderingSubsystem(OperatingSystemType.OSX, 3, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")] [assembly: ExportRenderingSubsystem(OperatingSystemType.OSX, 3, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")]

3
src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj

@ -39,6 +39,9 @@
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" /> <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="ClipboardImpl.cs" /> <Compile Include="ClipboardImpl.cs" />
<Compile Include="EmbeddableImpl.cs" /> <Compile Include="EmbeddableImpl.cs" />
<Compile Include="Embedding\GtkAvaloniaControlHost.cs" /> <Compile Include="Embedding\GtkAvaloniaControlHost.cs" />

13
src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs

@ -4,23 +4,10 @@
using Avalonia.Gtk; using Avalonia.Gtk;
using Avalonia.Platform; using Avalonia.Platform;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes. // Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project. // Change them to the values specific to your project.
[assembly: AssemblyTitle("Avalonia.Gtk")] [assembly: AssemblyTitle("Avalonia.Gtk")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("steven")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
[assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 3, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))] [assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 3, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))]
[assembly: ExportWindowingSubsystem(OperatingSystemType.Linux, 2, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))] [assembly: ExportWindowingSubsystem(OperatingSystemType.Linux, 2, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))]

3
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems> <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup> </PropertyGroup>
@ -24,6 +24,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
<Compile Include="..\Avalonia.Gtk\KeyTransform.cs"> <Compile Include="..\Avalonia.Gtk\KeyTransform.cs">
<Link>KeyTransform.cs</Link> <Link>KeyTransform.cs</Link>
</Compile> </Compile>

16
src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs

@ -104,14 +104,16 @@ namespace Avalonia.Gtk3.Interop
var path = Custom?.Lookup(dll); var path = Custom?.Lookup(dll);
if (path == null && Custom?.BasePath != null) if (path == null && Custom?.BasePath != null)
path = Path.Combine(Custom.BasePath, name); path = Path.Combine(Custom.BasePath, name);
if (path != null)
try
{
return loader.LoadLibrary(path);
}
catch (Exception e)
{ {
exceptions.Add(e); try
{
return loader.LoadLibrary(path);
}
catch (Exception e)
{
exceptions.Add(e);
}
} }
throw new AggregateException("Unable to load " + dll, exceptions); throw new AggregateException("Unable to load " + dll, exceptions);
} }

2
src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs

@ -36,6 +36,8 @@ namespace Avalonia.Gtk3.Interop
public static unsafe string StringFromPtr(IntPtr s) public static unsafe string StringFromPtr(IntPtr s)
{ {
var pstr = (byte*)s; var pstr = (byte*)s;
if (pstr == null)
return null;
int len; int len;
for (len = 0; pstr[len] != 0; len++) ; for (len = 0; pstr[len] != 0; len++) ;
var bytes = new byte[len]; var bytes = new byte[len];

25
src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs

@ -1,7 +1,4 @@
using System.Resources; using System.Reflection;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Avalonia.Gtk3; using Avalonia.Gtk3;
using Avalonia.Platform; using Avalonia.Platform;
@ -9,27 +6,7 @@ using Avalonia.Platform;
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("Avalonia.Gtk3")] [assembly: AssemblyTitle("Avalonia.Gtk3")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Avalonia.Gtk3")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]
// 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")]
[assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 2, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))] [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.Linux, 1, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]
[assembly: ExportWindowingSubsystem(OperatingSystemType.OSX, 2, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))] [assembly: ExportWindowingSubsystem(OperatingSystemType.OSX, 2, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]

2
src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

1
src/Linux/Avalonia.LinuxFramebuffer/NativeUnsafeMethods.cs

@ -72,6 +72,7 @@ namespace Avalonia.LinuxFramebuffer
FB_VBLANK_HAVE_VSYNC = 0x100 /* verical syncs can be detected */ FB_VBLANK_HAVE_VSYNC = 0x100 /* verical syncs can be detected */
} }
[StructLayout(LayoutKind.Sequential)]
unsafe struct fb_vblank { unsafe struct fb_vblank {
public VBlankFlags flags; /* FB_VBLANK flags */ public VBlankFlags flags; /* FB_VBLANK flags */
__u32 count; /* counter of retraces since boot */ __u32 count; /* counter of retraces since boot */

5
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems> <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<EnableDefaultItems>false</EnableDefaultItems> <EnableDefaultItems>false</EnableDefaultItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
@ -31,6 +31,8 @@
</Compile> </Compile>
<Compile Include="AvaloniaXamlLoaderPortableXaml.cs" /> <Compile Include="AvaloniaXamlLoaderPortableXaml.cs" />
<Compile Include="AvaloniaXamlLoader.cs" /> <Compile Include="AvaloniaXamlLoader.cs" />
<Compile Include="Converters\MatrixTypeConverter.cs" />
<Compile Include="Converters\RectTypeConverter.cs" />
<Compile Include="Converters\SetterValueTypeConverter.cs" /> <Compile Include="Converters\SetterValueTypeConverter.cs" />
<Compile Include="MarkupExtensions\StyleIncludeExtension.cs" /> <Compile Include="MarkupExtensions\StyleIncludeExtension.cs" />
<Compile Include="PortableXaml\AvaloniaXamlContext.cs" /> <Compile Include="PortableXaml\AvaloniaXamlContext.cs" />
@ -92,6 +94,7 @@
<Compile Include="Templates\TemplateLoader.cs" /> <Compile Include="Templates\TemplateLoader.cs" />
<Compile Include="Templates\TreeDataTemplate.cs" /> <Compile Include="Templates\TreeDataTemplate.cs" />
<Compile Include="PortableXaml\portable.xaml.github\src\Portable.Xaml\**\*.cs" Exclude="PortableXaml\portable.xaml.github\src\Portable.Xaml\Assembly\**\*.cs" /> <Compile Include="PortableXaml\portable.xaml.github\src\Portable.Xaml\**\*.cs" Exclude="PortableXaml\portable.xaml.github\src\Portable.Xaml\Assembly\**\*.cs" />
<Compile Remove="**\UriTypeConverter.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj" /> <ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj" />

23
src/Markup/Avalonia.Markup.Xaml/Converters/MatrixTypeConverter.cs

@ -0,0 +1,23 @@
// 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;
using System.Globalization;
namespace Avalonia.Markup.Xaml.Converters
{
using System.ComponentModel;
public class MatrixTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return Matrix.Parse((string)value, culture);
}
}
}

23
src/Markup/Avalonia.Markup.Xaml/Converters/RectTypeConverter.cs

@ -0,0 +1,23 @@
// 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;
using System.Globalization;
namespace Avalonia.Markup.Xaml.Converters
{
using System.ComponentModel;
public class RectTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return Rect.Parse((string)value, culture);
}
}
}

2
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaDefaultTypeConverters.cs

@ -32,12 +32,14 @@ namespace Avalonia.Markup.Xaml.PortableXaml
{ typeof(AvaloniaList<double>), typeof(AvaloniaListTypeConverter<double>) }, { typeof(AvaloniaList<double>), typeof(AvaloniaListTypeConverter<double>) },
{ typeof(IMemberSelector), typeof(MemberSelectorTypeConverter) }, { typeof(IMemberSelector), typeof(MemberSelectorTypeConverter) },
{ typeof(Point), typeof(PointTypeConverter) }, { typeof(Point), typeof(PointTypeConverter) },
{ typeof(Matrix), typeof(MatrixTypeConverter) },
{ typeof(IList<Point>), typeof(PointsListTypeConverter) }, { typeof(IList<Point>), typeof(PointsListTypeConverter) },
{ typeof(AvaloniaProperty), typeof(AvaloniaPropertyTypeConverter) }, { typeof(AvaloniaProperty), typeof(AvaloniaPropertyTypeConverter) },
{ typeof(RelativePoint), typeof(RelativePointTypeConverter) }, { typeof(RelativePoint), typeof(RelativePointTypeConverter) },
{ typeof(RelativeRect), typeof(RelativeRectTypeConverter) }, { typeof(RelativeRect), typeof(RelativeRectTypeConverter) },
{ typeof(RowDefinitions), typeof(RowDefinitionsTypeConverter) }, { typeof(RowDefinitions), typeof(RowDefinitionsTypeConverter) },
{ typeof(Size), typeof(SizeTypeConverter) }, { typeof(Size), typeof(SizeTypeConverter) },
{ typeof(Rect), typeof(RectTypeConverter) },
{ typeof(Selector), typeof(SelectorTypeConverter)}, { typeof(Selector), typeof(SelectorTypeConverter)},
{ typeof(SolidColorBrush), typeof(BrushTypeConverter) }, { typeof(SolidColorBrush), typeof(BrushTypeConverter) },
{ typeof(Thickness), typeof(ThicknessTypeConverter) }, { typeof(Thickness), typeof(ThicknessTypeConverter) },

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

Loading…
Cancel
Save