327 changed files with 13348 additions and 2208 deletions
@ -1,16 +1,31 @@ |
|||||
This template is not intended to be prescriptive, but to help us review pull requests it would be useful if you included as much of the following information as possible: |
## What does the pull request do? |
||||
|
|
||||
- What does the pull request do? |
Give a bit of background on the PR here, together with links to with related issues etc. |
||||
- What is the current behavior? |
|
||||
- What is the updated/expected behavior with this PR? |
|
||||
- How was the solution implemented (if it's not obvious)? |
|
||||
|
|
||||
Checklist: |
## What is the current behavior? |
||||
|
|
||||
|
If the PR is a fix, describe the current incorrect behavior, otherwise delete this section. |
||||
|
|
||||
|
## What is the updated/expected behavior with this PR? |
||||
|
|
||||
|
Describe how to test the PR. |
||||
|
|
||||
|
## How was the solution implemented (if it's not obvious)? |
||||
|
|
||||
|
Include any information that might be of use to a reviewer here. |
||||
|
|
||||
|
## Checklist |
||||
|
|
||||
- [ ] Added unit tests (if possible)? |
- [ ] Added unit tests (if possible)? |
||||
- [ ] Added XML documentation to any related classes? |
- [ ] Added XML documentation to any related classes? |
||||
- [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Avaloniaui.net with user documentation |
- [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Avaloniaui.net with user documentation |
||||
|
|
||||
|
## Breaking changes |
||||
|
|
||||
|
List any breaking changes here. When the PR is merged please add an entry to https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes |
||||
|
|
||||
|
## Fixed issues |
||||
|
|
||||
If the pull request fixes issue(s) list them like this: |
If the pull request fixes issue(s) list them like this: |
||||
|
|
||||
Fixes #123 |
Fixes #123 |
||||
|
|||||
@ -1,3 +1,6 @@ |
|||||
[submodule "src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github"] |
[submodule "src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github"] |
||||
path = src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github |
path = src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github |
||||
url = https://github.com/AvaloniaUI/Portable.Xaml.git |
url = https://github.com/AvaloniaUI/Portable.Xaml.git |
||||
|
[submodule "nukebuild/Numerge"] |
||||
|
path = nukebuild/Numerge |
||||
|
url = https://github.com/kekekeks/Numerge.git |
||||
|
|||||
@ -0,0 +1,5 @@ |
|||||
|
<ProjectConfiguration> |
||||
|
<Settings> |
||||
|
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely> |
||||
|
</Settings> |
||||
|
</ProjectConfiguration> |
||||
@ -0,0 +1,5 @@ |
|||||
|
<ProjectConfiguration> |
||||
|
<Settings> |
||||
|
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely> |
||||
|
</Settings> |
||||
|
</ProjectConfiguration> |
||||
@ -1,24 +0,0 @@ |
|||||
language: csharp |
|
||||
os: |
|
||||
- linux |
|
||||
dist: trusty |
|
||||
osx_image: xcode8.3 |
|
||||
env: |
|
||||
global: |
|
||||
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 |
|
||||
- DOTNET_CLI_TELEMETRY_OPTOUT=1 |
|
||||
mono: |
|
||||
- 5.2.0 |
|
||||
dotnet: 2.1.200 |
|
||||
script: |
|
||||
- sudo apt-get update |
|
||||
- sudo apt-get install castxml |
|
||||
- ./build.sh --target "Travis" --configuration "Release" |
|
||||
notifications: |
|
||||
email: false |
|
||||
webhooks: |
|
||||
urls: |
|
||||
- https://webhooks.gitter.im/e/98f653320ef2b7506c05 |
|
||||
on_success: change |
|
||||
on_failure: always |
|
||||
on_start: never |
|
||||
@ -1,5 +1,5 @@ |
|||||
<Project> |
<Project> |
||||
<PropertyGroup> |
<PropertyGroup> |
||||
<PackageOutputPath Condition="'$(PackageOutputPath)' == ''">$(MSBuildThisFileDirectory)artifacts/nuget</PackageOutputPath> |
<PackageOutputPath Condition="'$(PackageOutputPath)' == ''">$(MSBuildThisFileDirectory)build-intermediate/nuget</PackageOutputPath> |
||||
</PropertyGroup> |
</PropertyGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,23 +0,0 @@ |
|||||
os: Visual Studio 2017 |
|
||||
skip_branch_with_pr: true |
|
||||
configuration: |
|
||||
- Release |
|
||||
environment: |
|
||||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 |
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1 |
|
||||
NUGET_API_URL: https://www.nuget.org/api/v2/package |
|
||||
MYGET_API_KEY: |
|
||||
secure: OtVfyN3ErqQrDTnWH2HDfJDlCiu/i4/X4wFmK3ZXXP7HmCiXYPSbTjMPwwdOxRaK |
|
||||
MYGET_API_URL: https://www.myget.org/F/avalonia-ci/api/v2/package |
|
||||
init: |
|
||||
- ps: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")} |
|
||||
before_build: |
|
||||
- git submodule update --init |
|
||||
build_script: |
|
||||
- ps: .\build.ps1 -Target "AppVeyor" -Configuration "$env:configuration" |
|
||||
|
|
||||
test: off |
|
||||
artifacts: |
|
||||
- path: artifacts\nuget\*.nupkg |
|
||||
- path: artifacts\zip\*.zip |
|
||||
- path: artifacts\inspectcode.xml |
|
||||
@ -1,312 +0,0 @@ |
|||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
// TOOLS |
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
#tool "nuget:?package=NuGet.CommandLine&version=4.7.1" |
|
||||
#tool "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.2.3" |
|
||||
#tool "nuget:?package=xunit.runner.console&version=2.3.1" |
|
||||
#tool "nuget:?package=JetBrains.dotMemoryUnit&version=3.0.20171219.105559" |
|
||||
|
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
// USINGS |
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
using System; |
|
||||
using System.Collections; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
|
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
// SCRIPTS |
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
#load "./parameters.cake" |
|
||||
|
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
// SETUP |
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
Setup<Parameters>(context => |
|
||||
{ |
|
||||
var parameters = new Parameters(context); |
|
||||
|
|
||||
Information("Building version {0} of Avalonia ({1}) using version {2} of Cake.", |
|
||||
parameters.Version, |
|
||||
parameters.Configuration, |
|
||||
typeof(ICakeContext).Assembly.GetName().Version.ToString()); |
|
||||
|
|
||||
if (parameters.IsRunningOnAppVeyor) |
|
||||
{ |
|
||||
Information("Repository Name: " + BuildSystem.AppVeyor.Environment.Repository.Name); |
|
||||
Information("Repository Branch: " + BuildSystem.AppVeyor.Environment.Repository.Branch); |
|
||||
} |
|
||||
Information("Target:" + context.TargetTask.Name); |
|
||||
Information("Configuration: " + parameters.Configuration); |
|
||||
Information("IsLocalBuild: " + parameters.IsLocalBuild); |
|
||||
Information("IsRunningOnUnix: " + parameters.IsRunningOnUnix); |
|
||||
Information("IsRunningOnWindows: " + parameters.IsRunningOnWindows); |
|
||||
Information("IsRunningOnAppVeyor: " + parameters.IsRunningOnAppVeyor); |
|
||||
Information("IsRunnongOnAzure:" + parameters.IsRunningOnAzure); |
|
||||
Information("IsPullRequest: " + parameters.IsPullRequest); |
|
||||
Information("IsMainRepo: " + parameters.IsMainRepo); |
|
||||
Information("IsMasterBranch: " + parameters.IsMasterBranch); |
|
||||
Information("IsReleaseBranch: " + parameters.IsReleaseBranch); |
|
||||
Information("IsTagged: " + parameters.IsTagged); |
|
||||
Information("IsReleasable: " + parameters.IsReleasable); |
|
||||
Information("IsMyGetRelease: " + parameters.IsMyGetRelease); |
|
||||
Information("IsNuGetRelease: " + parameters.IsNuGetRelease); |
|
||||
|
|
||||
return parameters; |
|
||||
}); |
|
||||
|
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
// TEARDOWN |
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
Teardown<Parameters>((context, buildContext) => |
|
||||
{ |
|
||||
Information("Finished running tasks."); |
|
||||
}); |
|
||||
|
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
// TASKS |
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
Task("Clean-Impl") |
|
||||
.Does<Parameters>(data => |
|
||||
{ |
|
||||
CleanDirectories(data.BuildDirs); |
|
||||
CleanDirectory(data.ArtifactsDir); |
|
||||
CleanDirectory(data.NugetRoot); |
|
||||
CleanDirectory(data.ZipRoot); |
|
||||
CleanDirectory(data.TestResultsRoot); |
|
||||
}); |
|
||||
|
|
||||
void DotNetCoreBuild(Parameters parameters) |
|
||||
{ |
|
||||
var settings = new DotNetCoreBuildSettings |
|
||||
{ |
|
||||
Configuration = parameters.Configuration, |
|
||||
MSBuildSettings = new DotNetCoreMSBuildSettings |
|
||||
{ |
|
||||
Properties = |
|
||||
{ |
|
||||
{ "PackageVersion", new [] { parameters.Version } } |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
DotNetCoreBuild(parameters.MSBuildSolution, settings); |
|
||||
} |
|
||||
|
|
||||
Task("Build-Impl") |
|
||||
.Does<Parameters>(data => |
|
||||
{ |
|
||||
if(data.IsRunningOnWindows) |
|
||||
{ |
|
||||
MSBuild(data.MSBuildSolution, settings => { |
|
||||
settings.SetConfiguration(data.Configuration); |
|
||||
settings.SetVerbosity(Verbosity.Minimal); |
|
||||
settings.WithProperty("iOSRoslynPathHackRequired", "true"); |
|
||||
settings.WithProperty("PackageVersion", data.Version); |
|
||||
settings.UseToolVersion(MSBuildToolVersion.VS2017); |
|
||||
settings.WithRestore(); |
|
||||
}); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
DotNetCoreBuild(data); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
void RunCoreTest(string project, Parameters parameters, bool coreOnly = false) |
|
||||
{ |
|
||||
if(!project.EndsWith(".csproj")) |
|
||||
project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj"); |
|
||||
Information("Running tests from " + project); |
|
||||
var frameworks = new List<string>(){"netcoreapp2.0"}; |
|
||||
foreach(var fw in frameworks) |
|
||||
{ |
|
||||
if(!fw.StartsWith("netcoreapp") && coreOnly) |
|
||||
continue; |
|
||||
Information("Running for " + fw); |
|
||||
|
|
||||
var settings = new DotNetCoreTestSettings { |
|
||||
Configuration = parameters.Configuration, |
|
||||
Framework = fw, |
|
||||
NoBuild = true, |
|
||||
NoRestore = true |
|
||||
}; |
|
||||
|
|
||||
if (parameters.PublishTestResults) |
|
||||
{ |
|
||||
settings.Logger = "trx"; |
|
||||
settings.ResultsDirectory = parameters.TestResultsRoot; |
|
||||
} |
|
||||
|
|
||||
DotNetCoreTest(project, settings); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
Task("Run-Unit-Tests-Impl") |
|
||||
.WithCriteria<Parameters>((context, data) => !data.SkipTests) |
|
||||
.Does<Parameters>(data => |
|
||||
{ |
|
||||
RunCoreTest("./tests/Avalonia.Base.UnitTests", data, false); |
|
||||
RunCoreTest("./tests/Avalonia.Controls.UnitTests", data, false); |
|
||||
RunCoreTest("./tests/Avalonia.Input.UnitTests", data, false); |
|
||||
RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", data, false); |
|
||||
RunCoreTest("./tests/Avalonia.Layout.UnitTests", data, false); |
|
||||
RunCoreTest("./tests/Avalonia.Markup.UnitTests", data, false); |
|
||||
RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", data, false); |
|
||||
RunCoreTest("./tests/Avalonia.Styling.UnitTests", data, false); |
|
||||
RunCoreTest("./tests/Avalonia.Visuals.UnitTests", data, false); |
|
||||
RunCoreTest("./tests/Avalonia.Skia.UnitTests", data, false); |
|
||||
RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests", data, false); |
|
||||
if (data.IsRunningOnWindows) |
|
||||
{ |
|
||||
RunCoreTest("./tests/Avalonia.Direct2D1.UnitTests", data, false); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
Task("Run-Designer-Tests-Impl") |
|
||||
.WithCriteria<Parameters>((context, data) => !data.SkipTests) |
|
||||
.Does<Parameters>(data => |
|
||||
{ |
|
||||
RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", data, false); |
|
||||
}); |
|
||||
|
|
||||
Task("Run-Render-Tests-Impl") |
|
||||
.WithCriteria<Parameters>((context, data) => !data.SkipTests) |
|
||||
.WithCriteria<Parameters>((context, data) => data.IsRunningOnWindows) |
|
||||
.Does<Parameters>(data => |
|
||||
{ |
|
||||
RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", data, true); |
|
||||
RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", data, true); |
|
||||
}); |
|
||||
|
|
||||
Task("Run-Leak-Tests-Impl") |
|
||||
.WithCriteria<Parameters>((context, data) => !data.SkipTests) |
|
||||
.WithCriteria<Parameters>((context, data) => data.IsRunningOnWindows) |
|
||||
.Does(() => |
|
||||
{ |
|
||||
var dotMemoryUnit = Context.Tools.Resolve("dotMemoryUnit.exe"); |
|
||||
var leakTestsExitCode = StartProcess(dotMemoryUnit, new ProcessSettings |
|
||||
{ |
|
||||
Arguments = new ProcessArgumentBuilder() |
|
||||
.Append(Context.Tools.Resolve("xunit.console.x86.exe").FullPath) |
|
||||
.Append("--propagate-exit-code") |
|
||||
.Append("--") |
|
||||
.Append("tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"), |
|
||||
Timeout = 120000 |
|
||||
}); |
|
||||
|
|
||||
if (leakTestsExitCode != 0) |
|
||||
{ |
|
||||
throw new Exception("Leak Tests failed"); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
Task("Zip-Files-Impl") |
|
||||
.Does<Parameters>(data => |
|
||||
{ |
|
||||
Zip(data.BinRoot, data.ZipCoreArtifacts); |
|
||||
|
|
||||
Zip(data.NugetRoot, data.ZipNuGetArtifacts); |
|
||||
|
|
||||
Zip(data.ZipSourceControlCatalogDesktopDirs, |
|
||||
data.ZipTargetControlCatalogDesktopDirs, |
|
||||
GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") + |
|
||||
GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.config") + |
|
||||
GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.so") + |
|
||||
GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dylib") + |
|
||||
GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe")); |
|
||||
}); |
|
||||
|
|
||||
void DotNetCorePack(Parameters parameters) |
|
||||
{ |
|
||||
var settings = new DotNetCorePackSettings |
|
||||
{ |
|
||||
Configuration = parameters.Configuration, |
|
||||
MSBuildSettings = new DotNetCoreMSBuildSettings |
|
||||
{ |
|
||||
Properties = |
|
||||
{ |
|
||||
{ "PackageVersion", new [] { parameters.Version } } |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
DotNetCorePack(parameters.MSBuildSolution, settings); |
|
||||
} |
|
||||
|
|
||||
Task("Create-NuGet-Packages-Impl") |
|
||||
.Does<Parameters>(data => |
|
||||
{ |
|
||||
if(data.IsRunningOnWindows) |
|
||||
{ |
|
||||
MSBuild(data.MSBuildSolution, settings => { |
|
||||
settings.SetConfiguration(data.Configuration); |
|
||||
settings.SetVerbosity(Verbosity.Minimal); |
|
||||
settings.WithProperty("iOSRoslynPathHackRequired", "true"); |
|
||||
settings.WithProperty("PackageVersion", data.Version); |
|
||||
settings.UseToolVersion(MSBuildToolVersion.VS2017); |
|
||||
settings.WithRestore(); |
|
||||
settings.WithTarget("Pack"); |
|
||||
}); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
DotNetCorePack(data); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
// TARGETS |
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
Task("Build") |
|
||||
.IsDependentOn("Clean-Impl") |
|
||||
.IsDependentOn("Build-Impl"); |
|
||||
|
|
||||
Task("Run-Tests") |
|
||||
.IsDependentOn("Build") |
|
||||
.IsDependentOn("Run-Unit-Tests-Impl") |
|
||||
.IsDependentOn("Run-Render-Tests-Impl") |
|
||||
.IsDependentOn("Run-Designer-Tests-Impl") |
|
||||
.IsDependentOn("Run-Leak-Tests-Impl"); |
|
||||
|
|
||||
Task("Package") |
|
||||
.IsDependentOn("Run-Tests") |
|
||||
.IsDependentOn("Create-NuGet-Packages-Impl"); |
|
||||
|
|
||||
Task("AppVeyor") |
|
||||
.IsDependentOn("Package") |
|
||||
.IsDependentOn("Zip-Files-Impl"); |
|
||||
|
|
||||
Task("Travis") |
|
||||
.IsDependentOn("Run-Tests"); |
|
||||
|
|
||||
Task("Azure-Linux") |
|
||||
.IsDependentOn("Run-Tests"); |
|
||||
|
|
||||
Task("Azure-OSX") |
|
||||
.IsDependentOn("Package") |
|
||||
.IsDependentOn("Zip-Files-Impl"); |
|
||||
|
|
||||
Task("Azure-Windows") |
|
||||
.IsDependentOn("Package") |
|
||||
.IsDependentOn("Zip-Files-Impl"); |
|
||||
|
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
// EXECUTE |
|
||||
/////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
var target = Context.Argument("target", "Default"); |
|
||||
|
|
||||
if (target == "Default") |
|
||||
{ |
|
||||
target = Context.IsRunningOnWindows() ? "Package" : "Run-Tests"; |
|
||||
} |
|
||||
|
|
||||
RunTarget(target); |
|
||||
@ -1,201 +1,69 @@ |
|||||
########################################################################## |
|
||||
# This is the Cake bootstrapper script for PowerShell. |
|
||||
# This file was downloaded from https://github.com/cake-build/resources |
|
||||
# Feel free to change this file to fit your needs. |
|
||||
########################################################################## |
|
||||
|
|
||||
<# |
|
||||
|
|
||||
.SYNOPSIS |
|
||||
This is a Powershell script to bootstrap a Cake build. |
|
||||
|
|
||||
.DESCRIPTION |
|
||||
This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) |
|
||||
and execute your Cake build script with the parameters you provide. |
|
||||
|
|
||||
.PARAMETER Script |
|
||||
The build script to execute. |
|
||||
.PARAMETER Target |
|
||||
The build script target to run. |
|
||||
.PARAMETER Platform |
|
||||
The build platform to use. |
|
||||
.PARAMETER Configuration |
|
||||
The build configuration to use. |
|
||||
.PARAMETER Verbosity |
|
||||
Specifies the amount of information to be displayed. |
|
||||
.PARAMETER Experimental |
|
||||
Tells Cake to use the latest Roslyn release. |
|
||||
.PARAMETER WhatIf |
|
||||
Performs a dry run of the build script. |
|
||||
No tasks will be executed. |
|
||||
.PARAMETER Mono |
|
||||
Tells Cake to use the Mono scripting engine. |
|
||||
.PARAMETER SkipToolPackageRestore |
|
||||
Skips restoring of packages. |
|
||||
.PARAMETER SkipTests |
|
||||
Skips unit tests |
|
||||
.PARAMETER ScriptArgs |
|
||||
Remaining arguments are added here. |
|
||||
|
|
||||
.LINK |
|
||||
http://cakebuild.net |
|
||||
|
|
||||
#> |
|
||||
|
|
||||
[CmdletBinding()] |
[CmdletBinding()] |
||||
Param( |
Param( |
||||
[string]$Script = "build.cake", |
#[switch]$CustomParam, |
||||
[string]$Target = "Default", |
|
||||
[ValidateSet("Any CPU", "x86", "x64", "NetCoreOnly", "iPhone")] |
|
||||
[string]$Platform = "Any CPU", |
|
||||
[ValidateSet("Release", "Debug")] |
|
||||
[string]$Configuration = "Release", |
|
||||
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] |
|
||||
[string]$Verbosity = "Verbose", |
|
||||
[switch]$Experimental, |
|
||||
[Alias("DryRun","Noop")] |
|
||||
[switch]$WhatIf, |
|
||||
[switch]$Mono, |
|
||||
[switch]$SkipToolPackageRestore, |
|
||||
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] |
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] |
||||
[string[]]$ScriptArgs |
[string[]]$BuildArguments |
||||
) |
) |
||||
|
|
||||
[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null |
Write-Output "Windows PowerShell $($Host.Version)" |
||||
function MD5HashFile([string] $filePath) |
|
||||
{ |
|
||||
if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) |
|
||||
{ |
|
||||
return $null |
|
||||
} |
|
||||
|
|
||||
[System.IO.Stream] $file = $null; |
|
||||
[System.Security.Cryptography.MD5] $md5 = $null; |
|
||||
try |
|
||||
{ |
|
||||
$md5 = [System.Security.Cryptography.MD5]::Create() |
|
||||
$file = [System.IO.File]::OpenRead($filePath) |
|
||||
return [System.BitConverter]::ToString($md5.ComputeHash($file)) |
|
||||
} |
|
||||
finally |
|
||||
{ |
|
||||
if ($file -ne $null) |
|
||||
{ |
|
||||
$file.Dispose() |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
Write-Host "Preparing to run build script..." |
|
||||
|
|
||||
if(!$PSScriptRoot){ |
|
||||
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent |
|
||||
} |
|
||||
|
|
||||
$TOOLS_DIR = Join-Path $PSScriptRoot "tools" |
Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { exit 1 } |
||||
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" |
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent |
||||
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" |
|
||||
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" |
|
||||
$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" |
|
||||
$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" |
|
||||
|
|
||||
# Should we use mono? |
########################################################################### |
||||
$UseMono = ""; |
# CONFIGURATION |
||||
if($Mono.IsPresent) { |
########################################################################### |
||||
Write-Verbose -Message "Using the Mono based scripting engine." |
|
||||
$UseMono = "-mono" |
|
||||
} |
|
||||
|
|
||||
# Should we use the new Roslyn? |
$BuildProjectFile = "$PSScriptRoot\nukebuild\_build.csproj" |
||||
$UseExperimental = ""; |
$TempDirectory = "$PSScriptRoot\\.tmp" |
||||
if($Experimental.IsPresent -and !($Mono.IsPresent)) { |
|
||||
Write-Verbose -Message "Using experimental version of Roslyn." |
|
||||
$UseExperimental = "-experimental" |
|
||||
} |
|
||||
|
|
||||
# Is this a dry run? |
$DotNetGlobalFile = "$PSScriptRoot\\global.json" |
||||
$UseDryRun = ""; |
$DotNetInstallUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1" |
||||
if($WhatIf.IsPresent) { |
$DotNetChannel = "Current" |
||||
$UseDryRun = "-dryrun" |
|
||||
} |
|
||||
|
|
||||
# Is this a dry run? |
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1 |
||||
$UseSkipTests = ""; |
$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 |
||||
if($SkipTests.IsPresent) { |
$env:NUGET_XMLDOC_MODE = "skip" |
||||
$UseSkipTests = "-skip-tests" |
|
||||
} |
|
||||
|
|
||||
# Make sure tools folder exists |
########################################################################### |
||||
if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { |
# EXECUTION |
||||
Write-Verbose -Message "Creating tools directory..." |
########################################################################### |
||||
New-Item -Path $TOOLS_DIR -Type directory | out-null |
|
||||
} |
|
||||
|
|
||||
# Make sure that packages.config exist. |
function ExecSafe([scriptblock] $cmd) { |
||||
if (!(Test-Path $PACKAGES_CONFIG)) { |
& $cmd |
||||
Write-Verbose -Message "Downloading packages.config..." |
if ($LASTEXITCODE) { exit $LASTEXITCODE } |
||||
try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch { |
|
||||
Throw "Could not download packages.config." |
|
||||
} |
|
||||
} |
} |
||||
|
|
||||
# Try find NuGet.exe in path if not exists |
# If global.json exists, load expected version |
||||
if (!(Test-Path $NUGET_EXE)) { |
if (Test-Path $DotNetGlobalFile) { |
||||
Write-Verbose -Message "Trying to find nuget.exe in PATH..." |
$DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json) |
||||
$existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) } |
if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) { |
||||
$NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 |
$DotNetVersion = $DotNetGlobal.sdk.version |
||||
if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { |
|
||||
Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." |
|
||||
$NUGET_EXE = $NUGET_EXE_IN_PATH.FullName |
|
||||
} |
} |
||||
} |
} |
||||
|
|
||||
# Try download NuGet.exe if not exists |
# If dotnet is installed locally, and expected version is not set or installation matches the expected version |
||||
if (!(Test-Path $NUGET_EXE)) { |
if ((Get-Command "dotnet" -ErrorAction SilentlyContinue) -ne $null -and ` |
||||
Write-Verbose -Message "Downloading NuGet.exe..." |
(!(Test-Path variable:DotNetVersion) -or $(& dotnet --version) -eq $DotNetVersion)) { |
||||
try { |
$env:DOTNET_EXE = (Get-Command "dotnet").Path |
||||
(New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE) |
|
||||
} catch { |
|
||||
Throw "Could not download NuGet.exe." |
|
||||
} |
|
||||
} |
} |
||||
|
else { |
||||
# Save nuget.exe path to environment to be available to child processed |
$DotNetDirectory = "$TempDirectory\dotnet-win" |
||||
$ENV:NUGET_EXE = $NUGET_EXE |
$env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe" |
||||
|
|
||||
# Restore tools from NuGet? |
# Download install script |
||||
if(-Not $SkipToolPackageRestore.IsPresent) { |
$DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" |
||||
Push-Location |
md -force $TempDirectory > $null |
||||
Set-Location $TOOLS_DIR |
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) |
||||
|
|
||||
# Check for changes in packages.config and remove installed tools if true. |
# Install by channel or version |
||||
[string] $md5Hash = MD5HashFile($PACKAGES_CONFIG) |
if (!(Test-Path variable:DotNetVersion)) { |
||||
if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or |
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath } |
||||
($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { |
} else { |
||||
Write-Verbose -Message "Missing or changed package.config hash..." |
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } |
||||
Remove-Item * -Recurse -Exclude packages.config,nuget.exe |
|
||||
} |
} |
||||
|
|
||||
Write-Verbose -Message "Restoring tools from NuGet..." |
|
||||
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" |
|
||||
|
|
||||
if ($LASTEXITCODE -ne 0) { |
|
||||
Throw "An error occured while restoring NuGet tools." |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
$md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" |
|
||||
} |
|
||||
Write-Verbose -Message ($NuGetOutput | out-string) |
|
||||
Pop-Location |
|
||||
} |
} |
||||
|
|
||||
# Make sure that Cake has been installed. |
Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)" |
||||
if (!(Test-Path $CAKE_EXE)) { |
|
||||
Throw "Could not find Cake.exe at $CAKE_EXE" |
|
||||
} |
|
||||
|
|
||||
# Start Cake |
ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile -- $BuildArguments } |
||||
Write-Host "Running build script..." |
|
||||
Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -platform=`"$Platform`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseSkipTests $UseMono $UseDryRun $UseExperimental $ScriptArgs" |
|
||||
exit $LASTEXITCODE |
|
||||
|
|||||
@ -1,105 +1,72 @@ |
|||||
#!/usr/bin/env bash |
#!/usr/bin/env bash |
||||
|
|
||||
########################################################################## |
echo $(bash --version 2>&1 | head -n 1) |
||||
# This is the Cake bootstrapper script for Linux and OS X. |
|
||||
# This file was downloaded from https://github.com/cake-build/resources |
|
||||
# Feel free to change this file to fit your needs. |
|
||||
########################################################################## |
|
||||
|
|
||||
# Define directories. |
#CUSTOMPARAM=0 |
||||
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) |
BUILD_ARGUMENTS=() |
||||
TOOLS_DIR=$SCRIPT_DIR/tools |
|
||||
NUGET_EXE=$TOOLS_DIR/nuget.exe |
|
||||
CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe |
|
||||
PACKAGES_CONFIG=$TOOLS_DIR/packages.config |
|
||||
PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum |
|
||||
|
|
||||
# Define md5sum or md5 depending on Linux/OSX |
|
||||
MD5_EXE= |
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then |
|
||||
MD5_EXE="md5 -r" |
|
||||
else |
|
||||
MD5_EXE="md5sum" |
|
||||
fi |
|
||||
|
|
||||
# Define default arguments. |
|
||||
SCRIPT="build.cake" |
|
||||
TARGET="Default" |
|
||||
CONFIGURATION="Release" |
|
||||
PLATFORM="Any CPU" |
|
||||
VERBOSITY="verbose" |
|
||||
DRYRUN= |
|
||||
SKIP_TESTS= |
|
||||
SHOW_VERSION=false |
|
||||
SCRIPT_ARGUMENTS=() |
|
||||
|
|
||||
# Parse arguments. |
|
||||
for i in "$@"; do |
for i in "$@"; do |
||||
case $1 in |
case $(echo $1 | awk '{print tolower($0)}') in |
||||
-s|--script) SCRIPT="$2"; shift ;; |
# -custom-param) CUSTOMPARAM=1;; |
||||
-t|--target) TARGET="$2"; shift ;; |
*) BUILD_ARGUMENTS+=("$1") ;; |
||||
-p|--platform) PLATFORM="$2"; shift ;; |
|
||||
-c|--configuration) CONFIGURATION="$2"; shift ;; |
|
||||
--skip-tests) SKIP_TESTS="-skip-tests"; shift ;; |
|
||||
-v|--verbosity) VERBOSITY="$2"; shift ;; |
|
||||
-d|--dryrun) DRYRUN="-dryrun" ;; |
|
||||
--version) SHOW_VERSION=true ;; |
|
||||
--) shift; SCRIPT_ARGUMENTS+=("$@"); break ;; |
|
||||
*) SCRIPT_ARGUMENTS+=("$1") ;; |
|
||||
esac |
esac |
||||
shift |
shift |
||||
done |
done |
||||
|
|
||||
# Make sure the tools folder exist. |
set -eo pipefail |
||||
if [ ! -d "$TOOLS_DIR" ]; then |
SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) |
||||
mkdir "$TOOLS_DIR" |
|
||||
fi |
|
||||
|
|
||||
# Make sure that packages.config exist. |
########################################################################### |
||||
if [ ! -f "$TOOLS_DIR/packages.config" ]; then |
# CONFIGURATION |
||||
echo "Downloading packages.config..." |
########################################################################### |
||||
curl -Lsfo "$TOOLS_DIR/packages.config" http://cakebuild.net/download/bootstrapper/packages |
|
||||
if [ $? -ne 0 ]; then |
|
||||
echo "An error occured while downloading packages.config." |
|
||||
exit 1 |
|
||||
fi |
|
||||
fi |
|
||||
|
|
||||
# Download NuGet if it does not exist. |
BUILD_PROJECT_FILE="$SCRIPT_DIR/nukebuild/_build.csproj" |
||||
if [ ! -f "$NUGET_EXE" ]; then |
TEMP_DIRECTORY="$SCRIPT_DIR//.tmp" |
||||
echo "Downloading NuGet..." |
|
||||
curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe |
|
||||
if [ $? -ne 0 ]; then |
|
||||
echo "An error occured while downloading nuget.exe." |
|
||||
exit 1 |
|
||||
fi |
|
||||
fi |
|
||||
|
|
||||
# Restore tools from NuGet. |
DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" |
||||
pushd "$TOOLS_DIR" >/dev/null |
DOTNET_INSTALL_URL="https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.sh" |
||||
if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then |
DOTNET_CHANNEL="Current" |
||||
find . -type d ! -name . | xargs rm -rf |
|
||||
fi |
|
||||
|
|
||||
mono "$NUGET_EXE" install -ExcludeVersion |
export DOTNET_CLI_TELEMETRY_OPTOUT=1 |
||||
if [ $? -ne 0 ]; then |
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 |
||||
echo "Could not restore NuGet packages." |
export NUGET_XMLDOC_MODE="skip" |
||||
exit 1 |
|
||||
fi |
|
||||
|
|
||||
$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5 |
########################################################################### |
||||
|
# EXECUTION |
||||
|
########################################################################### |
||||
|
|
||||
popd >/dev/null |
function FirstJsonValue { |
||||
|
perl -nle 'print $1 if m{"'$1'": "([^"\-]+)",?}' <<< ${@:2} |
||||
|
} |
||||
|
|
||||
# Make sure that Cake has been installed. |
# If global.json exists, load expected version |
||||
if [ ! -f "$CAKE_EXE" ]; then |
if [ -f "$DOTNET_GLOBAL_FILE" ]; then |
||||
echo "Could not find Cake.exe at '$CAKE_EXE'." |
DOTNET_VERSION=$(FirstJsonValue "version" $(cat "$DOTNET_GLOBAL_FILE")) |
||||
exit 1 |
if [ "$DOTNET_VERSION" == "" ]; then |
||||
|
unset DOTNET_VERSION |
||||
|
fi |
||||
fi |
fi |
||||
|
|
||||
# Start Cake |
# If dotnet is installed locally, and expected version is not set or installation matches the expected version |
||||
if $SHOW_VERSION; then |
if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version) == "$DOTNET_VERSION") ]]; then |
||||
exec mono "$CAKE_EXE" -version |
export DOTNET_EXE="$(command -v dotnet)" |
||||
else |
else |
||||
exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -platform="$PLATFORM" -configuration="$CONFIGURATION" -target=$TARGET $DRYRUN $SKIP_TESTS "${SCRIPT_ARGUMENTS[@]}" |
DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" |
||||
|
export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" |
||||
|
|
||||
|
# Download install script |
||||
|
DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" |
||||
|
mkdir -p "$TEMP_DIRECTORY" |
||||
|
curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" |
||||
|
chmod +x "$DOTNET_INSTALL_FILE" |
||||
|
|
||||
|
# Install by channel or version |
||||
|
if [ -z ${DOTNET_VERSION+x} ]; then |
||||
|
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path |
||||
|
else |
||||
|
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path |
||||
|
fi |
||||
fi |
fi |
||||
|
|
||||
|
echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)" |
||||
|
|
||||
|
"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]} |
||||
|
|||||
@ -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="Magick.NET-Q16-AnyCPU" Version="7.0.6.102" /> |
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.9.0.2" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,6 +1,6 @@ |
|||||
<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="SkiaSharp" Version="1.60.0" /> |
<PackageReference Include="SkiaSharp" Version="1.68.0" /> |
||||
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="Avalonia.Skia.Linux.Natives" Version="1.60.0.1" /> |
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="1.68.0" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -0,0 +1,8 @@ |
|||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
<Import Project="$(MSBuildThisFileDirectory)/NetFX.props" /> |
||||
|
<ItemGroup Condition="$(TargetFramework.StartsWith('net4'))"> |
||||
|
<Content Include="$(MSBuildThisFileDirectory)/xunit.runner.mono.json" Link="xunit.runner.json" > |
||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
||||
|
</Content> |
||||
|
</ItemGroup> |
||||
|
</Project> |
||||
@ -0,0 +1 @@ |
|||||
|
{ "appDomain": "denied" } |
||||
@ -1,15 +0,0 @@ |
|||||
; This is the default configuration file for Cake. |
|
||||
; This file was downloaded from https://github.com/cake-build/resources |
|
||||
|
|
||||
[Nuget] |
|
||||
Source=https://api.nuget.org/v3/index.json |
|
||||
UseInProcessClient=true |
|
||||
LoadDependencies=false |
|
||||
|
|
||||
[Paths] |
|
||||
Tools=./tools |
|
||||
Addins=./tools/Addins |
|
||||
Modules=./tools/Modules |
|
||||
|
|
||||
[Settings] |
|
||||
SkipVerification=false |
|
||||
@ -1,7 +1,7 @@ |
|||||
{ |
{ |
||||
"msbuild-sdks": { |
"msbuild-sdks": { |
||||
"Microsoft.Build.Traversal": "1.0.43", |
"Microsoft.Build.Traversal": "1.0.43", |
||||
"MSBuild.Sdk.Extras": "1.6.46", |
"MSBuild.Sdk.Extras": "1.6.65", |
||||
"AggregatePackage.NuGet.Sdk" : "0.1.12" |
"AggregatePackage.NuGet.Sdk" : "0.1.12" |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,8 @@ |
|||||
|
# editorconfig.org |
||||
|
|
||||
|
# top-most EditorConfig file |
||||
|
root = false |
||||
|
|
||||
|
# C# files |
||||
|
[*.cs] |
||||
|
dotnet_style_require_accessibility_modifiers = never |
||||
@ -0,0 +1,265 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Diagnostics; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using System.Threading; |
||||
|
using System.Xml.Linq; |
||||
|
using Nuke.Common; |
||||
|
using Nuke.Common.Git; |
||||
|
using Nuke.Common.ProjectModel; |
||||
|
using Nuke.Common.Tooling; |
||||
|
using Nuke.Common.Tools.DotNet; |
||||
|
using Nuke.Common.Tools.MSBuild; |
||||
|
using Nuke.Common.Utilities; |
||||
|
using static Nuke.Common.EnvironmentInfo; |
||||
|
using static Nuke.Common.IO.FileSystemTasks; |
||||
|
using static Nuke.Common.IO.PathConstruction; |
||||
|
using static Nuke.Common.Tools.MSBuild.MSBuildTasks; |
||||
|
using static Nuke.Common.Tools.DotNet.DotNetTasks; |
||||
|
using static Nuke.Common.Tools.Xunit.XunitTasks; |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
Before editing this file, install support plugin for your IDE, |
||||
|
running and debugging a particular target (optionally without deps) would be way easier |
||||
|
ReSharper/Rider - https://plugins.jetbrains.com/plugin/10803-nuke-support
|
||||
|
VSCode - https://marketplace.visualstudio.com/items?itemName=nuke.support
|
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
partial class Build : NukeBuild |
||||
|
{ |
||||
|
BuildParameters Parameters { get; set; } |
||||
|
protected override void OnBuildInitialized() |
||||
|
{ |
||||
|
Parameters = new BuildParameters(this); |
||||
|
Information("Building version {0} of Avalonia ({1}) using version {2} of Nuke.", |
||||
|
Parameters.Version, |
||||
|
Parameters.Configuration, |
||||
|
typeof(NukeBuild).Assembly.GetName().Version.ToString()); |
||||
|
|
||||
|
if (Parameters.IsLocalBuild) |
||||
|
{ |
||||
|
Information("Repository Name: " + Parameters.RepositoryName); |
||||
|
Information("Repository Branch: " + Parameters.RepositoryBranch); |
||||
|
} |
||||
|
Information("Configuration: " + Parameters.Configuration); |
||||
|
Information("IsLocalBuild: " + Parameters.IsLocalBuild); |
||||
|
Information("IsRunningOnUnix: " + Parameters.IsRunningOnUnix); |
||||
|
Information("IsRunningOnWindows: " + Parameters.IsRunningOnWindows); |
||||
|
Information("IsRunningOnAzure:" + Parameters.IsRunningOnAzure); |
||||
|
Information("IsPullRequest: " + Parameters.IsPullRequest); |
||||
|
Information("IsMainRepo: " + Parameters.IsMainRepo); |
||||
|
Information("IsMasterBranch: " + Parameters.IsMasterBranch); |
||||
|
Information("IsReleaseBranch: " + Parameters.IsReleaseBranch); |
||||
|
Information("IsReleasable: " + Parameters.IsReleasable); |
||||
|
Information("IsMyGetRelease: " + Parameters.IsMyGetRelease); |
||||
|
Information("IsNuGetRelease: " + Parameters.IsNuGetRelease); |
||||
|
|
||||
|
void ExecWait(string preamble, string command, string args) |
||||
|
{ |
||||
|
Console.WriteLine(preamble); |
||||
|
Process.Start(new ProcessStartInfo(command, args) {UseShellExecute = false}).WaitForExit(); |
||||
|
} |
||||
|
ExecWait("dotnet version:", "dotnet", "--version"); |
||||
|
if (Parameters.IsRunningOnUnix) |
||||
|
ExecWait("Mono version:", "mono", "--version"); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
Target Clean => _ => _.Executes(() => |
||||
|
{ |
||||
|
DeleteDirectories(Parameters.BuildDirs); |
||||
|
EnsureCleanDirectories(Parameters.BuildDirs); |
||||
|
EnsureCleanDirectory(Parameters.ArtifactsDir); |
||||
|
EnsureCleanDirectory(Parameters.NugetIntermediateRoot); |
||||
|
EnsureCleanDirectory(Parameters.NugetRoot); |
||||
|
EnsureCleanDirectory(Parameters.ZipRoot); |
||||
|
EnsureCleanDirectory(Parameters.TestResultsRoot); |
||||
|
}); |
||||
|
|
||||
|
Target Compile => _ => _ |
||||
|
.DependsOn(Clean) |
||||
|
.Executes(() => |
||||
|
{ |
||||
|
|
||||
|
if (Parameters.IsRunningOnWindows) |
||||
|
MSBuild(Parameters.MSBuildSolution, c => c |
||||
|
.SetArgumentConfigurator(a => a.Add("/r")) |
||||
|
.SetConfiguration(Parameters.Configuration) |
||||
|
.SetVerbosity(MSBuildVerbosity.Minimal) |
||||
|
.AddProperty("PackageVersion", Parameters.Version) |
||||
|
.AddProperty("iOSRoslynPathHackRequired", "true") |
||||
|
.SetToolsVersion(MSBuildToolsVersion._15_0) |
||||
|
.AddTargets("Build") |
||||
|
); |
||||
|
|
||||
|
else |
||||
|
DotNetBuild(Parameters.MSBuildSolution, c => c |
||||
|
.AddProperty("PackageVersion", Parameters.Version) |
||||
|
.SetConfiguration(Parameters.Configuration) |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
void RunCoreTest(string project) |
||||
|
{ |
||||
|
if(!project.EndsWith(".csproj")) |
||||
|
project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj"); |
||||
|
Information("Running tests from " + project); |
||||
|
XDocument xdoc; |
||||
|
using (var s = File.OpenRead(project)) |
||||
|
xdoc = XDocument.Load(s); |
||||
|
|
||||
|
List<string> frameworks = null; |
||||
|
var targets = xdoc.Root.Descendants("TargetFrameworks").FirstOrDefault(); |
||||
|
if (targets != null) |
||||
|
frameworks = targets.Value.Split(';').Where(f => !string.IsNullOrWhiteSpace(f)).ToList(); |
||||
|
else |
||||
|
frameworks = new List<string> {xdoc.Root.Descendants("TargetFramework").First().Value}; |
||||
|
|
||||
|
foreach(var fw in frameworks) |
||||
|
{ |
||||
|
Information("Running for " + fw); |
||||
|
DotNetTest(c => |
||||
|
{ |
||||
|
c = c |
||||
|
.SetProjectFile(project) |
||||
|
.SetConfiguration(Parameters.Configuration) |
||||
|
.SetFramework(fw) |
||||
|
.EnableNoBuild() |
||||
|
.EnableNoRestore(); |
||||
|
// NOTE: I can see that we could maybe add another extension method "Switch" or "If" to make this more convenient
|
||||
|
if (Parameters.PublishTestResults) |
||||
|
c = c.SetLogger("trx").SetResultsDirectory(Parameters.TestResultsRoot); |
||||
|
return c; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Target RunCoreLibsTests => _ => _ |
||||
|
.OnlyWhen(() => !Parameters.SkipTests) |
||||
|
.DependsOn(Compile) |
||||
|
.Executes(() => |
||||
|
{ |
||||
|
RunCoreTest("./tests/Avalonia.Animation.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.Base.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.Controls.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.Input.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.Interactivity.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.Layout.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.Markup.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.Styling.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.Visuals.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.Skia.UnitTests"); |
||||
|
RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests"); |
||||
|
}); |
||||
|
|
||||
|
Target RunRenderTests => _ => _ |
||||
|
.OnlyWhen(() => !Parameters.SkipTests) |
||||
|
.DependsOn(Compile) |
||||
|
.Executes(() => |
||||
|
{ |
||||
|
RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj"); |
||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) |
||||
|
RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj"); |
||||
|
}); |
||||
|
|
||||
|
Target RunDesignerTests => _ => _ |
||||
|
.OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows) |
||||
|
.DependsOn(Compile) |
||||
|
.Executes(() => |
||||
|
{ |
||||
|
RunCoreTest("./tests/Avalonia.DesignerSupport.Tests"); |
||||
|
}); |
||||
|
|
||||
|
[PackageExecutable("JetBrains.dotMemoryUnit", "dotMemoryUnit.exe")] readonly Tool DotMemoryUnit; |
||||
|
|
||||
|
Target RunLeakTests => _ => _ |
||||
|
.OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows) |
||||
|
.DependsOn(Compile) |
||||
|
.Executes(() => |
||||
|
{ |
||||
|
var testAssembly = "tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"; |
||||
|
DotMemoryUnit( |
||||
|
$"{XunitPath.DoubleQuoteIfNeeded()} --propagate-exit-code -- {testAssembly}", |
||||
|
timeout: 120_000); |
||||
|
}); |
||||
|
|
||||
|
Target ZipFiles => _ => _ |
||||
|
.After(CreateNugetPackages, Compile, RunCoreLibsTests, Package) |
||||
|
.Executes(() => |
||||
|
{ |
||||
|
var data = Parameters; |
||||
|
Zip(data.ZipCoreArtifacts, data.BinRoot); |
||||
|
Zip(data.ZipNuGetArtifacts, data.NugetRoot); |
||||
|
Zip(data.ZipTargetControlCatalogDesktopDir, |
||||
|
GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.dll").Concat( |
||||
|
GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.config")).Concat( |
||||
|
GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.so")).Concat( |
||||
|
GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.dylib")).Concat( |
||||
|
GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.exe"))); |
||||
|
}); |
||||
|
|
||||
|
Target CreateIntermediateNugetPackages => _ => _ |
||||
|
.DependsOn(Compile) |
||||
|
.After(RunTests) |
||||
|
.Executes(() => |
||||
|
{ |
||||
|
if (Parameters.IsRunningOnWindows) |
||||
|
|
||||
|
MSBuild(Parameters.MSBuildSolution, c => c |
||||
|
.SetConfiguration(Parameters.Configuration) |
||||
|
.SetVerbosity(MSBuildVerbosity.Minimal) |
||||
|
.AddProperty("PackageVersion", Parameters.Version) |
||||
|
.AddProperty("iOSRoslynPathHackRequired", "true") |
||||
|
.SetToolsVersion(MSBuildToolsVersion._15_0) |
||||
|
.AddTargets("Pack")); |
||||
|
else |
||||
|
DotNetPack(Parameters.MSBuildSolution, c => |
||||
|
c.SetConfiguration(Parameters.Configuration) |
||||
|
.AddProperty("PackageVersion", Parameters.Version)); |
||||
|
}); |
||||
|
|
||||
|
Target CreateNugetPackages => _ => _ |
||||
|
.DependsOn(CreateIntermediateNugetPackages) |
||||
|
.Executes(() => |
||||
|
{ |
||||
|
var config = Numerge.MergeConfiguration.LoadFile(RootDirectory / "nukebuild" / "numerge.config"); |
||||
|
EnsureCleanDirectory(Parameters.NugetRoot); |
||||
|
if(!Numerge.NugetPackageMerger.Merge(Parameters.NugetIntermediateRoot, Parameters.NugetRoot, config, |
||||
|
new NumergeNukeLogger())) |
||||
|
throw new Exception("Package merge failed"); |
||||
|
}); |
||||
|
|
||||
|
Target RunTests => _ => _ |
||||
|
.DependsOn(RunCoreLibsTests) |
||||
|
.DependsOn(RunRenderTests) |
||||
|
.DependsOn(RunDesignerTests) |
||||
|
.DependsOn(RunLeakTests); |
||||
|
|
||||
|
Target Package => _ => _ |
||||
|
.DependsOn(RunTests) |
||||
|
.DependsOn(CreateNugetPackages); |
||||
|
|
||||
|
Target CiAzureLinux => _ => _ |
||||
|
.DependsOn(RunTests); |
||||
|
|
||||
|
Target CiAzureOSX => _ => _ |
||||
|
.DependsOn(Package) |
||||
|
.DependsOn(ZipFiles); |
||||
|
|
||||
|
Target CiAzureWindows => _ => _ |
||||
|
.DependsOn(Package) |
||||
|
.DependsOn(ZipFiles); |
||||
|
|
||||
|
|
||||
|
public static int Main() => |
||||
|
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) |
||||
|
? Execute<Build>(x => x.Package) |
||||
|
: Execute<Build>(x => x.RunTests); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,142 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using System.Xml.Linq; |
||||
|
using Nuke.Common; |
||||
|
using Nuke.Common.BuildServers; |
||||
|
using Nuke.Common.Execution; |
||||
|
using Nuke.Common.IO; |
||||
|
using static Nuke.Common.IO.FileSystemTasks; |
||||
|
using static Nuke.Common.IO.PathConstruction; |
||||
|
using static Nuke.Common.Tools.MSBuild.MSBuildTasks; |
||||
|
|
||||
|
public partial class Build |
||||
|
{ |
||||
|
[Parameter("configuration")] |
||||
|
public string Configuration { get; set; } |
||||
|
|
||||
|
[Parameter("skip-tests")] |
||||
|
public bool SkipTests { get; set; } |
||||
|
|
||||
|
[Parameter("force-nuget-version")] |
||||
|
public string ForceNugetVersion { get; set; } |
||||
|
|
||||
|
public class BuildParameters |
||||
|
{ |
||||
|
public string Configuration { get; } |
||||
|
public bool SkipTests { get; } |
||||
|
public string MainRepo { get; } |
||||
|
public string MasterBranch { get; } |
||||
|
public string RepositoryName { get; } |
||||
|
public string RepositoryBranch { get; } |
||||
|
public string ReleaseConfiguration { get; } |
||||
|
public string ReleaseBranchPrefix { get; } |
||||
|
public string MSBuildSolution { get; } |
||||
|
public bool IsLocalBuild { get; } |
||||
|
public bool IsRunningOnUnix { get; } |
||||
|
public bool IsRunningOnWindows { get; } |
||||
|
public bool IsRunningOnAzure { get; } |
||||
|
public bool IsPullRequest { get; } |
||||
|
public bool IsMainRepo { get; } |
||||
|
public bool IsMasterBranch { get; } |
||||
|
public bool IsReleaseBranch { get; } |
||||
|
public bool IsReleasable { get; } |
||||
|
public bool IsMyGetRelease { get; } |
||||
|
public bool IsNuGetRelease { get; } |
||||
|
public bool PublishTestResults { get; } |
||||
|
public string Version { get; } |
||||
|
public AbsolutePath ArtifactsDir { get; } |
||||
|
public AbsolutePath NugetIntermediateRoot { get; } |
||||
|
public AbsolutePath NugetRoot { get; } |
||||
|
public AbsolutePath ZipRoot { get; } |
||||
|
public AbsolutePath BinRoot { get; } |
||||
|
public AbsolutePath TestResultsRoot { get; } |
||||
|
public string DirSuffix { get; } |
||||
|
public List<string> BuildDirs { get; } |
||||
|
public string FileZipSuffix { get; } |
||||
|
public AbsolutePath ZipCoreArtifacts { get; } |
||||
|
public AbsolutePath ZipNuGetArtifacts { get; } |
||||
|
public AbsolutePath ZipSourceControlCatalogDesktopDir { get; } |
||||
|
public AbsolutePath ZipTargetControlCatalogDesktopDir { get; } |
||||
|
|
||||
|
|
||||
|
public BuildParameters(Build b) |
||||
|
{ |
||||
|
// ARGUMENTS
|
||||
|
Configuration = b.Configuration ?? "Release"; |
||||
|
SkipTests = b.SkipTests; |
||||
|
|
||||
|
// CONFIGURATION
|
||||
|
MainRepo = "https://github.com/AvaloniaUI/Avalonia"; |
||||
|
MasterBranch = "refs/heads/master"; |
||||
|
ReleaseBranchPrefix = "refs/heads/release/"; |
||||
|
ReleaseConfiguration = "Release"; |
||||
|
MSBuildSolution = RootDirectory / "dirs.proj"; |
||||
|
|
||||
|
// PARAMETERS
|
||||
|
IsLocalBuild = Host == HostType.Console; |
||||
|
IsRunningOnUnix = Environment.OSVersion.Platform == PlatformID.Unix || |
||||
|
Environment.OSVersion.Platform == PlatformID.MacOSX; |
||||
|
IsRunningOnWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); |
||||
|
IsRunningOnAzure = Host == HostType.TeamServices || |
||||
|
Environment.GetEnvironmentVariable("LOGNAME") == "vsts"; |
||||
|
|
||||
|
if (IsRunningOnAzure) |
||||
|
{ |
||||
|
RepositoryName = TeamServices.Instance.RepositoryUri; |
||||
|
RepositoryBranch = TeamServices.Instance.SourceBranch; |
||||
|
IsPullRequest = TeamServices.Instance.PullRequestId.HasValue; |
||||
|
IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, TeamServices.Instance.RepositoryUri); |
||||
|
} |
||||
|
IsMainRepo = |
||||
|
StringComparer.OrdinalIgnoreCase.Equals(MainRepo, |
||||
|
RepositoryName); |
||||
|
IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, |
||||
|
RepositoryBranch); |
||||
|
IsReleaseBranch = RepositoryBranch?.StartsWith(ReleaseBranchPrefix, StringComparison.OrdinalIgnoreCase) == |
||||
|
true; |
||||
|
|
||||
|
IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration); |
||||
|
IsMyGetRelease = IsReleasable; |
||||
|
IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch; |
||||
|
|
||||
|
// VERSION
|
||||
|
Version = b.ForceNugetVersion ?? GetVersion(); |
||||
|
|
||||
|
if (IsRunningOnAzure) |
||||
|
{ |
||||
|
if (!IsNuGetRelease) |
||||
|
{ |
||||
|
// Use AssemblyVersion with Build as version
|
||||
|
Version += "-build" + Environment.GetEnvironmentVariable("BUILD_BUILDID") + "-beta"; |
||||
|
} |
||||
|
|
||||
|
PublishTestResults = true; |
||||
|
} |
||||
|
|
||||
|
// DIRECTORIES
|
||||
|
ArtifactsDir = RootDirectory / "artifacts"; |
||||
|
NugetRoot = ArtifactsDir / "nuget"; |
||||
|
NugetIntermediateRoot = RootDirectory / "build-intermediate" / "nuget"; |
||||
|
ZipRoot = ArtifactsDir / "zip"; |
||||
|
BinRoot = ArtifactsDir / "bin"; |
||||
|
TestResultsRoot = ArtifactsDir / "test-results"; |
||||
|
BuildDirs = GlobDirectories(RootDirectory, "**bin").Concat(GlobDirectories(RootDirectory, "**obj")).ToList(); |
||||
|
DirSuffix = Configuration; |
||||
|
FileZipSuffix = Version + ".zip"; |
||||
|
ZipCoreArtifacts = ZipRoot / ("Avalonia-" + FileZipSuffix); |
||||
|
ZipNuGetArtifacts = ZipRoot / ("Avalonia-NuGet-" + FileZipSuffix); |
||||
|
ZipSourceControlCatalogDesktopDir = |
||||
|
RootDirectory / ("samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461"); |
||||
|
ZipTargetControlCatalogDesktopDir = ZipRoot / ("ControlCatalog.Desktop-" + FileZipSuffix); |
||||
|
} |
||||
|
|
||||
|
string GetVersion() |
||||
|
{ |
||||
|
var xdoc = XDocument.Load(RootDirectory / "build/SharedVersion.props"); |
||||
|
return xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,93 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.IO; |
||||
|
using System.IO.Compression; |
||||
|
using System.Linq; |
||||
|
using Nuke.Common; |
||||
|
using Nuke.Common.IO; |
||||
|
using Numerge; |
||||
|
|
||||
|
public partial class Build |
||||
|
{ |
||||
|
static void Information(string info) |
||||
|
{ |
||||
|
Logger.Info(info); |
||||
|
} |
||||
|
|
||||
|
static void Information(string info, params object[] args) |
||||
|
{ |
||||
|
Logger.Info(info, args); |
||||
|
} |
||||
|
|
||||
|
private void Zip(PathConstruction.AbsolutePath target, params string[] paths) => Zip(target, paths.AsEnumerable()); |
||||
|
|
||||
|
private void Zip(PathConstruction.AbsolutePath target, IEnumerable<string> paths) |
||||
|
{ |
||||
|
var targetPath = target.ToString(); |
||||
|
bool finished = false, atLeastOneFileAdded = false; |
||||
|
try |
||||
|
{ |
||||
|
using (var targetStream = File.Create(targetPath)) |
||||
|
using(var archive = new System.IO.Compression.ZipArchive(targetStream, ZipArchiveMode.Create)) |
||||
|
{ |
||||
|
void AddFile(string path, string relativePath) |
||||
|
{ |
||||
|
var e = archive.CreateEntry(relativePath.Replace("\\", "/"), CompressionLevel.Optimal); |
||||
|
using (var entryStream = e.Open()) |
||||
|
using (var fileStream = File.OpenRead(path)) |
||||
|
fileStream.CopyTo(entryStream); |
||||
|
atLeastOneFileAdded = true; |
||||
|
} |
||||
|
|
||||
|
foreach (var path in paths) |
||||
|
{ |
||||
|
if (Directory.Exists(path)) |
||||
|
{ |
||||
|
var dirInfo = new DirectoryInfo(path); |
||||
|
var rootPath = Path.GetDirectoryName(dirInfo.FullName); |
||||
|
foreach(var fsEntry in dirInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories)) |
||||
|
{ |
||||
|
if (fsEntry is FileInfo) |
||||
|
{ |
||||
|
var relPath = Path.GetRelativePath(rootPath, fsEntry.FullName); |
||||
|
AddFile(fsEntry.FullName, relPath); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else if(File.Exists(path)) |
||||
|
{ |
||||
|
var name = Path.GetFileName(path); |
||||
|
AddFile(path, name); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
finished = true; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (!finished || !atLeastOneFileAdded) |
||||
|
File.Delete(targetPath); |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
//Ignore
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class NumergeNukeLogger : INumergeLogger |
||||
|
{ |
||||
|
public void Log(NumergeLogLevel level, string message) |
||||
|
{ |
||||
|
if(level == NumergeLogLevel.Error) |
||||
|
Logger.Error(message); |
||||
|
else if (level == NumergeLogLevel.Warning) |
||||
|
Logger.Warn(message); |
||||
|
else |
||||
|
Logger.Info(message); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<OutputType>Exe</OutputType> |
||||
|
<TargetFramework>netcoreapp2.0</TargetFramework> |
||||
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> |
||||
|
<RootNamespace></RootNamespace> |
||||
|
<IsPackable>False</IsPackable> |
||||
|
<NoWarn>CS0649;CS0169</NoWarn> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Nuke.Common" Version="0.12.3" /> |
||||
|
<PackageReference Include="xunit.runner.console" Version="2.3.1" /> |
||||
|
<PackageReference Include="JetBrains.dotMemoryUnit" Version="3.0.20171219.105559" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<NukeMetadata Include="**\*.json" Exclude="bin\**;obj\**" /> |
||||
|
<NukeExternalFiles Include="**\*.*.ext" Exclude="bin\**;obj\**" /> |
||||
|
<None Remove="*.csproj.DotSettings;*.ref.*.txt" /> |
||||
|
|
||||
|
<!-- Common build related files --> |
||||
|
<None Include="..\build.ps1" /> |
||||
|
<None Include="..\build.sh" /> |
||||
|
<None Include="..\.nuke" /> |
||||
|
<None Include="..\global.json" Condition="Exists('..\global.json')" /> |
||||
|
<None Include="..\nuget.config" Condition="Exists('..\nuget.config')" /> |
||||
|
<None Include="..\Jenkinsfile" Condition="Exists('..\Jenkinsfile')" /> |
||||
|
<None Include="..\appveyor.yml" Condition="Exists('..\appveyor.yml')" /> |
||||
|
<None Include="..\.travis.yml" Condition="Exists('..\.travis.yml')" /> |
||||
|
<None Include="..\GitVersion.yml" Condition="Exists('..\GitVersion.yml')" /> |
||||
|
<Compile Remove="Numerge/**/*.*" /> |
||||
|
<Compile Include="Numerge/Numerge/**/*.cs" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,24 @@ |
|||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> |
||||
|
<s:Boolean x:Key="/Default/CodeInspection/ImplicitNullability/EnableFields/@EntryValue">False</s:Boolean> |
||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_INTERNAL_MODIFIER/@EntryValue">Implicit</s:String> |
||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/DEFAULT_PRIVATE_MODIFIER/@EntryValue">Implicit</s:String> |
||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/METHOD_OR_OPERATOR_BODY/@EntryValue">ExpressionBody</s:String> |
||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">0</s:String> |
||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">NEXT_LINE</s:String> |
||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">True</s:Boolean> |
||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_AFTER_INVOCATION_LPAR/@EntryValue">False</s:Boolean> |
||||
|
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/MAX_ATTRIBUTE_LENGTH_FOR_SAME_LINE/@EntryValue">120</s:Int64> |
||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">IF_OWNER_IS_SINGLE_LINE</s:String> |
||||
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_ARGUMENTS_STYLE/@EntryValue">WRAP_IF_LONG</s:String> |
||||
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean> |
||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> |
||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean> |
||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean> |
||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> |
||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean> |
||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean> |
||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean> |
||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> |
||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean> |
||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> |
||||
@ -0,0 +1,23 @@ |
|||||
|
{ |
||||
|
"Packages": |
||||
|
[ |
||||
|
{ |
||||
|
"Id": "Avalonia", |
||||
|
"MergeAll": true, |
||||
|
"Exclude": ["Avalonia.Remote.Protocol"], |
||||
|
"IncomingIncludeAssetsOverride": "", |
||||
|
"Merge": [ |
||||
|
{ |
||||
|
"Id": "Avalonia.Build.Tasks", |
||||
|
"IgnoreMissingFrameworkBinaries": true, |
||||
|
"DoNotMergeDependencies": true |
||||
|
}, |
||||
|
{ |
||||
|
"Id": "Avalonia.DesktopRuntime", |
||||
|
"IgnoreMissingFrameworkBinaries": true, |
||||
|
"IgnoreMissingFrameworkDependencies": true |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
] |
||||
|
} |
||||
@ -1,129 +0,0 @@ |
|||||
using System.Xml.Linq; |
|
||||
using System.Linq; |
|
||||
|
|
||||
public class Parameters |
|
||||
{ |
|
||||
public string Configuration { get; private set; } |
|
||||
public bool SkipTests { get; private set; } |
|
||||
public string MainRepo { get; private set; } |
|
||||
public string MasterBranch { get; private set; } |
|
||||
public string ReleasePlatform { get; private set; } |
|
||||
public string ReleaseConfiguration { get; private set; } |
|
||||
public string ReleaseBranchPrefix { get; private set; } |
|
||||
public string MSBuildSolution { get; private set; } |
|
||||
public bool IsLocalBuild { get; private set; } |
|
||||
public bool IsRunningOnUnix { get; private set; } |
|
||||
public bool IsRunningOnWindows { get; private set; } |
|
||||
public bool IsRunningOnAppVeyor { get; private set; } |
|
||||
public bool IsRunningOnAzure { get; private set; } |
|
||||
public bool IsPullRequest { get; private set; } |
|
||||
public bool IsMainRepo { get; private set; } |
|
||||
public bool IsMasterBranch { get; private set; } |
|
||||
public bool IsReleaseBranch { get; private set; } |
|
||||
public bool IsTagged { get; private set; } |
|
||||
public bool IsReleasable { get; private set; } |
|
||||
public bool IsMyGetRelease { get; private set; } |
|
||||
public bool IsNuGetRelease { get; private set; } |
|
||||
public bool PublishTestResults { get; private set; } |
|
||||
public string Version { get; private set; } |
|
||||
public DirectoryPath ArtifactsDir { get; private set; } |
|
||||
public DirectoryPath NugetRoot { get; private set; } |
|
||||
public DirectoryPath ZipRoot { get; private set; } |
|
||||
public DirectoryPath BinRoot { get; private set; } |
|
||||
public DirectoryPath TestResultsRoot { get; private set; } |
|
||||
public string DirSuffix { get; private set; } |
|
||||
public DirectoryPathCollection BuildDirs { get; private set; } |
|
||||
public string FileZipSuffix { get; private set; } |
|
||||
public FilePath ZipCoreArtifacts { get; private set; } |
|
||||
public FilePath ZipNuGetArtifacts { get; private set; } |
|
||||
public DirectoryPath ZipSourceControlCatalogDesktopDirs { get; private set; } |
|
||||
public FilePath ZipTargetControlCatalogDesktopDirs { get; private set; } |
|
||||
|
|
||||
public Parameters(ICakeContext context) |
|
||||
{ |
|
||||
var buildSystem = context.BuildSystem(); |
|
||||
|
|
||||
// ARGUMENTS |
|
||||
Configuration = context.Argument("configuration", "Release"); |
|
||||
SkipTests = context.HasArgument("skip-tests"); |
|
||||
|
|
||||
// CONFIGURATION |
|
||||
MainRepo = "https://github.com/AvaloniaUI/Avalonia"; |
|
||||
MasterBranch = "master"; |
|
||||
ReleaseBranchPrefix = "refs/heads/release/"; |
|
||||
ReleaseConfiguration = "Release"; |
|
||||
MSBuildSolution = "./dirs.proj"; |
|
||||
|
|
||||
// PARAMETERS |
|
||||
IsLocalBuild = buildSystem.IsLocalBuild; |
|
||||
IsRunningOnUnix = context.IsRunningOnUnix(); |
|
||||
IsRunningOnWindows = context.IsRunningOnWindows(); |
|
||||
IsRunningOnAppVeyor = buildSystem.AppVeyor.IsRunningOnAppVeyor; |
|
||||
IsRunningOnAzure = buildSystem.IsRunningOnVSTS || buildSystem.IsRunningOnTFS || context.EnvironmentVariable("LOGNAME") == "vsts"; |
|
||||
|
|
||||
IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest; |
|
||||
IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, context.EnvironmentVariable("BUILD_REPOSITORY_URI")); |
|
||||
IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME")); |
|
||||
IsReleaseBranch = (context.EnvironmentVariable("BUILD_SOURCEBRANCH")??"").StartsWith(ReleaseBranchPrefix, StringComparison.OrdinalIgnoreCase); |
|
||||
IsTagged = buildSystem.AppVeyor.Environment.Repository.Tag.IsTag |
|
||||
&& !string.IsNullOrWhiteSpace(buildSystem.AppVeyor.Environment.Repository.Tag.Name); |
|
||||
IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration); |
|
||||
IsMyGetRelease = !IsTagged && IsReleasable; |
|
||||
IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch; |
|
||||
|
|
||||
// VERSION |
|
||||
Version = context.Argument("force-nuget-version", GetVersion()); |
|
||||
|
|
||||
if (IsRunningOnAppVeyor) |
|
||||
{ |
|
||||
string tagVersion = null; |
|
||||
if (IsTagged) |
|
||||
{ |
|
||||
var tag = buildSystem.AppVeyor.Environment.Repository.Tag.Name; |
|
||||
var nugetReleasePrefix = "nuget-release-"; |
|
||||
IsNuGetRelease = IsTagged && IsReleasable && tag.StartsWith(nugetReleasePrefix); |
|
||||
if(IsNuGetRelease) |
|
||||
tagVersion = tag.Substring(nugetReleasePrefix.Length); |
|
||||
} |
|
||||
if(tagVersion != null) |
|
||||
{ |
|
||||
Version = tagVersion; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
// Use AssemblyVersion with Build as version |
|
||||
Version += "-build" + context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-beta"; |
|
||||
} |
|
||||
} |
|
||||
else if (IsRunningOnAzure) |
|
||||
{ |
|
||||
if(!IsNuGetRelease) |
|
||||
{ |
|
||||
// Use AssemblyVersion with Build as version |
|
||||
Version += "-build" + context.EnvironmentVariable("BUILD_BUILDID") + "-beta"; |
|
||||
} |
|
||||
|
|
||||
PublishTestResults = true; |
|
||||
} |
|
||||
|
|
||||
// DIRECTORIES |
|
||||
ArtifactsDir = (DirectoryPath)context.Directory("./artifacts"); |
|
||||
NugetRoot = ArtifactsDir.Combine("nuget"); |
|
||||
ZipRoot = ArtifactsDir.Combine("zip"); |
|
||||
BinRoot = ArtifactsDir.Combine("bin"); |
|
||||
TestResultsRoot = ArtifactsDir.Combine("test-results"); |
|
||||
BuildDirs = context.GetDirectories("**/bin") + context.GetDirectories("**/obj"); |
|
||||
DirSuffix = Configuration; |
|
||||
FileZipSuffix = Version + ".zip"; |
|
||||
ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix); |
|
||||
ZipNuGetArtifacts = ZipRoot.CombineWithFilePath("Avalonia-NuGet-" + FileZipSuffix); |
|
||||
ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461"); |
|
||||
ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix); |
|
||||
} |
|
||||
|
|
||||
private static string GetVersion() |
|
||||
{ |
|
||||
var xdoc = XDocument.Load("./build/SharedVersion.props"); |
|
||||
return xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value; |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,6 @@ |
|||||
|
<Application xmlns="https://github.com/avaloniaui"> |
||||
|
<Application.Styles> |
||||
|
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/> |
||||
|
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/> |
||||
|
</Application.Styles> |
||||
|
</Application> |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Avalonia; |
||||
|
using Avalonia.Markup.Xaml; |
||||
|
|
||||
|
namespace PlatformSanityChecks |
||||
|
{ |
||||
|
public class App : Application |
||||
|
{ |
||||
|
public override void Initialize() |
||||
|
{ |
||||
|
AvaloniaXamlLoader.Load(this); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<OutputType>Exe</OutputType> |
||||
|
<TargetFramework>netcoreapp2.0</TargetFramework> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,132 @@ |
|||||
|
using System; |
||||
|
using System.Diagnostics; |
||||
|
using System.Reactive.Disposables; |
||||
|
using System.Runtime.CompilerServices; |
||||
|
using System.Threading; |
||||
|
using Avalonia; |
||||
|
using Avalonia.Platform; |
||||
|
using Avalonia.Threading; |
||||
|
using Avalonia.X11; |
||||
|
|
||||
|
namespace PlatformSanityChecks |
||||
|
{ |
||||
|
public class Program |
||||
|
{ |
||||
|
static Thread UiThread; |
||||
|
|
||||
|
static void Main(string[] args) |
||||
|
{ |
||||
|
UiThread = Thread.CurrentThread; |
||||
|
AppBuilder.Configure<App>().RuntimePlatformServicesInitializer(); |
||||
|
var app = new App(); |
||||
|
|
||||
|
AvaloniaX11PlatformExtensions.InitializeX11Platform(); |
||||
|
|
||||
|
CheckPlatformThreading(); |
||||
|
} |
||||
|
|
||||
|
static bool CheckAccess() => UiThread == Thread.CurrentThread; |
||||
|
|
||||
|
static void VerifyAccess() |
||||
|
{ |
||||
|
if (!CheckAccess()) |
||||
|
Die("Call from invalid thread"); |
||||
|
} |
||||
|
|
||||
|
static Exception Die(string error) |
||||
|
{ |
||||
|
Console.Error.WriteLine(error); |
||||
|
Console.Error.WriteLine(Environment.StackTrace); |
||||
|
Process.GetCurrentProcess().Kill(); |
||||
|
throw new Exception(error); |
||||
|
} |
||||
|
|
||||
|
static IDisposable Enter([CallerMemberName] string caller = null) |
||||
|
{ |
||||
|
Console.WriteLine("Entering " + caller); |
||||
|
return Disposable.Create(() => { Console.WriteLine("Leaving " + caller); }); |
||||
|
} |
||||
|
|
||||
|
static void EnterLoop(Action<CancellationTokenSource> cb, [CallerMemberName] string caller = null) |
||||
|
{ |
||||
|
using (Enter(caller)) |
||||
|
{ |
||||
|
var cts = new CancellationTokenSource(); |
||||
|
cb(cts); |
||||
|
Dispatcher.UIThread.MainLoop(cts.Token); |
||||
|
if (!cts.IsCancellationRequested) |
||||
|
Die("Unexpected loop exit"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static void CheckTimerOrdering() => EnterLoop(cts => |
||||
|
{ |
||||
|
bool firstFired = false, secondFired = false; |
||||
|
DispatcherTimer.Run(() => |
||||
|
{ |
||||
|
Console.WriteLine("Second tick"); |
||||
|
VerifyAccess(); |
||||
|
if (!firstFired) |
||||
|
throw Die("Invalid timer ordering"); |
||||
|
if (secondFired) |
||||
|
throw Die("Invocation of finished timer"); |
||||
|
secondFired = true; |
||||
|
cts.Cancel(); |
||||
|
return false; |
||||
|
}, TimeSpan.FromSeconds(2)); |
||||
|
DispatcherTimer.Run(() => |
||||
|
{ |
||||
|
Console.WriteLine("First tick"); |
||||
|
VerifyAccess(); |
||||
|
if (secondFired) |
||||
|
throw Die("Invalid timer ordering"); |
||||
|
if (firstFired) |
||||
|
throw Die("Invocation of finished timer"); |
||||
|
firstFired = true; |
||||
|
return false; |
||||
|
}, TimeSpan.FromSeconds(1)); |
||||
|
}); |
||||
|
|
||||
|
static void CheckTimerTicking() => EnterLoop(cts => |
||||
|
{ |
||||
|
int ticks = 0; |
||||
|
var st = Stopwatch.StartNew(); |
||||
|
DispatcherTimer.Run(() => |
||||
|
{ |
||||
|
ticks++; |
||||
|
Console.WriteLine($"Tick {ticks} at {st.Elapsed}"); |
||||
|
if (ticks == 5) |
||||
|
{ |
||||
|
if (st.Elapsed.TotalSeconds < 4.5) |
||||
|
Die("Timer is too fast"); |
||||
|
if (st.Elapsed.TotalSeconds > 6) |
||||
|
Die("Timer is too slow"); |
||||
|
cts.Cancel(); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
}, TimeSpan.FromSeconds(1)); |
||||
|
}); |
||||
|
|
||||
|
static void CheckSignaling() => EnterLoop(cts => |
||||
|
{ |
||||
|
ThreadPool.QueueUserWorkItem(_ => |
||||
|
{ |
||||
|
Thread.Sleep(100); |
||||
|
Dispatcher.UIThread.Post(() => |
||||
|
{ |
||||
|
VerifyAccess(); |
||||
|
cts.Cancel(); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
static void CheckPlatformThreading() |
||||
|
{ |
||||
|
CheckSignaling(); |
||||
|
CheckTimerOrdering(); |
||||
|
CheckTimerTicking(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// 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.
|
||||
|
|
||||
|
namespace Avalonia.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="bool"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class BoolAnimator : Animator<bool> |
||||
|
{ |
||||
|
/// <inheritdocs/>
|
||||
|
public override bool Interpolate(double progress, bool oldValue, bool newValue) |
||||
|
{ |
||||
|
if(progress >= 1d) |
||||
|
return newValue; |
||||
|
if(progress >= 0) |
||||
|
return oldValue; |
||||
|
return oldValue; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
// 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.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="byte"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class ByteAnimator : Animator<byte> |
||||
|
{ |
||||
|
const double maxVal = (double)byte.MaxValue; |
||||
|
|
||||
|
/// <inheritdocs/>
|
||||
|
public override byte Interpolate(double progress, byte oldValue, byte newValue) |
||||
|
{ |
||||
|
var normOV = oldValue / maxVal; |
||||
|
var normNV = newValue / maxVal; |
||||
|
var deltaV = normNV - normOV; |
||||
|
return (byte)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
// 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.
|
||||
|
|
||||
|
namespace Avalonia.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="decimal"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class DecimalAnimator : Animator<decimal> |
||||
|
{ |
||||
|
/// <inheritdocs/>
|
||||
|
public override decimal Interpolate(double progress, decimal oldValue, decimal newValue) |
||||
|
{ |
||||
|
return ((newValue - oldValue) * (decimal)progress) + oldValue; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
// 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.
|
||||
|
|
||||
|
namespace Avalonia.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="double"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class DoubleAnimator : Animator<double> |
||||
|
{ |
||||
|
/// <inheritdocs/>
|
||||
|
public override double Interpolate(double progress, double oldValue, double newValue) |
||||
|
{ |
||||
|
return ((newValue - oldValue) * progress) + oldValue; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
// 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.
|
||||
|
|
||||
|
namespace Avalonia.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="float"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class FloatAnimator : Animator<float> |
||||
|
{ |
||||
|
/// <inheritdocs/>
|
||||
|
public override float Interpolate(double progress, float oldValue, float newValue) |
||||
|
{ |
||||
|
return (float)(((newValue - oldValue) * progress) + oldValue); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
// 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.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="Int16"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class Int16Animator : Animator<Int16> |
||||
|
{ |
||||
|
const double maxVal = (double)Int16.MaxValue; |
||||
|
|
||||
|
/// <inheritdocs/>
|
||||
|
public override Int16 Interpolate(double progress, Int16 oldValue, Int16 newValue) |
||||
|
{ |
||||
|
var normOV = oldValue / maxVal; |
||||
|
var normNV = newValue / maxVal; |
||||
|
var deltaV = normNV - normOV; |
||||
|
return (Int16)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
// 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.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="Int32"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class Int32Animator : Animator<Int32> |
||||
|
{ |
||||
|
const double maxVal = (double)Int32.MaxValue; |
||||
|
|
||||
|
/// <inheritdocs/>
|
||||
|
public override Int32 Interpolate(double progress, Int32 oldValue, Int32 newValue) |
||||
|
{ |
||||
|
var normOV = oldValue / maxVal; |
||||
|
var normNV = newValue / maxVal; |
||||
|
var deltaV = normNV - normOV; |
||||
|
return (Int32)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
// 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.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="Int64"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class Int64Animator : Animator<Int64> |
||||
|
{ |
||||
|
const double maxVal = (double)Int64.MaxValue; |
||||
|
|
||||
|
/// <inheritdocs/>
|
||||
|
public override Int64 Interpolate(double progress, Int64 oldValue, Int64 newValue) |
||||
|
{ |
||||
|
var normOV = oldValue / maxVal; |
||||
|
var normNV = newValue / maxVal; |
||||
|
var deltaV = normNV - normOV; |
||||
|
return (Int64)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
// 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.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="UInt16"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class UInt16Animator : Animator<UInt16> |
||||
|
{ |
||||
|
const double maxVal = (double)UInt16.MaxValue; |
||||
|
|
||||
|
/// <inheritdocs/>
|
||||
|
public override UInt16 Interpolate(double progress, UInt16 oldValue, UInt16 newValue) |
||||
|
{ |
||||
|
var normOV = oldValue / maxVal; |
||||
|
var normNV = newValue / maxVal; |
||||
|
var deltaV = normNV - normOV; |
||||
|
return (UInt16)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
// 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.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="UInt32"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class UInt32Animator : Animator<UInt32> |
||||
|
{ |
||||
|
const double maxVal = (double)UInt32.MaxValue; |
||||
|
|
||||
|
/// <inheritdocs/>
|
||||
|
public override UInt32 Interpolate(double progress, UInt32 oldValue, UInt32 newValue) |
||||
|
{ |
||||
|
var normOV = oldValue / maxVal; |
||||
|
var normNV = newValue / maxVal; |
||||
|
var deltaV = normNV - normOV; |
||||
|
return (UInt32)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
// 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.Animation.Animators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Animator that handles <see cref="UInt64"/> properties.
|
||||
|
/// </summary>
|
||||
|
public class UInt64Animator : Animator<UInt64> |
||||
|
{ |
||||
|
const double maxVal = (double)UInt64.MaxValue; |
||||
|
|
||||
|
/// <inheritdocs/>
|
||||
|
public override UInt64 Interpolate(double progress, UInt64 oldValue, UInt64 newValue) |
||||
|
{ |
||||
|
var normOV = oldValue / maxVal; |
||||
|
var normNV = newValue / maxVal; |
||||
|
var deltaV = normNV - normOV; |
||||
|
return (UInt64)Math.Round(maxVal * ((deltaV * progress) + normOV)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,35 +0,0 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
namespace Avalonia.Animation |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Animator that handles <see cref="double"/> properties.
|
|
||||
/// </summary>
|
|
||||
public class DoubleAnimator : Animator<double> |
|
||||
{ |
|
||||
|
|
||||
/// <inheritdocs/>
|
|
||||
protected override double DoInterpolation(double t, double neutralValue) |
|
||||
{ |
|
||||
var pair = GetKFPairAndIntraKFTime(t); |
|
||||
double y0, y1; |
|
||||
|
|
||||
var firstKF = pair.KFPair.FirstKeyFrame; |
|
||||
var secondKF = pair.KFPair.SecondKeyFrame; |
|
||||
|
|
||||
if (firstKF.isNeutral) |
|
||||
y0 = neutralValue; |
|
||||
else |
|
||||
y0 = firstKF.TargetValue; |
|
||||
|
|
||||
if (secondKF.isNeutral) |
|
||||
y1 = neutralValue; |
|
||||
else |
|
||||
y1 = secondKF.TargetValue; |
|
||||
|
|
||||
// Do linear parametric interpolation
|
|
||||
return y0 + (pair.IntraKFTime) * (y1 - y0); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,176 @@ |
|||||
|
// 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.ComponentModel; |
||||
|
using System.Globalization; |
||||
|
|
||||
|
namespace Avalonia.Animation |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Defines the valid modes for a <see cref="IterationCount"/>.
|
||||
|
/// </summary>
|
||||
|
public enum IterationType |
||||
|
{ |
||||
|
Many, |
||||
|
Infinite |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Determines the number of iterations of an animation.
|
||||
|
/// Also defines its repeat behavior.
|
||||
|
/// </summary>
|
||||
|
[TypeConverter(typeof(IterationCountTypeConverter))] |
||||
|
public struct IterationCount : IEquatable<IterationCount> |
||||
|
{ |
||||
|
private readonly IterationType _type; |
||||
|
private readonly ulong _value; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="IterationCount"/> struct.
|
||||
|
/// </summary>
|
||||
|
/// <param name="value">The number of iterations of an animation.</param>
|
||||
|
public IterationCount(ulong value) |
||||
|
: this(value, IterationType.Many) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="IterationCount"/> struct.
|
||||
|
/// </summary>
|
||||
|
/// <param name="value">The size of the IterationCount.</param>
|
||||
|
/// <param name="type">The unit of the IterationCount.</param>
|
||||
|
public IterationCount(ulong value, IterationType type) |
||||
|
{ |
||||
|
if (type > IterationType.Infinite) |
||||
|
{ |
||||
|
throw new ArgumentException("Invalid value", nameof(type)); |
||||
|
} |
||||
|
|
||||
|
_type = type; |
||||
|
_value = value; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets an instance of <see cref="IterationCount"/> that indicates that an animation
|
||||
|
/// should repeat forever.
|
||||
|
/// </summary>
|
||||
|
public static IterationCount Infinite => new IterationCount(0, IterationType.Infinite); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the unit of the <see cref="IterationCount"/>.
|
||||
|
/// </summary>
|
||||
|
public IterationType RepeatType => _type; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value that indicates whether the <see cref="IterationCount"/> is set to loop.
|
||||
|
/// </summary>
|
||||
|
public bool IsInfinite => _type == IterationType.Infinite; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the number of repeat iterations.
|
||||
|
/// </summary>
|
||||
|
public ulong Value => _value; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Compares two IterationCount structures for equality.
|
||||
|
/// </summary>
|
||||
|
/// <param name="a">The first IterationCount.</param>
|
||||
|
/// <param name="b">The second IterationCount.</param>
|
||||
|
/// <returns>True if the structures are equal, otherwise false.</returns>
|
||||
|
public static bool operator ==(IterationCount a, IterationCount b) |
||||
|
{ |
||||
|
return (a.IsInfinite && b.IsInfinite) |
||||
|
|| (a._value == b._value && a._type == b._type); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Compares two IterationCount structures for inequality.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rc1">The first IterationCount.</param>
|
||||
|
/// <param name="rc2">The first IterationCount.</param>
|
||||
|
/// <returns>True if the structures are unequal, otherwise false.</returns>
|
||||
|
public static bool operator !=(IterationCount rc1, IterationCount rc2) |
||||
|
{ |
||||
|
return !(rc1 == rc2); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Determines whether the <see cref="IterationCount"/> is equal to the specified object.
|
||||
|
/// </summary>
|
||||
|
/// <param name="o">The object with which to test equality.</param>
|
||||
|
/// <returns>True if the objects are equal, otherwise false.</returns>
|
||||
|
public override bool Equals(object o) |
||||
|
{ |
||||
|
if (o == null) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (!(o is IterationCount)) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return this == (IterationCount)o; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Compares two IterationCount structures for equality.
|
||||
|
/// </summary>
|
||||
|
/// <param name="IterationCount">The structure with which to test equality.</param>
|
||||
|
/// <returns>True if the structures are equal, otherwise false.</returns>
|
||||
|
public bool Equals(IterationCount IterationCount) |
||||
|
{ |
||||
|
return this == IterationCount; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a hash code for the IterationCount.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The hash code.</returns>
|
||||
|
public override int GetHashCode() |
||||
|
{ |
||||
|
return _value.GetHashCode() ^ _type.GetHashCode(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a string representation of the <see cref="IterationCount"/>.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The string representation.</returns>
|
||||
|
public override string ToString() |
||||
|
{ |
||||
|
if (IsInfinite) |
||||
|
{ |
||||
|
return "Infinite"; |
||||
|
} |
||||
|
|
||||
|
string s = _value.ToString(); |
||||
|
return s; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Parses a string to return a <see cref="IterationCount"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="s">The string.</param>
|
||||
|
/// <returns>The <see cref="IterationCount"/>.</returns>
|
||||
|
public static IterationCount Parse(string s) |
||||
|
{ |
||||
|
s = s.ToUpperInvariant().Trim(); |
||||
|
|
||||
|
if (s.EndsWith("INFINITE")) |
||||
|
{ |
||||
|
return Infinite; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (s.StartsWith("-")) |
||||
|
throw new InvalidCastException("IterationCount can't be a negative number."); |
||||
|
|
||||
|
var value = ulong.Parse(s, CultureInfo.InvariantCulture); |
||||
|
|
||||
|
return new IterationCount(value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,33 +0,0 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
namespace Avalonia.Animation |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Represents a pair of keyframe, usually the
|
|
||||
/// Start and End keyframes of a <see cref="Animator{T}"/> object.
|
|
||||
/// </summary>
|
|
||||
public struct KeyFramePair<T> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes this <see cref="KeyFramePair{T}"/>
|
|
||||
/// </summary>
|
|
||||
/// <param name="FirstKeyFrame"></param>
|
|
||||
/// <param name="LastKeyFrame"></param>
|
|
||||
public KeyFramePair((T TargetValue, bool isNeutral) FirstKeyFrame, (T TargetValue, bool isNeutral) LastKeyFrame) : this() |
|
||||
{ |
|
||||
this.FirstKeyFrame = FirstKeyFrame; |
|
||||
this.SecondKeyFrame = LastKeyFrame; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// First <see cref="KeyFrame"/> object.
|
|
||||
/// </summary>
|
|
||||
public (T TargetValue, bool isNeutral) FirstKeyFrame { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Second <see cref="KeyFrame"/> object.
|
|
||||
/// </summary>
|
|
||||
public (T TargetValue, bool isNeutral) SecondKeyFrame { get; } |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,33 @@ |
|||||
|
// 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.Collections.Generic; |
||||
|
using Avalonia.Collections; |
||||
|
|
||||
|
namespace Avalonia.Animation |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A collection of <see cref="KeyFrame"/>s.
|
||||
|
/// </summary>
|
||||
|
public class KeyFrames : AvaloniaList<KeyFrame> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="KeyFrames"/> class.
|
||||
|
/// </summary>
|
||||
|
public KeyFrames() |
||||
|
{ |
||||
|
ResetBehavior = ResetBehavior.Remove; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="KeyFrames"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="items">The initial items in the collection.</param>
|
||||
|
public KeyFrames(IEnumerable<KeyFrame> items) |
||||
|
: base(items) |
||||
|
{ |
||||
|
ResetBehavior = ResetBehavior.Remove; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,199 +0,0 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
using System; |
|
||||
using System.ComponentModel; |
|
||||
using System.Globalization; |
|
||||
|
|
||||
namespace Avalonia.Animation |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Defines the valid modes for a <see cref="RepeatCount"/>.
|
|
||||
/// </summary>
|
|
||||
public enum RepeatType |
|
||||
{ |
|
||||
None, |
|
||||
Repeat, |
|
||||
Loop |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Determines the number of iterations of an animation.
|
|
||||
/// Also defines its repeat behavior.
|
|
||||
/// </summary>
|
|
||||
[TypeConverter(typeof(RepeatCountTypeConverter))] |
|
||||
public struct RepeatCount : IEquatable<RepeatCount> |
|
||||
{ |
|
||||
private readonly RepeatType _type; |
|
||||
private readonly ulong _value; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="RepeatCount"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The number of iterations of an animation.</param>
|
|
||||
public RepeatCount(ulong value) |
|
||||
: this(value, RepeatType.Repeat) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="RepeatCount"/> struct.
|
|
||||
/// </summary>
|
|
||||
/// <param name="value">The size of the RepeatCount.</param>
|
|
||||
/// <param name="type">The unit of the RepeatCount.</param>
|
|
||||
public RepeatCount(ulong value, RepeatType type) |
|
||||
{ |
|
||||
if (type < RepeatType.None || type > RepeatType.Loop) |
|
||||
{ |
|
||||
throw new ArgumentException("Invalid value", "type"); |
|
||||
} |
|
||||
|
|
||||
_type = type; |
|
||||
_value = value; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets an instance of <see cref="RepeatCount"/> that indicates that an animation
|
|
||||
/// should repeat forever.
|
|
||||
/// </summary>
|
|
||||
public static RepeatCount Loop => new RepeatCount(0, RepeatType.Loop); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets an instance of <see cref="RepeatCount"/> that indicates that an animation
|
|
||||
/// should not repeat.
|
|
||||
/// </summary>
|
|
||||
public static RepeatCount None => new RepeatCount(0, RepeatType.None); |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the unit of the <see cref="RepeatCount"/>.
|
|
||||
/// </summary>
|
|
||||
public RepeatType RepeatType => _type; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value that indicates whether the <see cref="RepeatCount"/> is set to loop.
|
|
||||
/// </summary>
|
|
||||
public bool IsLoop => _type == RepeatType.Loop; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a value that indicates whether the <see cref="RepeatCount"/> is set to not repeat.
|
|
||||
/// </summary>
|
|
||||
public bool IsNone => _type == RepeatType.None; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the number of repeat iterations.
|
|
||||
/// </summary>
|
|
||||
public ulong Value => _value; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Compares two RepeatCount structures for equality.
|
|
||||
/// </summary>
|
|
||||
/// <param name="a">The first RepeatCount.</param>
|
|
||||
/// <param name="b">The second RepeatCount.</param>
|
|
||||
/// <returns>True if the structures are equal, otherwise false.</returns>
|
|
||||
public static bool operator ==(RepeatCount a, RepeatCount b) |
|
||||
{ |
|
||||
return (a.IsNone && b.IsNone) && (a.IsLoop && b.IsLoop) |
|
||||
|| (a._value == b._value && a._type == b._type); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Compares two RepeatCount structures for inequality.
|
|
||||
/// </summary>
|
|
||||
/// <param name="rc1">The first RepeatCount.</param>
|
|
||||
/// <param name="rc2">The first RepeatCount.</param>
|
|
||||
/// <returns>True if the structures are unequal, otherwise false.</returns>
|
|
||||
public static bool operator !=(RepeatCount rc1, RepeatCount rc2) |
|
||||
{ |
|
||||
return !(rc1 == rc2); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Determines whether the <see cref="RepeatCount"/> is equal to the specified object.
|
|
||||
/// </summary>
|
|
||||
/// <param name="o">The object with which to test equality.</param>
|
|
||||
/// <returns>True if the objects are equal, otherwise false.</returns>
|
|
||||
public override bool Equals(object o) |
|
||||
{ |
|
||||
if (o == null) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
if (!(o is RepeatCount)) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
return this == (RepeatCount)o; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Compares two RepeatCount structures for equality.
|
|
||||
/// </summary>
|
|
||||
/// <param name="RepeatCount">The structure with which to test equality.</param>
|
|
||||
/// <returns>True if the structures are equal, otherwise false.</returns>
|
|
||||
public bool Equals(RepeatCount RepeatCount) |
|
||||
{ |
|
||||
return this == RepeatCount; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a hash code for the RepeatCount.
|
|
||||
/// </summary>
|
|
||||
/// <returns>The hash code.</returns>
|
|
||||
public override int GetHashCode() |
|
||||
{ |
|
||||
return _value.GetHashCode() ^ _type.GetHashCode(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets a string representation of the <see cref="RepeatCount"/>.
|
|
||||
/// </summary>
|
|
||||
/// <returns>The string representation.</returns>
|
|
||||
public override string ToString() |
|
||||
{ |
|
||||
if (IsLoop) |
|
||||
{ |
|
||||
return "Auto"; |
|
||||
} |
|
||||
else if (IsNone) |
|
||||
{ |
|
||||
return "None"; |
|
||||
} |
|
||||
|
|
||||
string s = _value.ToString(); |
|
||||
return s; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Parses a string to return a <see cref="RepeatCount"/>.
|
|
||||
/// </summary>
|
|
||||
/// <param name="s">The string.</param>
|
|
||||
/// <returns>The <see cref="RepeatCount"/>.</returns>
|
|
||||
public static RepeatCount Parse(string s) |
|
||||
{ |
|
||||
s = s.ToUpperInvariant().Trim(); |
|
||||
|
|
||||
if (s == "NONE") |
|
||||
{ |
|
||||
return None; |
|
||||
} |
|
||||
else if (s.EndsWith("LOOP")) |
|
||||
{ |
|
||||
return Loop; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
if(s.StartsWith("-")) |
|
||||
throw new InvalidCastException("RepeatCount can't be a negative number."); |
|
||||
|
|
||||
var value = ulong.Parse(s, CultureInfo.InvariantCulture); |
|
||||
|
|
||||
if (value == 1) |
|
||||
return None; |
|
||||
|
|
||||
return new RepeatCount(value); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,24 @@ |
|||||
|
// 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.
|
||||
|
|
||||
|
|
||||
|
namespace Avalonia.Data.Converters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Provides a set of useful <see cref="IValueConverter"/>s for working with objects.
|
||||
|
/// </summary>
|
||||
|
public static class ObjectConverters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A value converter that returns true if the input object is a null reference.
|
||||
|
/// </summary>
|
||||
|
public static readonly IValueConverter IsNull = |
||||
|
new FuncValueConverter<object, bool>(x => x is null); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A value converter that returns true if the input object is not null.
|
||||
|
/// </summary>
|
||||
|
public static readonly IValueConverter IsNotNull = |
||||
|
new FuncValueConverter<object, bool>(x => !(x is null)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Avalonia.Threading |
||||
|
{ |
||||
|
public class ThreadSafeObjectPool<T> where T : class, new() |
||||
|
{ |
||||
|
private Stack<T> _stack = new Stack<T>(); |
||||
|
private object _lock = new object(); |
||||
|
public static ThreadSafeObjectPool<T> Default { get; } = new ThreadSafeObjectPool<T>(); |
||||
|
|
||||
|
public T Get() |
||||
|
{ |
||||
|
lock (_lock) |
||||
|
{ |
||||
|
if(_stack.Count == 0) |
||||
|
return new T(); |
||||
|
return _stack.Pop(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Return(T obj) |
||||
|
{ |
||||
|
lock (_stack) |
||||
|
{ |
||||
|
_stack.Push(obj); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue