diff --git a/Avalonia.sln b/Avalonia.sln
index 3c2fc7437b..0354e20d4f 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -60,20 +60,17 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
+ src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}"
EndProject
-Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlatformSupport", "src\Shared\PlatformSupport\PlatformSupport.shproj", "{E4D9629C-F168-4224-3F51-A5E482FFBC42}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup", "src\Markup\Avalonia.Markup\Avalonia.Markup.csproj", "{6417E941-21BC-467B-A771-0DE389353CE6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BindingDemo", "samples\BindingDemo\BindingDemo.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}"
EndProject
-Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "RenderHelpers", "src\Shared\RenderHelpers\RenderHelpers.shproj", "{3C4C0CB4-0C0F-4450-A37B-148C84FF905F}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Skia", "Skia", "{3743B0F2-CC41-4F14-A8C8-267F579BF91E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}"
@@ -221,8 +218,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.Xaml.Loader
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sandbox", "samples\Sandbox\Sandbox.csproj", "{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroComGenerator", "src\tools\MicroComGenerator\MicroComGenerator.csproj", "{AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.MicroCom", "src\Avalonia.MicroCom\Avalonia.MicroCom.csproj", "{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniMvvm", "samples\MiniMvvm\MiniMvvm.csproj", "{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}"
@@ -237,15 +232,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsInteropTest", "sampl
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlSamples", "samples\SampleControls\ControlSamples.csproj", "{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport", "src\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj", "{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}"
+EndProject
Global
- GlobalSection(SharedMSBuildProjectFiles) = preSolution
- src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
- src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 5
- src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*SharedItemsImports = 5
- src\Shared\RenderHelpers\RenderHelpers.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 5
- src\Shared\PlatformSupport\PlatformSupport.projitems*{88060192-33d5-4932-b0f9-8bd2763e857d}*SharedItemsImports = 5
- src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13
- EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
Ad-Hoc|iPhone = Ad-Hoc|iPhone
@@ -2027,30 +2016,6 @@ Global
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Release|iPhone.Build.0 = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|Any CPU.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhone.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhone.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhone.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|Any CPU.Build.0 = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhone.ActiveCfg = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhone.Build.0 = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
@@ -2195,6 +2160,30 @@ Global
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhone.Build.0 = Release|Any CPU
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhone.Build.0 = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2213,11 +2202,9 @@ Global
{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{99135EAB-653D-47E4-A378-C96E1278CA44} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{3E53A01A-B331-47F3-B828-4A5717E77A24} = {8B6A8209-894F-4BA1-B880-965FD453982C}
- {E4D9629C-F168-4224-3F51-A5E482FFBC42} = {A689DEF5-D50F-4975-8B72-124C9EB54066}
{6417E941-21BC-467B-A771-0DE389353CE6} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{8EF392D5-1416-45AA-9956-7CBBC3229E8A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162} = {9B9E3891-2366-4253-A952-D08BCEB71098}
- {3C4C0CB4-0C0F-4450-A37B-148C84FF905F} = {A689DEF5-D50F-4975-8B72-124C9EB54066}
{7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
{FF69B927-C545-49AE-8E16-3D14D621AA12} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
{4488AD85-1495-4809-9AA4-DDFE0A48527E} = {0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}
@@ -2253,7 +2240,6 @@ Global
{3C84E04B-36CF-4D0D-B965-C26DD649D1F3} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098}
- {AEC9031E-06EA-4A9E-9E7F-7D7C719404DD} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{25831348-EB2A-483E-9576-E8F6528674A5} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{C08E9894-AA92-426E-BF56-033E262CAD3E} = {9B9E3891-2366-4253-A952-D08BCEB71098}
diff --git a/NuGet.Config b/NuGet.Config
index e430390d39..7a1f28bea7 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -5,6 +5,5 @@
-
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 903146cdd7..40669f4f53 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -2,6 +2,33 @@ variables:
MSBuildEnableWorkloadResolver: 'false'
jobs:
+
+- job: GetPRNumber
+ pool:
+ vmImage: 'windows-2022'
+ variables:
+ SolutionDir: '$(Build.SourcesDirectory)'
+ steps:
+
+ - task: PowerShell@2
+ displayName: Get PR Number
+ inputs:
+ targetType: 'inline'
+ script: |
+ $prId = $env:System_PullRequest_PullRequestNumber
+ Write-Host "PR Number is:-" $env:System_PullRequest_PullRequestNumber
+
+ if (!([string]::IsNullOrWhiteSpace($prId)))
+ {
+ Set-Content -Path $env:Build_ArtifactStagingDirectory\prId.txt -Value $prId
+ }
+
+ - task: PublishBuildArtifacts@1
+ inputs:
+ PathtoPublish: '$(Build.ArtifactStagingDirectory)'
+ ArtifactName: 'PRNumber'
+ publishLocation: 'Container'
+
- job: Linux
pool:
vmImage: 'ubuntu-20.04'
@@ -58,8 +85,10 @@ jobs:
displayName: 'Generate avalonia-native'
inputs:
script: |
- export PATH="`pwd`/sdk:$PATH"
- cd src/tools/MicroComGenerator; dotnet run -f net6.0 -i ../../Avalonia.Native/avn.idl --cpp ../../../native/Avalonia.Native/inc/avalonia-native.h
+ export COREHOST_TRACE=0
+ export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
+ export DOTNET_CLI_TELEMETRY_OPTOUT=1
+ ./build.sh --target GenerateCppHeaders --configuration Release
- task: Xcode@5
inputs:
diff --git a/build/CoreLibraries.props b/build/CoreLibraries.props
index fff00041c3..3fccad2641 100644
--- a/build/CoreLibraries.props
+++ b/build/CoreLibraries.props
@@ -17,5 +17,6 @@
+
diff --git a/build/HarfBuzzSharp.props b/build/HarfBuzzSharp.props
index 1346a1dafc..1d84d5289a 100644
--- a/build/HarfBuzzSharp.props
+++ b/build/HarfBuzzSharp.props
@@ -1,7 +1,7 @@
-
-
-
+
+
+
diff --git a/build/MicroCom.targets b/build/MicroCom.targets
deleted file mode 100644
index 029d7f95f5..0000000000
--- a/build/MicroCom.targets
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
- false
- all
- true
- TargetFramework=net6.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_AvaloniaPatchComInterop>true
-
-
-
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 7d75901288..7f24ef35bc 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -3,7 +3,7 @@
Avalonia
0.10.999
- Copyright 2021 © The AvaloniaUI Project
+ Copyright 2022 © The AvaloniaUI Project
https://avaloniaui.net
https://github.com/AvaloniaUI/Avalonia/
true
diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props
index 4a75a18290..bb370256f9 100644
--- a/build/SkiaSharp.props
+++ b/build/SkiaSharp.props
@@ -1,7 +1,7 @@
-
-
-
+
+
+
diff --git a/build/SourceLink.props b/build/SourceLink.props
index 1e007e01eb..9f05848881 100644
--- a/build/SourceLink.props
+++ b/build/SourceLink.props
@@ -3,7 +3,6 @@
true
false
true
- embedded
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
@@ -15,6 +14,10 @@
true
+
+ embedded
+
+
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index 16f49b8e26..40180274e1 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -43,6 +43,7 @@ public:
StandardContainer = [[AutoFitContentView new] initWithContent:View];
Window = [[AvnWindow alloc] initWithParent:this];
+ [Window setContentView: StandardContainer];
lastPositionSet.X = 100;
lastPositionSet.Y = 100;
@@ -124,8 +125,6 @@ public:
SetPosition(lastPositionSet);
UpdateStyle();
- [Window setContentView: StandardContainer];
-
[Window setTitle:_lastTitle];
if(ShouldTakeFocusOnShow() && activate)
@@ -328,8 +327,8 @@ public:
BaseEvents->Resized(AvnSize{x,y}, reason);
}
- [StandardContainer setFrameSize:NSSize{x,y}];
- [Window setContentSize:NSSize{x, y}];
+ [Window setContentSize:NSSize{x,y}];
+ [Window invalidateShadow];
}
@finally
{
@@ -1628,6 +1627,19 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
return;
}
}
+ else if (type == Magnify)
+ {
+ delta.X = delta.Y = [event magnification];
+ }
+ else if (type == Rotate)
+ {
+ delta.X = delta.Y = [event rotation];
+ }
+ else if (type == Swipe)
+ {
+ delta.X = [event deltaX];
+ delta.Y = [event deltaY];
+ }
auto timestamp = [event timestamp] * 1000;
auto modifiers = [self getModifiers:[event modifierFlags]];
@@ -1754,6 +1766,24 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
[super scrollWheel:event];
}
+- (void)magnifyWithEvent:(NSEvent *)event
+{
+ [self mouseEvent:event withType:Magnify];
+ [super magnifyWithEvent:event];
+}
+
+- (void)rotateWithEvent:(NSEvent *)event
+{
+ [self mouseEvent:event withType:Rotate];
+ [super rotateWithEvent:event];
+}
+
+- (void)swipeWithEvent:(NSEvent *)event
+{
+ [self mouseEvent:event withType:Swipe];
+ [super swipeWithEvent:event];
+}
+
- (void)mouseEntered:(NSEvent *)event
{
_isMouseOver = true;
diff --git a/nukebuild/MicroComGen.cs b/nukebuild/MicroComGen.cs
index 06c8acbf23..b1e546cb97 100644
--- a/nukebuild/MicroComGen.cs
+++ b/nukebuild/MicroComGen.cs
@@ -1,14 +1,14 @@
using System.IO;
-using MicroComGenerator;
+using MicroCom.CodeGenerator;
using Nuke.Common;
partial class Build : NukeBuild
{
Target GenerateCppHeaders => _ => _.Executes(() =>
{
- var text = File.ReadAllText(RootDirectory / "src" / "Avalonia.Native" / "avn.idl");
- var ast = AstParser.Parse(text);
+ var file = MicroComCodeGenerator.Parse(
+ File.ReadAllText(RootDirectory / "src" / "Avalonia.Native" / "avn.idl"));
File.WriteAllText(RootDirectory / "native" / "Avalonia.Native" / "inc" / "avalonia-native.h",
- CppGen.GenerateCpp(ast));
+ file.GenerateCppHeader());
});
}
\ No newline at end of file
diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj
index b28d3eb700..52b60b7d0f 100644
--- a/nukebuild/_build.csproj
+++ b/nukebuild/_build.csproj
@@ -15,7 +15,7 @@
-
+
@@ -37,10 +37,6 @@
-
- MicroComGenerator\%(Filename)%(Extension)
-
-
diff --git a/packages/Avalonia/Avalonia.csproj b/packages/Avalonia/Avalonia.csproj
index af9ed71c5f..4b28527465 100644
--- a/packages/Avalonia/Avalonia.csproj
+++ b/packages/Avalonia/Avalonia.csproj
@@ -1,6 +1,6 @@
- netstandard2.0;net461;netcoreapp2.0;net6.0
+ net6.0;netstandard2.0;net461;netcoreapp2.0
Avalonia
diff --git a/readme.md b/readme.md
index a8a6399f2f..96c7937559 100644
--- a/readme.md
+++ b/readme.md
@@ -3,13 +3,11 @@
[](https://www.nuget.org/packages/Avalonia) [](https://www.nuget.org/packages/Avalonia) [](https://www.myget.org/gallery/avalonia-ci) 
-## 📖 About AvaloniaUI
+## 📖 About
-Avalonia is a cross-platform XAML-based UI framework providing a flexible styling system and supporting a wide range of Operating Systems such as Windows via .NET Framework and .NET Core, Linux via Xorg, macOS. Avalonia is ready for **General-Purpose Desktop App Development**. However, there may be some bugs and breaking changes as we continue along into this project's development.
+Avalonia is a cross-platform UI framework for dotnet, providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, MacOs. Avalonia is mature and production ready. We also have in beta release support for iOS, Android and in early stages support for browser via WASM.
-
-
-([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
+
To see the status of some of our features, please see our [Roadmap](https://github.com/AvaloniaUI/Avalonia/issues/2239). You can also see what [breaking changes](https://github.com/AvaloniaUI/Avalonia/issues/3538) we have planned and what our [past breaking changes](https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes) have been. [Awesome Avalonia](https://github.com/AvaloniaCommunity/awesome-avalonia) is community-curated list of awesome Avalonia UI tools, libraries, projects and resources. Go and see what people are building with Avalonia!
@@ -28,18 +26,15 @@ Install-Package Avalonia.Desktop
## Showcase
Examples of UIs built with Avalonia
-
-
-([Synfonia](https://github.com/jmacato/Synfonia))
+
+([Lunacy](https://icons8.com/lunacy))
-
-([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
+
+([PlasticSCM](https://www.plasticscm.com/))
-
-([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
+
+([WasabiWallet](https://www.wasabiwallet.io/))
-
-([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
## JetBrains Rider
@@ -75,6 +70,12 @@ For more information see the [.NET Foundation Code of Conduct](https://dotnetfou
Avalonia is licenced under the [MIT licence](licence.md).
+## Support Avalonia
+
+**BTC**: bc1q05wx78qemgy9x6ytl5ljk2xrt00yqargyjm8gx
+
+This will be shared with the community and awarded for significant contributions.
+
### Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/Avalonia#backer)]
diff --git a/samples/ControlCatalog.Android/Assets/AboutAssets.txt b/samples/ControlCatalog.Android/Assets/AboutAssets.txt
index ee39886295..a9b0638eb1 100644
--- a/samples/ControlCatalog.Android/Assets/AboutAssets.txt
+++ b/samples/ControlCatalog.Android/Assets/AboutAssets.txt
@@ -1,7 +1,7 @@
Any raw assets you want to be deployed with your application can be placed in
this directory (and child directories) and given a Build Action of "AndroidAsset".
-These files will be deployed with you package and will be accessible using Android's
+These files will be deployed with your package and will be accessible using Android's
AssetManager, like this:
public class ReadAsset : Activity
@@ -16,4 +16,4 @@ public class ReadAsset : Activity
Additionally, some Android functions will automatically load asset files:
-Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
\ No newline at end of file
+Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
index 1a68c4d732..617b6b6ab0 100644
--- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
+++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
@@ -32,7 +32,7 @@
True
False
False
- armeabi-v7a;x86
+ armeabi-v7a;x86;x86_64
Xamarin
False
False
@@ -51,7 +51,7 @@
True
False
False
- armeabi-v7a,x86
+ armeabi-v7a,x86;x86_64
Xamarin
False
False
@@ -125,6 +125,10 @@
{42472427-4774-4c81-8aff-9f27b8e31721}
Avalonia.Layout
+
+ {c42d2fc1-a531-4ed4-84b9-89aec7c962fc}
+ Avalonia.Themes.Fluent
+
{eb582467-6abb-43a1-b052-e981ba910e3a}
Avalonia.Visuals
diff --git a/samples/ControlCatalog.Web/ControlCatalog.Web.csproj b/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
index d463dfa84a..199fa85ad2 100644
--- a/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
+++ b/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
@@ -2,6 +2,7 @@
net6.0
enable
+ True
diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml
index 227b31bf20..d0e1bd885e 100644
--- a/samples/ControlCatalog/App.xaml
+++ b/samples/ControlCatalog/App.xaml
@@ -3,6 +3,7 @@
xmlns:vm="using:ControlCatalog.ViewModels"
x:DataType="vm:ApplicationViewModel"
x:CompileBindings="True"
+ Name="Avalonia ControlCatalog"
x:Class="ControlCatalog.App">
-
-
- Inline Items
- Inline Item 2
- Inline Item 3
- Inline Item 4
-
+
+
+
+
+
-
-
-
-
- Hello
- World
-
-
-
-
-
-
-
-
-
-
-
+
+ Inline Items
+ Inline Item 2
+ Inline Item 3
+ Inline Item 4
+
-
-
-
-
- Control Items
-
-
-
-
-
-
-
-
-
+
+
+
+
+ Hello
+ World
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
- Inline Items
- Inline Item 2
- Inline Item 3
- Inline Item 4
-
-
-
-
-
+
+
+
+
+ Control Items
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+ Inline Items
+ Inline Item 2
+ Inline Item 3
+ Inline Item 4
+
+
+
+
+
+
+ WrapSelection
+
+
+
diff --git a/samples/ControlCatalog/Pages/ComboBoxPage.xaml.cs b/samples/ControlCatalog/Pages/ComboBoxPage.xaml.cs
index d50b051d9f..d304bf227d 100644
--- a/samples/ControlCatalog/Pages/ComboBoxPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ComboBoxPage.xaml.cs
@@ -2,6 +2,7 @@ using System.Linq;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
+using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
{
@@ -10,6 +11,7 @@ namespace ControlCatalog.Pages
public ComboBoxPage()
{
this.InitializeComponent();
+ DataContext = new ComboBoxPageViewModel();
}
private void InitializeComponent()
diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml b/samples/ControlCatalog/Pages/DataGridPage.xaml
index 63e873d9b5..f7e3cf2441 100644
--- a/samples/ControlCatalog/Pages/DataGridPage.xaml
+++ b/samples/ControlCatalog/Pages/DataGridPage.xaml
@@ -64,6 +64,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml.cs b/samples/ControlCatalog/Pages/DataGridPage.xaml.cs
index dc5cc49a90..c010d38eac 100644
--- a/samples/ControlCatalog/Pages/DataGridPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/DataGridPage.xaml.cs
@@ -6,7 +6,9 @@ using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using ControlCatalog.Models;
using Avalonia.Collections;
+using Avalonia.Controls.Primitives;
using Avalonia.Data;
+using Avalonia.Threading;
namespace ControlCatalog.Pages
{
@@ -48,9 +50,9 @@ namespace ControlCatalog.Pages
var items = new List
{
- new Person { FirstName = "John", LastName = "Doe" },
- new Person { FirstName = "Elizabeth", LastName = "Thomas", IsBanned = true },
- new Person { FirstName = "Zack", LastName = "Ward" }
+ new Person { FirstName = "John", LastName = "Doe" , Age = 30},
+ new Person { FirstName = "Elizabeth", LastName = "Thomas", IsBanned = true , Age = 40 },
+ new Person { FirstName = "Zack", LastName = "Ward" , Age = 50 }
};
var collectionView3 = new DataGridCollectionView(items);
@@ -84,5 +86,19 @@ namespace ControlCatalog.Pages
return Comparer.Default.Compare(x, y);
}
}
+
+ private void NumericUpDown_OnTemplateApplied(object sender, TemplateAppliedEventArgs e)
+ {
+ // We want to focus the TextBox of the NumericUpDown. To do so we search for this control when the template
+ // is applied, but we postpone the action until the control is actually loaded.
+ if (e.NameScope.Find("PART_TextBox") is {} textBox)
+ {
+ Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ textBox.Focus();
+ textBox.SelectAll();
+ }, DispatcherPriority.Loaded);
+ }
+ }
}
}
diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml b/samples/ControlCatalog/Pages/ListBoxPage.xaml
index 41658329df..433592345a 100644
--- a/samples/ControlCatalog/Pages/ListBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml
@@ -21,6 +21,7 @@
Toggle
AlwaysSelected
AutoScrollToSelectedItem
+ WrapSelection
@@ -30,6 +31,7 @@
+ SelectionMode="{Binding SelectionMode^}"
+ WrapSelection="{Binding WrapSelection}"/>
diff --git a/samples/ControlCatalog/Pages/PointersPage.cs b/samples/ControlCatalog/Pages/PointersPage.cs
index 60e946dfbe..2901013cea 100644
--- a/samples/ControlCatalog/Pages/PointersPage.cs
+++ b/samples/ControlCatalog/Pages/PointersPage.cs
@@ -1,15 +1,37 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
+using System.Reactive.Linq;
+using System.Runtime.InteropServices;
+using System.Threading;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
+using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Media.Immutable;
+using Avalonia.Threading;
+using Avalonia.VisualTree;
-namespace ControlCatalog.Pages
+namespace ControlCatalog.Pages;
+
+public class PointersPage : Decorator
{
- public class PointersPage : Control
+ public PointersPage()
+ {
+ Child = new TabControl
+ {
+ Items = new[]
+ {
+ new TabItem() { Header = "Contacts", Content = new PointerContactsTab() },
+ new TabItem() { Header = "IntermediatePoints", Content = new PointerIntermediatePointsTab() }
+ }
+ };
+ }
+
+
+ class PointerContactsTab : Control
{
class PointerInfo
{
@@ -45,7 +67,7 @@ namespace ControlCatalog.Pages
private Dictionary _pointers = new Dictionary();
- public PointersPage()
+ public PointerContactsTab()
{
ClipToBounds = true;
}
@@ -99,10 +121,201 @@ namespace ControlCatalog.Pages
foreach (var pt in _pointers.Values)
{
var brush = new ImmutableSolidColorBrush(pt.Color);
- context.DrawGeometry(brush, null, new EllipseGeometry(new Rect(pt.Point.X - 75, pt.Point.Y - 75,
- 150, 150)));
+
+ context.DrawEllipse(brush, null, pt.Point, 75, 75);
+ }
+ }
+ }
+
+ public class PointerIntermediatePointsTab : Decorator
+ {
+ public PointerIntermediatePointsTab()
+ {
+ this[TextBlock.ForegroundProperty] = Brushes.Black;
+ var slider = new Slider
+ {
+ Margin = new Thickness(5),
+ Minimum = 0,
+ Maximum = 500
+ };
+
+ var status = new TextBlock()
+ {
+ HorizontalAlignment = HorizontalAlignment.Left,
+ VerticalAlignment = VerticalAlignment.Top,
+ };
+ Child = new Grid
+ {
+ Children =
+ {
+ new PointerCanvas(slider, status),
+ new Border
+ {
+ Background = Brushes.LightYellow,
+ Child = new StackPanel
+ {
+ Children =
+ {
+ new StackPanel
+ {
+ Orientation = Orientation.Horizontal,
+ Children =
+ {
+ new TextBlock { Text = "Thread sleep:" },
+ new TextBlock()
+ {
+ [!TextBlock.TextProperty] =slider.GetObservable(Slider.ValueProperty)
+ .Select(x=>x.ToString()).ToBinding()
+ }
+ }
+ },
+ slider
+ }
+ },
+
+ HorizontalAlignment = HorizontalAlignment.Right,
+ VerticalAlignment = VerticalAlignment.Top,
+ Width = 300,
+ Height = 60
+ },
+ status
+ }
+ };
+ }
+
+ class PointerCanvas : Control
+ {
+ private readonly Slider _slider;
+ private readonly TextBlock _status;
+ private int _events;
+ private Stopwatch _stopwatch = Stopwatch.StartNew();
+ private Dictionary _pointers = new();
+ class PointerPoints
+ {
+ struct CanvasPoint
+ {
+ public IBrush Brush;
+ public Point Point;
+ public double Radius;
+ }
+
+ readonly CanvasPoint[] _points = new CanvasPoint[1000];
+ int _index;
+
+ public void Render(DrawingContext context)
+ {
+
+ CanvasPoint? prev = null;
+ for (var c = 0; c < _points.Length; c++)
+ {
+ var i = (c + _index) % _points.Length;
+ var pt = _points[i];
+ if (prev.HasValue && prev.Value.Brush != null && pt.Brush != null)
+ context.DrawLine(new Pen(Brushes.Black), prev.Value.Point, pt.Point);
+ prev = pt;
+ if (pt.Brush != null)
+ context.DrawEllipse(pt.Brush, null, pt.Point, pt.Radius, pt.Radius);
+
+ }
+
+ }
+
+ void AddPoint(Point pt, IBrush brush, double radius)
+ {
+ _points[_index] = new CanvasPoint { Point = pt, Brush = brush, Radius = radius };
+ _index = (_index + 1) % _points.Length;
+ }
+
+ public void HandleEvent(PointerEventArgs e, Visual v)
+ {
+ e.Handled = true;
+ if (e.RoutedEvent == PointerPressedEvent)
+ AddPoint(e.GetPosition(v), Brushes.Green, 10);
+ else if (e.RoutedEvent == PointerReleasedEvent)
+ AddPoint(e.GetPosition(v), Brushes.Red, 10);
+ else
+ {
+ var pts = e.GetIntermediatePoints(v);
+ for (var c = 0; c < pts.Count; c++)
+ {
+ var pt = pts[c];
+ AddPoint(pt.Position, c == pts.Count - 1 ? Brushes.Blue : Brushes.Black,
+ c == pts.Count - 1 ? 5 : 2);
+ }
+ }
+ }
+ }
+
+ public PointerCanvas(Slider slider, TextBlock status)
+ {
+ _slider = slider;
+ _status = status;
+ DispatcherTimer.Run(() =>
+ {
+ if (_stopwatch.Elapsed.TotalSeconds > 1)
+ {
+ _status.Text = "Events per second: " + (_events / _stopwatch.Elapsed.TotalSeconds);
+ _stopwatch.Restart();
+ _events = 0;
+ }
+
+ return this.GetVisualRoot() != null;
+ }, TimeSpan.FromMilliseconds(10));
+ }
+
+
+ void HandleEvent(PointerEventArgs e)
+ {
+ _events++;
+ Thread.Sleep((int)_slider.Value);
+ InvalidateVisual();
+
+ if (e.RoutedEvent == PointerReleasedEvent && e.Pointer.Type == PointerType.Touch)
+ {
+ _pointers.Remove(e.Pointer.Id);
+ return;
+ }
+
+ if (!_pointers.TryGetValue(e.Pointer.Id, out var pt))
+ _pointers[e.Pointer.Id] = pt = new PointerPoints();
+ pt.HandleEvent(e, this);
+
+
}
+ public override void Render(DrawingContext context)
+ {
+ context.FillRectangle(Brushes.White, Bounds);
+ foreach(var pt in _pointers.Values)
+ pt.Render(context);
+ base.Render(context);
+ }
+
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
+ {
+ if (e.ClickCount == 2)
+ {
+ _pointers.Clear();
+ InvalidateVisual();
+ return;
+ }
+
+ HandleEvent(e);
+ base.OnPointerPressed(e);
+ }
+
+ protected override void OnPointerMoved(PointerEventArgs e)
+ {
+ HandleEvent(e);
+ base.OnPointerMoved(e);
+ }
+
+ protected override void OnPointerReleased(PointerReleasedEventArgs e)
+ {
+ HandleEvent(e);
+ base.OnPointerReleased(e);
+ }
}
+
}
}
diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs
index 4edb0f137a..caad8b0854 100644
--- a/samples/ControlCatalog/Pages/ScreenPage.cs
+++ b/samples/ControlCatalog/Pages/ScreenPage.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
@@ -49,25 +50,33 @@ namespace ControlCatalog.Pages
context.DrawRectangle(p, boundsRect);
context.DrawRectangle(p, workingAreaRect);
- var text = new FormattedText() { Typeface = new Typeface("Arial"), FontSize = 18 };
- text.Text = $"Bounds: {screen.Bounds.TopLeft} {screen.Bounds.Width}:{screen.Bounds.Height}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height), text);
-
- text.Text = $"WorkArea: {screen.WorkingArea.TopLeft} {screen.WorkingArea.Width}:{screen.WorkingArea.Height}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text);
+ var formattedText = CreateFormattedText($"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height));
- text.Text = $"Scaling: {screen.PixelDensity * 100}%";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
-
- text.Text = $"Primary: {screen.Primary}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
-
- text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 80), text);
+ formattedText =
+ CreateFormattedText($"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 20));
+
+ formattedText = CreateFormattedText($"Scaling: {screen.PixelDensity * 100}%");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40));
+
+ formattedText = CreateFormattedText($"Primary: {screen.Primary}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 60));
+
+ formattedText =
+ CreateFormattedText(
+ $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 80));
}
context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10f, w.Bounds.Width / 10, w.Bounds.Height / 10));
}
+
+ private FormattedText CreateFormattedText(string textToFormat)
+ {
+ return new FormattedText(textToFormat, CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
+ Typeface.Default, 12, Brushes.Green);
+ }
}
}
diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml b/samples/ControlCatalog/Pages/ViewboxPage.xaml
index 81e5046636..e7e3007d35 100644
--- a/samples/ControlCatalog/Pages/ViewboxPage.xaml
+++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml
@@ -1,5 +1,6 @@
@@ -12,8 +13,8 @@
+ Stretch="{Binding #StretchSelector.SelectedItem, FallbackValue={x:Static Stretch.Uniform}}"
+ StretchDirection="{Binding #StretchDirectionSelector.SelectedItem, FallbackValue={x:Static StretchDirection.Both}}">
@@ -25,9 +26,22 @@
-
+
+
+ Uniform
+ UniformToFill
+ Fill
+ None
+
+
-
+
+
+ Both
+ DownOnly
+ UpOnly
+
+
diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
index 94b3f3ea14..12b5086e12 100644
--- a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
@@ -1,6 +1,5 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
-using Avalonia.Media;
namespace ControlCatalog.Pages
{
@@ -9,24 +8,6 @@ namespace ControlCatalog.Pages
public ViewboxPage()
{
InitializeComponent();
-
- var stretchSelector = this.FindControl("StretchSelector");
-
- stretchSelector.Items = new[]
- {
- Stretch.Uniform, Stretch.UniformToFill, Stretch.Fill, Stretch.None
- };
-
- stretchSelector.SelectedIndex = 0;
-
- var stretchDirectionSelector = this.FindControl("StretchDirectionSelector");
-
- stretchDirectionSelector.Items = new[]
- {
- StretchDirection.Both, StretchDirection.DownOnly, StretchDirection.UpOnly
- };
-
- stretchDirectionSelector.SelectedIndex = 0;
}
private void InitializeComponent()
diff --git a/samples/ControlCatalog/ViewModels/ComboBoxPageViewModel.cs b/samples/ControlCatalog/ViewModels/ComboBoxPageViewModel.cs
new file mode 100644
index 0000000000..bbe970afd6
--- /dev/null
+++ b/samples/ControlCatalog/ViewModels/ComboBoxPageViewModel.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reactive;
+using Avalonia.Controls;
+using Avalonia.Controls.Selection;
+using MiniMvvm;
+
+namespace ControlCatalog.ViewModels
+{
+ public class ComboBoxPageViewModel : ViewModelBase
+ {
+ private bool _wrapSelection;
+
+ public bool WrapSelection
+ {
+ get => _wrapSelection;
+ set => this.RaiseAndSetIfChanged(ref _wrapSelection, value);
+ }
+ }
+}
diff --git a/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs b/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
index 7f2d6e9572..59489ebcc0 100644
--- a/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
@@ -14,6 +14,7 @@ namespace ControlCatalog.ViewModels
private bool _toggle;
private bool _alwaysSelected;
private bool _autoScrollToSelectedItem = true;
+ private bool _wrapSelection;
private int _counter;
private IObservable _selectionMode;
@@ -85,6 +86,12 @@ namespace ControlCatalog.ViewModels
set => this.RaiseAndSetIfChanged(ref _autoScrollToSelectedItem, value);
}
+ public bool WrapSelection
+ {
+ get => _wrapSelection;
+ set => this.RaiseAndSetIfChanged(ref _wrapSelection, value);
+ }
+
public MiniCommand AddItemCommand { get; }
public MiniCommand RemoveItemCommand { get; }
public MiniCommand SelectRandomItemCommand { get; }
diff --git a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
index 4b3cfa9c9d..2b0c30f311 100644
--- a/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
@@ -5,6 +5,7 @@ using Avalonia.Controls.Notifications;
using Avalonia.Dialogs;
using Avalonia.Platform;
using System;
+using System.ComponentModel.DataAnnotations;
using MiniMvvm;
namespace ControlCatalog.ViewModels
@@ -164,5 +165,17 @@ namespace ControlCatalog.ViewModels
public MiniCommand ExitCommand { get; }
public MiniCommand ToggleMenuItemCheckedCommand { get; }
+
+ private DateTime? _validatedDateExample;
+
+ ///
+ /// A required DateTime which should demonstrate validation for the DateTimePicker
+ ///
+ [Required]
+ public DateTime? ValidatedDateExample
+ {
+ get => _validatedDateExample;
+ set => this.RaiseAndSetIfChanged(ref _validatedDateExample, value);
+ }
}
}
diff --git a/samples/RenderDemo/MainWindow.xaml b/samples/RenderDemo/MainWindow.xaml
index a4c6299278..4a8fb819ca 100644
--- a/samples/RenderDemo/MainWindow.xaml
+++ b/samples/RenderDemo/MainWindow.xaml
@@ -57,6 +57,9 @@
+
+
+
diff --git a/samples/RenderDemo/Pages/ClippingPage.xaml b/samples/RenderDemo/Pages/ClippingPage.xaml
index 10225f7c49..698e18d496 100644
--- a/samples/RenderDemo/Pages/ClippingPage.xaml
+++ b/samples/RenderDemo/Pages/ClippingPage.xaml
@@ -19,30 +19,36 @@
-
+
+
+
+
diff --git a/samples/RenderDemo/Pages/ClippingPage.xaml.cs b/samples/RenderDemo/Pages/ClippingPage.xaml.cs
index 5357181838..c5b669343a 100644
--- a/samples/RenderDemo/Pages/ClippingPage.xaml.cs
+++ b/samples/RenderDemo/Pages/ClippingPage.xaml.cs
@@ -1,35 +1,18 @@
-using System;
-using System.Reactive.Linq;
-using Avalonia;
-using Avalonia.Animation;
using Avalonia.Controls;
-using Avalonia.Data;
using Avalonia.Markup.Xaml;
-using Avalonia.Media;
namespace RenderDemo.Pages
{
public class ClippingPage : UserControl
{
- private Geometry _clip;
-
public ClippingPage()
{
InitializeComponent();
- WireUpCheckbox();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
-
- private void WireUpCheckbox()
- {
- var useMask = this.FindControl("useMask");
- var clipped = this.FindControl("clipped");
- _clip = clipped.Clip;
- useMask.Click += (s, e) => clipped.Clip = clipped.Clip == null ? _clip : null;
- }
}
}
diff --git a/samples/RenderDemo/Pages/CustomSkiaPage.cs b/samples/RenderDemo/Pages/CustomSkiaPage.cs
index 2e59d934a1..9c524a7932 100644
--- a/samples/RenderDemo/Pages/CustomSkiaPage.cs
+++ b/samples/RenderDemo/Pages/CustomSkiaPage.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
+using System.Globalization;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
@@ -41,7 +42,10 @@ namespace RenderDemo.Pages
{
var canvas = (context as ISkiaDrawingContextImpl)?.SkCanvas;
if (canvas == null)
- context.DrawText(Brushes.Black, new Point(), _noSkia.PlatformImpl);
+ using (var c = new DrawingContext(context, false))
+ {
+ c.DrawText(_noSkia, new Point());
+ }
else
{
canvas.Save();
@@ -108,10 +112,9 @@ namespace RenderDemo.Pages
public override void Render(DrawingContext context)
{
- var noSkia = new FormattedText()
- {
- Text = "Current rendering API is not Skia"
- };
+ var noSkia = new FormattedText("Current rendering API is not Skia", CultureInfo.CurrentCulture,
+ FlowDirection.LeftToRight, Typeface.Default, 12, Brushes.Black);
+
context.Custom(new CustomDrawOp(new Rect(0, 0, Bounds.Width, Bounds.Height), noSkia));
Dispatcher.UIThread.InvokeAsync(InvalidateVisual, DispatcherPriority.Background);
}
diff --git a/samples/RenderDemo/Pages/FormattedTextPage.axaml b/samples/RenderDemo/Pages/FormattedTextPage.axaml
new file mode 100644
index 0000000000..92775bec9e
--- /dev/null
+++ b/samples/RenderDemo/Pages/FormattedTextPage.axaml
@@ -0,0 +1,7 @@
+
+
diff --git a/samples/RenderDemo/Pages/FormattedTextPage.axaml.cs b/samples/RenderDemo/Pages/FormattedTextPage.axaml.cs
new file mode 100644
index 0000000000..25e29c67a9
--- /dev/null
+++ b/samples/RenderDemo/Pages/FormattedTextPage.axaml.cs
@@ -0,0 +1,60 @@
+using System.Globalization;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.Media;
+
+namespace RenderDemo.Pages
+{
+ public class FormattedTextPage : UserControl
+ {
+ public FormattedTextPage()
+ {
+ this.InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void Render(DrawingContext context)
+ {
+ const string testString = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor";
+
+ // Create the initial formatted text string.
+ var formattedText = new FormattedText(
+ testString,
+ CultureInfo.GetCultureInfo("en-us"),
+ FlowDirection.LeftToRight,
+ new Typeface("Verdana"),
+ 32,
+ Brushes.Black) { MaxTextWidth = 300, MaxTextHeight = 240 };
+
+ // Set a maximum width and height. If the text overflows these values, an ellipsis "..." appears.
+
+ // Use a larger font size beginning at the first (zero-based) character and continuing for 5 characters.
+ // The font size is calculated in terms of points -- not as device-independent pixels.
+ formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5);
+
+ // Use a Bold font weight beginning at the 6th character and continuing for 11 characters.
+ formattedText.SetFontWeight(FontWeight.Bold, 6, 11);
+
+ var gradient = new LinearGradientBrush
+ {
+ GradientStops =
+ new GradientStops { new GradientStop(Colors.Orange, 0), new GradientStop(Colors.Teal, 1) },
+ StartPoint = new RelativePoint(0,0, RelativeUnit.Relative),
+ EndPoint = new RelativePoint(0,1, RelativeUnit.Relative)
+ };
+
+ // Use a linear gradient brush beginning at the 6th character and continuing for 11 characters.
+ formattedText.SetForegroundBrush(gradient, 6, 11);
+
+ // Use an Italic font style beginning at the 28th character and continuing for 28 characters.
+ formattedText.SetFontStyle(FontStyle.Italic, 28, 28);
+
+ context.DrawText(formattedText, new Point(10, 0));
+ }
+ }
+}
diff --git a/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs b/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
index 857358f6b2..7f85606957 100644
--- a/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
+++ b/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
@@ -13,6 +13,7 @@ namespace RenderDemo.Pages
private GlyphTypeface _glyphTypeface = Typeface.Default.GlyphTypeface;
private readonly Random _rand = new Random();
private ushort[] _glyphIndices = new ushort[1];
+ private char[] _characters = new char[1];
private float _fontSize = 20;
private int _direction = 10;
@@ -38,7 +39,7 @@ namespace RenderDemo.Pages
private void UpdateGlyphRun()
{
- var c = (uint)_rand.Next(65, 90);
+ var c = (char)_rand.Next(65, 90);
if (_fontSize + _direction > 200)
{
@@ -54,6 +55,8 @@ namespace RenderDemo.Pages
_glyphIndices[0] = _glyphTypeface.GetGlyph(c);
+ _characters[0] = c;
+
var scale = (double)_fontSize / _glyphTypeface.DesignEmHeight;
var drawingGroup = new DrawingGroup();
@@ -61,7 +64,7 @@ namespace RenderDemo.Pages
var glyphRunDrawing = new GlyphRunDrawing
{
Foreground = Brushes.Black,
- GlyphRun = new GlyphRun(_glyphTypeface, _fontSize, _glyphIndices),
+ GlyphRun = new GlyphRun(_glyphTypeface, _fontSize, _characters, _glyphIndices)
};
drawingGroup.Children.Add(glyphRunDrawing);
diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs
index 5e11d8eab2..2d4f6a305f 100644
--- a/src/Android/Avalonia.Android/AndroidPlatform.cs
+++ b/src/Android/Avalonia.Android/AndroidPlatform.cs
@@ -10,7 +10,7 @@ using Avalonia.Input.Platform;
using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
using Avalonia.Rendering;
-using Avalonia.Shared.PlatformSupport;
+using Avalonia.PlatformSupport;
using Avalonia.Skia;
namespace Avalonia
@@ -33,8 +33,16 @@ namespace Avalonia.Android
{
public static readonly AndroidPlatform Instance = new AndroidPlatform();
public static AndroidPlatformOptions Options { get; private set; }
- public Size DoubleClickSize => new Size(4, 4);
- public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(200);
+
+ ///
+ public Size TouchDoubleClickSize => new Size(4, 4);
+
+ ///
+ public TimeSpan TouchDoubleClickTime => TimeSpan.FromMilliseconds(200);
+
+ public Size DoubleClickSize => TouchDoubleClickSize;
+
+ public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(500);
public static void Initialize(Type appType, AndroidPlatformOptions options)
{
@@ -43,15 +51,15 @@ namespace Avalonia.Android
AvaloniaLocator.CurrentMutable
.Bind().ToTransient()
.Bind().ToTransient()
+ .Bind().ToConstant(new WindowingPlatformStub())
.Bind().ToSingleton()
.Bind().ToConstant(Instance)
.Bind().ToConstant(new AndroidThreadingInterface())
.Bind().ToTransient()
- .Bind().ToSingleton()
+ .Bind().ToSingleton()
.Bind().ToConstant(new ChoreographerTimer())
.Bind().ToConstant(new RenderLoop())
- .Bind().ToSingleton()
- .Bind().ToConstant(new AssetLoader(appType.Assembly));
+ .Bind().ToSingleton();
SkiaPlatform.Initialize();
diff --git a/src/Android/Avalonia.Android/AppBuilder.cs b/src/Android/Avalonia.Android/AppBuilder.cs
index 805bb61655..04f1ff00d0 100644
--- a/src/Android/Avalonia.Android/AppBuilder.cs
+++ b/src/Android/Avalonia.Android/AppBuilder.cs
@@ -1,5 +1,5 @@
using Avalonia.Controls;
-using Avalonia.Shared.PlatformSupport;
+using Avalonia.PlatformSupport;
namespace Avalonia
{
diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj
index 8c6775733f..5c33dbcea6 100644
--- a/src/Android/Avalonia.Android/Avalonia.Android.csproj
+++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj
@@ -5,9 +5,11 @@
+
+ TargetFramework=netstandard2.0
+
-
diff --git a/src/Android/Avalonia.Android/RuntimeInfo.cs b/src/Android/Avalonia.Android/RuntimeInfo.cs
deleted file mode 100644
index bb2466c357..0000000000
--- a/src/Android/Avalonia.Android/RuntimeInfo.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Avalonia.Platform;
-
-namespace Avalonia.Shared.PlatformSupport
-{
- internal partial class StandardRuntimePlatform
- {
- public RuntimePlatformInfo GetRuntimeInfo() => new RuntimePlatformInfo
- {
- IsCoreClr = false,
- IsDesktop = false,
- IsMobile = true,
- IsDotNetFramework = false,
- IsMono = true,
- IsUnix = true,
- OperatingSystem = OperatingSystemType.Android
- };
- }
-}
\ No newline at end of file
diff --git a/src/Android/Avalonia.Android/Stubs.cs b/src/Android/Avalonia.Android/Stubs.cs
new file mode 100644
index 0000000000..f36c01dbc8
--- /dev/null
+++ b/src/Android/Avalonia.Android/Stubs.cs
@@ -0,0 +1,56 @@
+using System;
+using System.IO;
+using Avalonia.Platform;
+
+namespace Avalonia.Android
+{
+ class WindowingPlatformStub : IWindowingPlatform
+ {
+ public IWindowImpl CreateWindow() => throw new NotSupportedException();
+
+ public IWindowImpl CreateEmbeddableWindow() => throw new NotSupportedException();
+
+ public ITrayIconImpl CreateTrayIcon() => null;
+ }
+
+ class PlatformIconLoaderStub : IPlatformIconLoader
+ {
+ public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
+ {
+ using (var stream = new MemoryStream())
+ {
+ bitmap.Save(stream);
+ return LoadIcon(stream);
+ }
+ }
+
+ public IWindowIconImpl LoadIcon(Stream stream)
+ {
+ var ms = new MemoryStream();
+ stream.CopyTo(ms);
+ return new IconStub(ms);
+ }
+
+ public IWindowIconImpl LoadIcon(string fileName)
+ {
+ using (var file = File.Open(fileName, FileMode.Open))
+ return LoadIcon(file);
+ }
+ }
+
+ public class IconStub : IWindowIconImpl
+ {
+ private readonly MemoryStream _ms;
+
+ public IconStub(MemoryStream stream)
+ {
+ _ms = stream;
+ }
+
+ public void Save(Stream outputStream)
+ {
+ _ms.Position = 0;
+ _ms.CopyTo(outputStream);
+ }
+ }
+}
diff --git a/src/Android/Avalonia.AndroidTestApplication/Resources/Resource.Designer.cs b/src/Android/Avalonia.AndroidTestApplication/Resources/Resource.Designer.cs
index 83db67fcee..87fd47df25 100644
--- a/src/Android/Avalonia.AndroidTestApplication/Resources/Resource.Designer.cs
+++ b/src/Android/Avalonia.AndroidTestApplication/Resources/Resource.Designer.cs
@@ -14,7 +14,7 @@ namespace Avalonia.AndroidTestApplication
{
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "12.1.99.62")]
public partial class Resource
{
diff --git a/src/Avalonia.Animation/Animatable.cs b/src/Avalonia.Animation/Animatable.cs
index 4811028f85..50fc5ac73b 100644
--- a/src/Avalonia.Animation/Animatable.cs
+++ b/src/Avalonia.Animation/Animatable.cs
@@ -157,7 +157,7 @@ namespace Avalonia.Animation
state.Instance?.Dispose();
state.Instance = transition.Apply(
this,
- Clock ?? AvaloniaLocator.Current.GetService(),
+ Clock ?? AvaloniaLocator.Current.GetRequiredService(),
oldValue,
newValue);
return;
@@ -169,7 +169,7 @@ namespace Avalonia.Animation
base.OnPropertyChangedCore(change);
}
- private void TransitionsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void TransitionsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (!_transitionsEnabled)
{
@@ -179,14 +179,14 @@ namespace Avalonia.Animation
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
- AddTransitions(e.NewItems);
+ AddTransitions(e.NewItems!);
break;
case NotifyCollectionChangedAction.Remove:
- RemoveTransitions(e.OldItems);
+ RemoveTransitions(e.OldItems!);
break;
case NotifyCollectionChangedAction.Replace:
- RemoveTransitions(e.OldItems);
- AddTransitions(e.NewItems);
+ RemoveTransitions(e.OldItems!);
+ AddTransitions(e.NewItems!);
break;
case NotifyCollectionChangedAction.Reset:
throw new NotSupportedException("Transitions collection cannot be reset.");
@@ -204,7 +204,7 @@ namespace Avalonia.Animation
for (var i = 0; i < items.Count; ++i)
{
- var t = (ITransition)items[i];
+ var t = (ITransition)items[i]!;
_transitionState.Add(t, new TransitionState
{
@@ -222,7 +222,7 @@ namespace Avalonia.Animation
for (var i = 0; i < items.Count; ++i)
{
- var t = (ITransition)items[i];
+ var t = (ITransition)items[i]!;
if (_transitionState.TryGetValue(t, out var state))
{
diff --git a/src/Avalonia.Animation/Animation.cs b/src/Avalonia.Animation/Animation.cs
index a4515db514..03b2d17e44 100644
--- a/src/Avalonia.Animation/Animation.cs
+++ b/src/Avalonia.Animation/Animation.cs
@@ -203,7 +203,7 @@ namespace Avalonia.Animation
///
/// The animation setter.
/// The property animator type.
- public static Type GetAnimator(IAnimationSetter setter)
+ public static Type? GetAnimator(IAnimationSetter setter)
{
if (s_animators.TryGetValue(setter, out var type))
{
@@ -254,7 +254,7 @@ namespace Avalonia.Animation
Animators.Insert(0, (condition, typeof(TAnimator)));
}
- private static Type GetAnimatorType(AvaloniaProperty property)
+ private static Type? GetAnimatorType(AvaloniaProperty property)
{
foreach (var (condition, type) in Animators)
{
@@ -276,6 +276,11 @@ namespace Avalonia.Animation
{
foreach (var setter in keyframe.Setters)
{
+ if (setter.Property is null)
+ {
+ throw new InvalidOperationException("No Setter property assigned.");
+ }
+
var handler = Animation.GetAnimator(setter) ?? GetAnimatorType(setter.Property);
if (handler == null)
@@ -305,7 +310,7 @@ namespace Avalonia.Animation
foreach (var (handlerType, property) in handlerList)
{
- var newInstance = (IAnimator)Activator.CreateInstance(handlerType);
+ var newInstance = (IAnimator)Activator.CreateInstance(handlerType)!;
newInstance.Property = property;
newAnimatorInstances.Add(newInstance);
}
@@ -321,32 +326,43 @@ namespace Avalonia.Animation
}
///
- public IDisposable Apply(Animatable control, IClock clock, IObservable match, Action onComplete)
+ public IDisposable Apply(Animatable control, IClock? clock, IObservable match, Action? onComplete)
{
var (animators, subscriptions) = InterpretKeyframes(control);
if (animators.Count == 1)
{
- subscriptions.Add(animators[0].Apply(this, control, clock, match, onComplete));
+ var subscription = animators[0].Apply(this, control, clock, match, onComplete);
+
+ if (subscription is not null)
+ {
+ subscriptions.Add(subscription);
+ }
}
else
{
var completionTasks = onComplete != null ? new List() : null;
foreach (IAnimator animator in animators)
{
- Action animatorOnComplete = null;
+ Action? animatorOnComplete = null;
if (onComplete != null)
{
- var tcs = new TaskCompletionSource