Browse Source

Use TemplatePart

pull/10882/head
Benedikt Stebner 3 years ago
parent
commit
384e090d10
  1. 5
      .ncrunch/AppWithoutLifetime.v3.ncrunchproject
  2. 5
      .ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject
  3. 5
      .ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject
  4. 11
      Avalonia.Desktop.slnf
  5. 3
      Avalonia.sln
  6. 2
      build/SharedVersion.props
  7. 6
      dirs.proj
  8. 2
      nukebuild/Build.cs
  9. 101
      nukebuild/RefAssemblyGenerator.cs
  10. 6
      nukebuild/_build.csproj
  11. 2
      packages/Avalonia/Avalonia.csproj
  12. 1
      packages/Avalonia/Avalonia.targets
  13. 26
      packages/Avalonia/AvaloniaPrivateApis.targets
  14. 7
      samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
  15. 11
      samples/ControlCatalog.Desktop/Program.cs
  16. 1
      samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
  17. 5
      samples/ControlCatalog/MainView.xaml.cs
  18. 3
      samples/ControlCatalog/Pages/ColorPickerPage.xaml
  19. 4
      samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs
  20. 2
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  21. 5
      samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs
  22. 3
      samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs
  23. 29
      samples/ControlCatalog/Pages/TabControlPage.xaml
  24. 2
      samples/ControlCatalog/Pages/TabControlPage.xaml.cs
  25. 2
      samples/ControlCatalog/ViewModels/TabControlPageViewModel.cs
  26. 2
      samples/GpuInterop/MainWindow.axaml.cs
  27. 2
      samples/GpuInterop/VulkanDemo/VulkanContext.cs
  28. 3
      samples/IntegrationTestApp/MainWindow.axaml
  29. 2
      samples/IntegrationTestApp/MainWindow.axaml.cs
  30. 21
      samples/MobileSandbox.Desktop/MobileSandbox.Desktop.csproj
  31. 15
      samples/MobileSandbox/MobileSandbox.csproj
  32. 2
      samples/RenderDemo/MainWindow.xaml.cs
  33. 4
      samples/RenderDemo/Pages/AnimationsPage.xaml
  34. 15
      samples/RenderDemo/Pages/AnimationsPage.xaml.cs
  35. 12
      samples/RenderDemo/Pages/CustomAnimatorPage.xaml
  36. 6
      samples/RenderDemo/Pages/CustomSkiaPage.cs
  37. 5
      samples/RenderDemo/Pages/CustomStringAnimator.cs
  38. 8
      samples/RenderDemo/Pages/PathMeasurementPage.cs
  39. 3
      samples/RenderDemo/Pages/Transform3DPage.axaml
  40. 4
      samples/RenderDemo/Pages/TransitionsPage.xaml
  41. 15
      samples/RenderDemo/Pages/TransitionsPage.xaml.cs
  42. 1
      samples/Sandbox/Sandbox.csproj
  43. 6
      samples/VirtualizationDemo/ViewModels/PlaygroundPageViewModel.cs
  44. 4
      samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.Designer.cs
  45. 23
      samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.cs
  46. 33
      samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml
  47. 52
      samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs
  48. 9
      samples/interop/WindowsInteropTest/Program.cs
  49. 76
      samples/interop/WindowsInteropTest/SelectorForm.Designer.cs
  50. 30
      samples/interop/WindowsInteropTest/SelectorForm.cs
  51. 120
      samples/interop/WindowsInteropTest/SelectorForm.resx
  52. 6
      samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
  53. 7
      src/Android/Avalonia.Android/AndroidPlatform.cs
  54. 4
      src/Android/Avalonia.Android/AvaloniaView.cs
  55. 112
      src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs
  56. 2
      src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
  57. 173
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  58. 8
      src/Avalonia.Base/Animation/Animatable.cs
  59. 27
      src/Avalonia.Base/Animation/Animation.cs
  60. 9
      src/Avalonia.Base/Animation/AnimatorDrivenTransition.cs
  61. 4
      src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
  62. 6
      src/Avalonia.Base/Animation/AnimatorTransitionObservable.cs
  63. 2
      src/Avalonia.Base/Animation/Animators/Animator`1.cs
  64. 2
      src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs
  65. 2
      src/Avalonia.Base/Animation/Animators/BoolAnimator.cs
  66. 2
      src/Avalonia.Base/Animation/Animators/BoxShadowAnimator.cs
  67. 2
      src/Avalonia.Base/Animation/Animators/BoxShadowsAnimator.cs
  68. 2
      src/Avalonia.Base/Animation/Animators/ByteAnimator.cs
  69. 2
      src/Avalonia.Base/Animation/Animators/ColorAnimator.cs
  70. 2
      src/Avalonia.Base/Animation/Animators/CornerRadiusAnimator.cs
  71. 2
      src/Avalonia.Base/Animation/Animators/DecimalAnimator.cs
  72. 2
      src/Avalonia.Base/Animation/Animators/DoubleAnimator.cs
  73. 2
      src/Avalonia.Base/Animation/Animators/FloatAnimator.cs
  74. 2
      src/Avalonia.Base/Animation/Animators/GradientBrushAnimator.cs
  75. 2
      src/Avalonia.Base/Animation/Animators/Int16Animator.cs
  76. 2
      src/Avalonia.Base/Animation/Animators/Int32Animator.cs
  77. 2
      src/Avalonia.Base/Animation/Animators/Int64Animator.cs
  78. 2
      src/Avalonia.Base/Animation/Animators/PointAnimator.cs
  79. 2
      src/Avalonia.Base/Animation/Animators/RectAnimator.cs
  80. 2
      src/Avalonia.Base/Animation/Animators/RelativePointAnimator.cs
  81. 2
      src/Avalonia.Base/Animation/Animators/SizeAnimator.cs
  82. 2
      src/Avalonia.Base/Animation/Animators/SolidColorBrushAnimator.cs
  83. 2
      src/Avalonia.Base/Animation/Animators/ThicknessAnimator.cs
  84. 2
      src/Avalonia.Base/Animation/Animators/TransformAnimator.cs
  85. 2
      src/Avalonia.Base/Animation/Animators/TransformOperationsAnimator.cs
  86. 2
      src/Avalonia.Base/Animation/Animators/UInt16Animator.cs
  87. 2
      src/Avalonia.Base/Animation/Animators/UInt32Animator.cs
  88. 2
      src/Avalonia.Base/Animation/Animators/UInt64Animator.cs
  89. 2
      src/Avalonia.Base/Animation/Animators/VectorAnimator.cs
  90. 5
      src/Avalonia.Base/Animation/Clock.cs
  91. 2
      src/Avalonia.Base/Animation/ClockBase.cs
  92. 3
      src/Avalonia.Base/Animation/Easings/IEasing.cs
  93. 5
      src/Avalonia.Base/Animation/Easings/SpringEasing.cs
  94. 4
      src/Avalonia.Base/Animation/IAnimation.cs
  95. 2
      src/Avalonia.Base/Animation/IAnimationSetter.cs
  96. 3
      src/Avalonia.Base/Animation/IAnimator.cs
  97. 3
      src/Avalonia.Base/Animation/IClock.cs
  98. 30
      src/Avalonia.Base/Animation/ICustomAnimator.cs
  99. 3
      src/Avalonia.Base/Animation/IGlobalClock.cs
  100. 4
      src/Avalonia.Base/Animation/ITransition.cs

5
.ncrunch/AppWithoutLifetime.v3.ncrunchproject

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

5
.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject

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

5
.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject

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

11
Avalonia.Desktop.slnf

@ -39,14 +39,13 @@
"src\\Markup\\Avalonia.Markup.Xaml\\Avalonia.Markup.Xaml.csproj",
"src\\Markup\\Avalonia.Markup\\Avalonia.Markup.csproj",
"src\\Skia\\Avalonia.Skia\\Avalonia.Skia.csproj",
"src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj",
"src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj",
"src\\tools\\DevAnalyzers\\DevAnalyzers.csproj",
"src\\tools\\DevGenerators\\DevGenerators.csproj",
"src\\tools\\PublicAnalyzers\\Avalonia.Analyzers.csproj",
"src\\Windows\\Avalonia.Direct2D1\\Avalonia.Direct2D1.csproj",
"src\\Windows\\Avalonia.Win32.Interop\\Avalonia.Win32.Interop.csproj",
"src\\Windows\\Avalonia.Win32\\Avalonia.Win32.csproj",
"src\\tools\\Avalonia.Analyzers\\Avalonia.Analyzers.csproj",
"src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj",
"src\\tools\\DevAnalyzers\\DevAnalyzers.csproj",
"src\\tools\\DevGenerators\\DevGenerators.csproj",
"tests\\Avalonia.Base.UnitTests\\Avalonia.Base.UnitTests.csproj",
"tests\\Avalonia.Benchmarks\\Avalonia.Benchmarks.csproj",
"tests\\Avalonia.Controls.DataGrid.UnitTests\\Avalonia.Controls.DataGrid.UnitTests.csproj",
@ -66,4 +65,4 @@
"tests\\Avalonia.UnitTests\\Avalonia.UnitTests.csproj"
]
}
}
}

3
Avalonia.sln

@ -135,7 +135,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.LinuxFramebuffer", "src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj", "{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.Interop", "src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.Interoperability", "src\Windows\Avalonia.Win32.Interoperability\Avalonia.Win32.Interoperability.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.RenderTests", "tests\Avalonia.Skia.RenderTests\Avalonia.Skia.RenderTests.csproj", "{E1582370-37B3-403C-917F-8209551B1634}"
EndProject
@ -251,6 +251,7 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Generators.Sandbox", "samples\Generators.Sandbox\Generators.Sandbox.csproj", "{A82AD1BC-EBE6-4FC3-A13B-D52A50297533}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppWithoutLifetime", "samples\AppWithoutLifetime\AppWithoutLifetime.csproj", "{F8928267-688E-4A51-989C-612A72446D33}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo", "samples\SafeAreaDemo\SafeAreaDemo.csproj", "{6B60A970-D5D2-49C2-8BAB-F9C7973B74B6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo.Android", "samples\SafeAreaDemo.Android\SafeAreaDemo.Android.csproj", "{22E3BC08-EAF7-4889-BDC4-B4D3046C4E2D}"

2
build/SharedVersion.props

@ -4,7 +4,7 @@
<Product>Avalonia</Product>
<Version>11.0.999</Version>
<Authors>Avalonia Team</Authors>
<Copyright>Copyright 2022 &#169; The AvaloniaUI Project</Copyright>
<Copyright>Copyright 2013-$([System.DateTime]::Now.ToString(`yyyy`)) &#169; The AvaloniaUI Project</Copyright>
<PackageProjectUrl>https://avaloniaui.net</PackageProjectUrl>
<RepositoryUrl>https://github.com/AvaloniaUI/Avalonia/</RepositoryUrl>
<GenerateDocumentationFile>true</GenerateDocumentationFile>

6
dirs.proj

@ -14,11 +14,11 @@
<ProjectReference Remove="samples/*.Android/*.csproj" />
<ProjectReference Remove="samples/*.Browser/*.csproj" />
<ProjectReference Remove="samples/*.Blazor/*.csproj" />
<ProjectReference Remove="samples/ControlCatalog.Desktop/*.*proj" />
</ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsOsPlatform('Windows')) OR '$(MSBuildRuntimeType)' != 'Full'">
<ProjectReference Remove="src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj" />
<ItemGroup Condition="!$([MSBuild]::IsOsPlatform('Windows'))">
<ProjectReference Remove="src/Windows/Avalonia.Win32.Interoperability/Avalonia.Win32.Interoperability.csproj" />
<ProjectReference Remove="samples/interop/**/*.*proj" />
<ProjectReference Remove="samples/ControlCatalog.Desktop/*.*proj" />
</ItemGroup>
<!-- Build android and iOS projects only on Windows, where we have installed android workload -->

2
nukebuild/Build.cs

@ -312,7 +312,7 @@ partial class Build : NukeBuild
public static int Main() =>
RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? Execute<Build>(x => x.RunToolsTests)
? Execute<Build>(x => x.Package)
: Execute<Build>(x => x.RunTests);
}

101
nukebuild/RefAssemblyGenerator.cs

@ -63,52 +63,89 @@ public class RefAssemblyGenerator
});
}
static bool HasPrivateApi(IEnumerable<CustomAttribute> attrs) => attrs.Any(a =>
a.AttributeType.FullName == "Avalonia.Metadata.PrivateApiAttribute");
static void ProcessType(TypeDefinition type, MethodReference obsoleteCtor)
{
foreach (var nested in type.NestedTypes)
ProcessType(nested, obsoleteCtor);
if (type.IsInterface)
var hideMembers = (type.IsInterface && type.Name.EndsWith("Impl"))
|| HasPrivateApi(type.CustomAttributes);
var injectMethod = hideMembers
|| type.CustomAttributes.Any(a =>
a.AttributeType.FullName == "Avalonia.Metadata.NotClientImplementableAttribute");
if (injectMethod)
{
var hideMethods = type.Name.EndsWith("Impl")
|| (type.HasCustomAttributes && type.CustomAttributes.Any(a =>
a.AttributeType.FullName == "Avalonia.Metadata.PrivateApiAttribute"));
type.Methods.Add(new MethodDefinition(
"(This interface or abstract class is -not- implementable by user code !)",
MethodAttributes.Assembly
| MethodAttributes.Abstract
| MethodAttributes.NewSlot
| MethodAttributes.HideBySig, type.Module.TypeSystem.Void));
}
var injectMethod = hideMethods
|| type.CustomAttributes.Any(a =>
a.AttributeType.FullName == "Avalonia.Metadata.NotClientImplementableAttribute");
if (hideMethods)
var forceUnstable = type.CustomAttributes.FirstOrDefault(a =>
a.AttributeType.FullName == "Avalonia.Metadata.UnstableAttribute");
foreach (var m in type.Methods)
{
if (hideMembers || HasPrivateApi(m.CustomAttributes))
{
foreach (var m in type.Methods)
{
var dflags = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.FamORAssem |
MethodAttributes.FamANDAssem | MethodAttributes.Assembly;
m.Attributes = ((m.Attributes | dflags) ^ dflags) | MethodAttributes.Assembly;
}
HideMethod(m);
}
if(injectMethod)
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
}
foreach (var p in type.Properties)
{
if (HasPrivateApi(p.CustomAttributes))
{
type.Methods.Add(new MethodDefinition("NotClientImplementable",
MethodAttributes.Assembly
| MethodAttributes.Abstract
| MethodAttributes.NewSlot
| MethodAttributes.HideBySig, type.Module.TypeSystem.Void));
if (p.SetMethod != null)
HideMethod(p.SetMethod);
if (p.GetMethod != null)
HideMethod(p.GetMethod);
}
}
var forceUnstable = type.CustomAttributes.FirstOrDefault(a =>
a.AttributeType.FullName == "Avalonia.Metadata.UnstableAttribute");
foreach (var m in type.Methods)
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
foreach (var m in type.Properties)
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
foreach (var m in type.Events)
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
foreach (var f in type.Fields)
{
if (hideMembers || HasPrivateApi(f.CustomAttributes))
{
var dflags = FieldAttributes.Public | FieldAttributes.Family | FieldAttributes.FamORAssem |
FieldAttributes.FamANDAssem | FieldAttributes.Assembly;
f.Attributes = ((f.Attributes | dflags) ^ dflags) | FieldAttributes.Assembly;
}
}
foreach (var cl in type.NestedTypes)
{
ProcessType(cl, obsoleteCtor);
if (hideMembers)
{
var dflags = TypeAttributes.Public;
cl.Attributes = ((cl.Attributes | dflags) ^ dflags) | TypeAttributes.NotPublic;
}
}
foreach (var m in type.Properties)
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
foreach (var m in type.Events)
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
}
static void HideMethod(MethodDefinition m)
{
var dflags = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.FamORAssem |
MethodAttributes.FamANDAssem | MethodAttributes.Assembly;
m.Attributes = ((m.Attributes | dflags) ^ dflags) | MethodAttributes.Assembly;
}
static void MarkAsUnstable(IMemberDefinition def, MethodReference obsoleteCtor, ICustomAttribute unstableAttribute)
{
if (def.CustomAttributes.Any(a => a.AttributeType.FullName == "System.ObsoleteAttribute"))

6
nukebuild/_build.csproj

@ -35,6 +35,12 @@
<EmbeddedResource Include="../build/avalonia.snk"></EmbeddedResource>
<Compile Remove="il-repack\ILRepack\Application.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="..\dirs.proj">
<Link>dirs.proj</Link>
</Content>
</ItemGroup>

2
packages/Avalonia/Avalonia.csproj

@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia.BuildServices" Version="0.0.12" />
<PackageReference Include="Avalonia.BuildServices" Version="0.0.19" />
<ProjectReference Include="../../src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj" />
<ProjectReference Include="../../src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj">
<PrivateAssets>all</PrivateAssets>

1
packages/Avalonia/Avalonia.targets

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

26
packages/Avalonia/AvaloniaPrivateApis.targets

@ -0,0 +1,26 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="RemoveAvaloniaRefAssemblies" AfterTargets="ResolveTargetingPackAssets" Condition="'$(AvaloniaAccessUnstablePrivateApis.ToLowerInvariant())'=='true'">
<ItemGroup>
<ReferencesToRemove Include="@(Reference)" Condition="'%(Reference.NuGetPackageId)' == 'Avalonia'" />
</ItemGroup>
<ItemGroup>
<Reference Remove="@(ReferencesToRemove)" />
</ItemGroup>
</Target>
<Target Name="PreventPackingAvaloniaUnstableApis" BeforeTargets="Pack">
<Error Condition="'$(IsPackable.ToLowerInvariant())' == 'true' and '$(AvaloniaAccessUnstablePrivateApis.ToLowerInvariant())' == 'true' and '$(Avalonia_I_Want_To_Use_Private_Apis_In_Nuget_Package_And_Promise_To_Pin_The_Exact_Avalonia_Version_In_Package_Dependency)' != 'true'"
Text="It seems that you are using private APIs in a nuget package, please follow this guide https://github.com/AvaloniaUI/Avalonia/wiki/Using-private-apis-in-nuget-packages" />
</Target>
<Target Name="AddReferencePathsToRealAvaloniaAssemblies" BeforeTargets="CoreCompile" Condition="'$(AvaloniaAccessUnstablePrivateApis.ToLowerInvariant())'=='true'">
<PropertyGroup>
<AvaloniaUnstableApiFrameworkToUse>net6.0</AvaloniaUnstableApiFrameworkToUse>
<AvaloniaUnstableApiFrameworkToUse Condition="$(TargetFramework.StartsWith('net4')) == 'true' or $(TargetFramework.StartsWith('net5')) == 'true' or $(TargetFramework.StartsWith('netsta')) == 'true' or $(TargetFramework.StartsWith('netcore')) == 'true'">netstandard2.0</AvaloniaUnstableApiFrameworkToUse>
</PropertyGroup>
<ItemGroup>
<Reference Include="$(MSBuildThisFileDirectory)/../lib/$(AvaloniaUnstableApiFrameworkToUse)/*.dll"/>
<ReferencePath Include="$(MSBuildThisFileDirectory)/../lib/$(AvaloniaUnstableApiFrameworkToUse)/*.dll"/>
<ReferencePathWithRefAssemblies Include="$(MSBuildThisFileDirectory)/../lib/$(AvaloniaUnstableApiFrameworkToUse)/*.dll"/>
</ItemGroup>
<Warning Text="AvaloniaAccessUnstablePrivateApis is Enabled: This means you are using unstable internal APIs, and your code may be depending on APIs which may change or be removed in future versions of Avalonia. Set AvaloniaAccessUnstablePrivateApis to 'False' to disable this warning." />
</Target>
</Project>

7
samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj

@ -4,10 +4,17 @@
<OutputType>Exe</OutputType>
<TargetFramework>net461</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationManifest>../ControlCatalog.NetCore/app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\ControlCatalog.NetCore\NativeControls\Win\*.cs" Link="NativeControls\*" />
</ItemGroup>
<Import Project="..\..\build\SampleApp.props" />

11
samples/ControlCatalog.Desktop/Program.cs

@ -3,6 +3,8 @@ using System.Linq;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Platform;
using ControlCatalog.NetCore;
using ControlCatalog.Pages;
namespace ControlCatalog
{
@ -18,6 +20,15 @@ namespace ControlCatalog
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.LogToTrace()
.AfterSetup(builder =>
{
builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions()
{
StartupScreenIndex = 1,
});
EmbedSample.Implementation = new EmbedSampleWin();
})
.UsePlatformDetect();
private static void ConfigureAssetAssembly(AppBuilder builder)

1
samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj

@ -16,6 +16,7 @@
<ItemGroup>
<Compile Include="..\..\src\Avalonia.X11\NativeDialogs\Gtk.cs" Link="NativeControls\Gtk\Gtk.cs" />
<Compile Include="..\..\src\Avalonia.Base\Platform\Interop\Utf8Buffer.cs" Link="NativeControls\Utf8Buffer.cs" />
</ItemGroup>
<ItemGroup>

5
samples/ControlCatalog/MainView.xaml.cs

@ -83,9 +83,10 @@ namespace ControlCatalog
if (transparencyLevels.SelectedItem is WindowTransparencyLevel selected)
{
var topLevel = (TopLevel)this.GetVisualRoot()!;
topLevel.TransparencyLevelHint = selected;
topLevel.TransparencyLevelHint = new[] { selected };
if (selected != WindowTransparencyLevel.None)
if (topLevel.ActualTransparencyLevel != WindowTransparencyLevel.None &&
topLevel.ActualTransparencyLevel == selected)
{
var transparentBrush = new ImmutableSolidColorBrush(Colors.White, 0);
var semiTransparentBrush = new ImmutableSolidColorBrush(Colors.Gray, 0.2);

3
samples/ControlCatalog/Pages/ColorPickerPage.xaml

@ -103,7 +103,8 @@
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}" />-->
<ColorPreviewer Grid.Row="8"
IsAccentColorsVisible="False"
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}" />
HsvColor="{Binding HsvColor, ElementName=ColorSpectrum1}"
Margin="0,2,0,0" />
</Grid>
</Grid>
</UserControl>

4
samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs

@ -19,8 +19,8 @@ namespace ControlCatalog.Pages
customContextRequestedBorder.AddHandler(ContextRequestedEvent, CustomContextRequested, RoutingStrategies.Tunnel);
var cancellableContextBorder = this.Get<Border>("CancellableContextBorder");
cancellableContextBorder.ContextMenu!.ContextMenuClosing += ContextFlyoutPage_Closing;
cancellableContextBorder.ContextMenu!.ContextMenuOpening += ContextFlyoutPage_Opening;
cancellableContextBorder.ContextMenu!.Closing += ContextFlyoutPage_Closing;
cancellableContextBorder.ContextMenu!.Opening += ContextFlyoutPage_Opening;
}
private ContextPageViewModel? _model;

2
samples/ControlCatalog/Pages/DialogsPage.xaml.cs

@ -307,7 +307,7 @@ namespace ControlCatalog.Pages
Content:
";
resultText += await ReadTextFromFile(file, 10000);
resultText += await ReadTextFromFile(file, 500);
}
openedFileContent.Text = resultText;

5
samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs

@ -1,5 +1,4 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Avalonia.Controls;
@ -23,7 +22,7 @@ namespace ControlCatalog.Pages
$"Text was dragged {++textCount} times"), DragDropEffects.Copy | DragDropEffects.Move | DragDropEffects.Link);
SetupDnd("Custom", d => d.Set(CustomFormat, "Test123"), DragDropEffects.Move);
SetupDnd("Files", d => d.Set(DataFormats.Files, new[] { Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName }), DragDropEffects.Copy);
SetupDnd("Files", async d => d.Set(DataFormats.Files, new[] { await (VisualRoot as TopLevel)!.StorageProvider.TryGetFileFromPathAsync(Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName) }), DragDropEffects.Copy);
}
void SetupDnd(string suffix, Action<DataObject> factory, DragDropEffects effects)
@ -99,7 +98,7 @@ namespace ControlCatalog.Pages
{
if (item is IStorageFile file)
{
var content = await DialogsPage.ReadTextFromFile(file, 1000);
var content = await DialogsPage.ReadTextFromFile(file, 500);
contentStr += $"File {item.Name}:{Environment.NewLine}{content}{Environment.NewLine}{Environment.NewLine}";
}
else if (item is IStorageFolder folder)

3
samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs

@ -117,9 +117,8 @@ namespace ControlCatalog.Pages
private void ScrollTo(int index)
{
System.Diagnostics.Debug.WriteLine("Scroll to " + index);
var layoutManager = ((TopLevel)VisualRoot!).LayoutManager;
var element = _repeater.GetOrCreateElement(index);
layoutManager.ExecuteLayoutPass();
((TopLevel)VisualRoot!).UpdateLayout();
element.BringIntoView();
}

29
samples/ControlCatalog/Pages/TabControlPage.xaml

@ -4,7 +4,27 @@
xmlns="https://github.com/avaloniaui"
xmlns:viewModels="using:ControlCatalog.ViewModels"
x:DataType="viewModels:TabControlPageViewModel">
<DockPanel>
<DockPanel Classes.WithContentTemplates="{Binding IsChecked, ElementName=UseContentTemplates}">
<DockPanel.Styles>
<Style Selector="DockPanel.WithContentTemplates">
<Style Selector="^ TabItem">
<Setter Property="ContentTemplate">
<DataTemplate x:CompileBindings="False">
<Border BorderBrush="Red" BorderThickness="10">
<ContentPresenter Content="{Binding}"/>
</Border>
</DataTemplate>
</Setter>
</Style>
<Style Selector="^ TabControl">
<Setter Property="ContentTemplate">
<DataTemplate>
<TextBlock Text="This template should be overriden by each TabItem's template."/>
</DataTemplate>
</Setter>
</Style>
</Style>
</DockPanel.Styles>
<TextBlock
DockPanel.Dock="Top"
Classes="h2"
@ -55,14 +75,14 @@
Margin="0 16"
DisplayMemberBinding="{Binding Header, x:DataType=viewModels:TabControlPageViewModelItem}"
TabStripPlacement="{Binding TabPlacement}">
<TabControl.ContentTemplate>
<TabControl.DataTemplates>
<DataTemplate x:DataType="viewModels:TabControlPageViewModelItem">
<StackPanel Orientation="Vertical" Spacing="8">
<TextBlock Text="{Binding Text}"/>
<Image Source="{Binding Image}" Width="300"/>
</StackPanel>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl.DataTemplates>
<TabControl.Styles>
<Style Selector="TabItem" x:DataType="viewModels:TabControlPageViewModelItem">
<Setter Property="IsEnabled" Value="{Binding IsEnabled}"/>
@ -78,12 +98,13 @@
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock VerticalAlignment="Center">Tab Placement:</TextBlock>
<ComboBox SelectedIndex="{Binding TabPlacement, Mode=TwoWay}">
<ComboBox SelectedIndex="{Binding TabPlacement, Mode=TwoWay}" Width="100">
<ComboBoxItem>Left</ComboBoxItem>
<ComboBoxItem>Bottom</ComboBoxItem>
<ComboBoxItem>Right</ComboBoxItem>
<ComboBoxItem>Top</ComboBoxItem>
</ComboBox>
<CheckBox Name="UseContentTemplates">Set TabItem.ContentTemplate</CheckBox>
</StackPanel>
</Grid>
</DockPanel>

2
samples/ControlCatalog/Pages/TabControlPage.xaml.cs

@ -49,7 +49,7 @@ namespace ControlCatalog.Pages
AvaloniaXamlLoader.Load(this);
}
private static IBitmap LoadBitmap(string uri)
private static Bitmap LoadBitmap(string uri)
{
var assets = AvaloniaLocator.Current.GetRequiredService<IAssetLoader>();
return new Bitmap(assets.Open(new Uri(uri)));

2
samples/ControlCatalog/ViewModels/TabControlPageViewModel.cs

@ -21,6 +21,6 @@ public class TabControlPageViewModelItem
{
public string? Header { get; set; }
public string? Text { get; set; }
public IBitmap? Image { get; set; }
public Bitmap? Image { get; set; }
public bool IsEnabled { get; set; } = true;
}

2
samples/GpuInterop/MainWindow.axaml.cs

@ -11,7 +11,7 @@ namespace GpuInterop
{
InitializeComponent();
this.AttachDevTools();
Renderer.Diagnostics.DebugOverlays = RendererDebugOverlays.Fps;
RendererDiagnostics.DebugOverlays = RendererDebugOverlays.Fps;
}
private void InitializeComponent()

2
samples/GpuInterop/VulkanDemo/VulkanContext.cs

@ -174,7 +174,7 @@ public unsafe class VulkanContext : IDisposable
for (uint queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; queueFamilyIndex++)
{
var family = familyProperties[queueFamilyIndex];
if (!family.QueueFlags.HasAllFlags(QueueFlags.GraphicsBit))
if (!family.QueueFlags.HasFlag(QueueFlags.GraphicsBit))
continue;

3
samples/IntegrationTestApp/MainWindow.axaml

@ -47,6 +47,9 @@
<Button Name="DisabledButton" IsEnabled="False">
Disabled Button
</Button>
<Button Name="EffectivelyDisabledButton" Command="{ReflectionBinding DoesntExist}">
Effectively Disabled Button
</Button>
<Button Name="BasicButton">
Basic Button
</Button>

2
samples/IntegrationTestApp/MainWindow.axaml.cs

@ -136,7 +136,7 @@ namespace IntegrationTestApp
Name = "TransparentWindow",
SystemDecorations = SystemDecorations.None,
Background = Brushes.Transparent,
TransparencyLevelHint = WindowTransparencyLevel.Transparent,
TransparencyLevelHint = new[] { WindowTransparencyLevel.Transparent },
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Width = 200,
Height = 200,

21
samples/MobileSandbox.Desktop/MobileSandbox.Desktop.csproj

@ -4,37 +4,16 @@
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(RunNativeAotCompilation)' == 'true'">
<IlcTrimMetadata>true</IlcTrimMetadata>
<RestoreAdditionalProjectSources>https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json</RestoreAdditionalProjectSources>
<NativeAotCompilerVersion>7.0.0-*</NativeAotCompilerVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\src\Avalonia.X11\NativeDialogs\Gtk.cs" Link="NativeControls\Gtk\Gtk.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Headless\Avalonia.Headless.Vnc\Avalonia.Headless.Vnc.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Dialogs\Avalonia.Dialogs.csproj" />
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
<ProjectReference Include="..\MobileSandbox\MobileSandbox.csproj" />
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" />
<!-- For native controls test -->
<PackageReference Include="MonoMac.NetStandard" Version="0.0.4" />
</ItemGroup>
<ItemGroup Condition="'$(RunNativeAotCompilation)' == 'true'">
<PackageReference Include="Microsoft.DotNet.ILCompiler" Version="$(NativeAotCompilerVersion)" />
<!-- Cross-compilation for Windows x64-arm64 and Linux x64-arm64 -->
<PackageReference Condition="'$(RuntimeIdentifier)'=='win-arm64'" Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="$(NativeAotCompilerVersion)" />
<PackageReference Condition="'$(RuntimeIdentifier)'=='linux-arm64'" Include="runtime.linux-x64.Microsoft.DotNet.ILCompiler" Version="$(NativeAotCompilerVersion)" />
</ItemGroup>
<PropertyGroup>
<!-- For Microsoft.CodeAnalysis -->
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>

15
samples/MobileSandbox/MobileSandbox.csproj

@ -14,9 +14,6 @@
<AvaloniaResource Include="Assets\*" />
<AvaloniaResource Include="Assets\Fonts\*" />
</ItemGroup>
<ItemGroup>
<None Remove="Pages\NativeEmbedPage.xaml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Assets\Fonts\SourceSansPro-Bold.ttf" />
<EmbeddedResource Include="Assets\Fonts\SourceSansPro-BoldItalic.ttf" />
@ -34,17 +31,5 @@
<ProjectReference Include="..\SampleControls\ControlSamples.csproj" />
</ItemGroup>
<ItemGroup>
<AvaloniaResource Update="Pages\NativeEmbedPage.xaml">
<Generator>MSBuild:Compile</Generator>
</AvaloniaResource>
</ItemGroup>
<ItemGroup>
<Compile Update="Pages\NativeEmbedPage.xaml.cs">
<DependentUpon>%(Filename)</DependentUpon>
</Compile>
</ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" />
</Project>

2
samples/RenderDemo/MainWindow.xaml.cs

@ -21,7 +21,7 @@ namespace RenderDemo
void BindOverlay(Expression<Func<MainWindowViewModel, bool>> expr, RendererDebugOverlays overlay)
=> vm.WhenAnyValue(expr).Subscribe(x =>
{
var diagnostics = Renderer.Diagnostics;
var diagnostics = RendererDiagnostics;
diagnostics.DebugOverlays = x ?
diagnostics.DebugOverlays | overlay :
diagnostics.DebugOverlays & ~overlay;

4
samples/RenderDemo/Pages/AnimationsPage.xaml

@ -347,12 +347,8 @@
</UserControl.Styles>
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" ClipToBounds="False">
<StackPanel.Clock>
<Clock />
</StackPanel.Clock>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Spacing="20">
<TextBlock VerticalAlignment="Center">Hover to activate Keyframe Animations.</TextBlock>
<Button Content="{Binding PlayStateText}" Command="{Binding TogglePlayState}" Click="ToggleClock" />
</StackPanel>
<WrapPanel ClipToBounds="False">
<Border Classes="Test Rect1" Background="DarkRed"/>

15
samples/RenderDemo/Pages/AnimationsPage.xaml.cs

@ -24,20 +24,5 @@ namespace RenderDemo.Pages
{
AvaloniaXamlLoader.Load(this);
}
private void ToggleClock(object sender, RoutedEventArgs args)
{
var button = sender as Button;
var clock = button.Clock;
if (clock.PlayState == PlayState.Run)
{
clock.PlayState = PlayState.Pause;
}
else if (clock.PlayState == PlayState.Pause)
{
clock.PlayState = PlayState.Run;
}
}
}
}

12
samples/RenderDemo/Pages/CustomAnimatorPage.xaml

@ -11,10 +11,18 @@
<Style.Animations>
<Animation Duration="0:0:1" IterationCount="Infinite">
<KeyFrame Cue="0%">
<Setter Property="Text" Value="" Animation.Animator="{x:Type pages:CustomStringAnimator}"/>
<Setter Property="Text" Value="">
<Animation.Animator>
<pages:CustomStringAnimator/>
</Animation.Animator>
</Setter>
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="Text" Value="0123456789" Animation.Animator="{x:Type pages:CustomStringAnimator}"/>
<Setter Property="Text" Value="0123456789" >
<Animation.Animator>
<pages:CustomStringAnimator/>
</Animation.Animator>
</Setter>
</KeyFrame>
</Animation>
</Style.Animations>

6
samples/RenderDemo/Pages/CustomSkiaPage.cs

@ -27,11 +27,11 @@ namespace RenderDemo.Pages
class CustomDrawOp : ICustomDrawOperation
{
private readonly GlyphRun _noSkia;
private readonly IImmutableGlyphRunReference _noSkia;
public CustomDrawOp(Rect bounds, GlyphRun noSkia)
{
_noSkia = noSkia;
_noSkia = noSkia.TryCreateImmutableGlyphRunReference();
Bounds = bounds;
}
@ -48,7 +48,7 @@ namespace RenderDemo.Pages
{
var leaseFeature = context.TryGetFeature<ISkiaSharpApiLeaseFeature>();
if (leaseFeature == null)
context.DrawGlyphRun(Brushes.Black, _noSkia.PlatformImpl);
context.DrawGlyphRun(Brushes.Black, _noSkia);
else
{
using var lease = leaseFeature.Lease();

5
samples/RenderDemo/Pages/CustomStringAnimator.cs

@ -1,8 +1,9 @@
using Avalonia.Animation.Animators;
using Avalonia.Animation;
using Avalonia.Animation.Animators;
namespace RenderDemo.Pages
{
public class CustomStringAnimator : Animator<string>
public class CustomStringAnimator : CustomAnimatorBase<string>
{
public override string Interpolate(double progress, string oldValue, string newValue)
{

8
samples/RenderDemo/Pages/PathMeasurementPage.cs

@ -53,15 +53,15 @@ namespace RenderDemo.Pages
bitmapCtx.DrawGeometry(null, strokePen, basePath);
var length = basePath.PlatformImpl.ContourLength;
var length = basePath.ContourLength;
if (basePath.PlatformImpl.TryGetSegment(length * 0.05, length * 0.2, true, out var dst1))
if (basePath.TryGetSegment(length * 0.05, length * 0.2, true, out var dst1))
bitmapCtx.DrawGeometry(null, strokePen1, dst1);
if (basePath.PlatformImpl.TryGetSegment(length * 0.2, length * 0.8, true, out var dst2))
if (basePath.TryGetSegment(length * 0.2, length * 0.8, true, out var dst2))
bitmapCtx.DrawGeometry(null, strokePen2, dst2);
if (basePath.PlatformImpl.TryGetSegment(length * 0.8, length * 0.95, true, out var dst3))
if (basePath.TryGetSegment(length * 0.8, length * 0.95, true, out var dst3))
bitmapCtx.DrawGeometry(null, strokePen3, dst3);
var pathBounds = basePath.GetRenderBounds(strokePen);

3
samples/RenderDemo/Pages/Transform3DPage.axaml

@ -134,9 +134,6 @@
</UserControl.Styles>
<Grid ColumnDefinitions="Auto,*,Auto,*" RowDefinitions="*, Auto, Auto, Auto, Auto, Auto, Auto, Auto">
<Grid.Clock>
<Clock />
</Grid.Clock>
<Border Name="B1" Background="DarkRed" Classes="Test">
<Border.RenderTransform>
<Rotate3DTransform CenterZ="-100"

4
samples/RenderDemo/Pages/TransitionsPage.xaml

@ -248,12 +248,8 @@
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" ClipToBounds="False">
<StackPanel.Clock>
<Clock />
</StackPanel.Clock>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Spacing="20">
<TextBlock VerticalAlignment="Center">Hover to activate Transitions.</TextBlock>
<Button Content="{Binding PlayStateText}" Command="{Binding TogglePlayState}" Click="ToggleClock" />
</StackPanel>
<WrapPanel ClipToBounds="False">
<Border Classes="Test Rect1" Background="DarkRed"/>

15
samples/RenderDemo/Pages/TransitionsPage.xaml.cs

@ -18,20 +18,5 @@ namespace RenderDemo.Pages
{
AvaloniaXamlLoader.Load(this);
}
private void ToggleClock(object sender, RoutedEventArgs args)
{
var button = sender as Button;
var clock = button.Clock;
if (clock.PlayState == PlayState.Run)
{
clock.PlayState = PlayState.Pause;
}
else if (clock.PlayState == PlayState.Pause)
{
clock.PlayState = PlayState.Run;
}
}
}
}

1
samples/Sandbox/Sandbox.csproj

@ -5,6 +5,7 @@
<TargetFramework>net6.0</TargetFramework>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<IncludeAvaloniaGenerators>true</IncludeAvaloniaGenerators>
<!-- <AvaloniaXamlIlDebuggerLaunch>true</AvaloniaXamlIlDebuggerLaunch>-->
</PropertyGroup>
<ItemGroup>

6
samples/VirtualizationDemo/ViewModels/PlaygroundPageViewModel.cs

@ -24,19 +24,19 @@ public class PlaygroundPageViewModel : ViewModelBase
public bool Multiple
{
get => _selectionMode.HasAnyFlag(SelectionMode.Multiple);
get => _selectionMode.HasFlag(SelectionMode.Multiple);
set => SetSelectionMode(SelectionMode.Multiple, value);
}
public bool Toggle
{
get => _selectionMode.HasAnyFlag(SelectionMode.Toggle);
get => _selectionMode.HasFlag(SelectionMode.Toggle);
set => SetSelectionMode(SelectionMode.Toggle, value);
}
public bool AlwaysSelected
{
get => _selectionMode.HasAnyFlag(SelectionMode.AlwaysSelected);
get => _selectionMode.HasFlag(SelectionMode.AlwaysSelected);
set => SetSelectionMode(SelectionMode.AlwaysSelected, value);
}

4
samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.Designer.cs

@ -1,4 +1,4 @@
using Avalonia.Win32.Embedding;
using Avalonia.Win32.Interoperability;
namespace WindowsInteropTest
{
@ -116,4 +116,4 @@ namespace WindowsInteropTest
private System.Windows.Forms.GroupBox groupBox2;
private WinFormsAvaloniaControlHost avaloniaHost;
}
}
}

23
samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.cs

@ -1,35 +1,14 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Avalonia.Controls;
using Avalonia.Rendering;
using Avalonia.VisualTree;
using System.Windows.Forms;
using ControlCatalog;
namespace WindowsInteropTest
{
public partial class EmbedToWinFormsDemo : Form
{
private readonly IRenderer _renderer;
public EmbedToWinFormsDemo()
{
InitializeComponent();
avaloniaHost.Content = new MainView();
_renderer = ((TopLevel)avaloniaHost.Content.GetVisualRoot()).Renderer;
_renderer.Start();
}
protected override void OnClosed(EventArgs e)
{
_renderer.Stop();
base.OnClosed(e);
}
}
}

33
samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml

@ -1,33 +0,0 @@
<Window x:Class="WindowsInteropTest.EmbedToWpfDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:av="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WindowsInteropTest"
xmlns:embedding="clr-namespace:Avalonia.Win32.Embedding;assembly=Avalonia.Win32"
xmlns:wpf="clr-namespace:Avalonia.Win32.Interop.Wpf;assembly=Avalonia.Win32.Interop"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="400" MinWidth="500" MinHeight="400">
<DockPanel>
<GroupBox DockPanel.Dock="Left" Header="WPF">
<StackPanel>
<Slider/>
<Calendar/>
</StackPanel>
</GroupBox>
<GroupBox Header="Avalonia button" DockPanel.Dock="Bottom">
<wpf:WpfAvaloniaHost >
<av:Button Content="Avalonia button"/>
</wpf:WpfAvaloniaHost>
</GroupBox>
<GroupBox Header="AvBtn" DockPanel.Dock="Right">
<wpf:WpfAvaloniaHost x:Name="RightBtn">
<av:Button Content="Avalonia button 2"/>
</wpf:WpfAvaloniaHost>
</GroupBox>
<GroupBox Header="Avalonia">
<wpf:WpfAvaloniaHost x:Name="Host"/>
</GroupBox>
</DockPanel>
</Window>

52
samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs

@ -1,52 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Rendering;
using Avalonia.VisualTree;
using ControlCatalog;
using Window = System.Windows.Window;
namespace WindowsInteropTest
{
/// <summary>
/// Interaction logic for EmbedToWpfDemo.xaml
/// </summary>
public partial class EmbedToWpfDemo : Window
{
private IRenderer _renderer;
public EmbedToWpfDemo()
{
InitializeComponent();
var view = new MainView();
Host.Content = view;
var tl = (TopLevel)view.GetVisualRoot();
tl.AttachDevTools();
_renderer = tl.Renderer;
_renderer.Start();
var btn = (Avalonia.Controls.Button) RightBtn.Content;
btn.Click += delegate
{
btn.Content += "!";
};
}
protected override void OnClosed(EventArgs e)
{
_renderer.Stop();
base.OnClosed(e);
}
}
}

9
samples/interop/WindowsInteropTest/Program.cs

@ -16,14 +16,9 @@ namespace WindowsInteropTest
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
AppBuilder.Configure<App>()
.UseWin32()
.UseDirect2D1()
.With(new Win32PlatformOptions
{
UseWindowsUIComposition = false,
ShouldRenderOnUIThread = true // necessary for WPF
})
.UseSkia()
.SetupWithoutStarting();
System.Windows.Forms.Application.Run(new SelectorForm());
System.Windows.Forms.Application.Run(new EmbedToWinFormsDemo());
}
}
}

76
samples/interop/WindowsInteropTest/SelectorForm.Designer.cs

@ -1,76 +0,0 @@
namespace WindowsInteropTest
{
partial class SelectorForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnEmbedToWinForms = new System.Windows.Forms.Button();
this.btnEmbedToWpf = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnEmbedToWinForms
//
this.btnEmbedToWinForms.Location = new System.Drawing.Point(12, 12);
this.btnEmbedToWinForms.Name = "btnEmbedToWinForms";
this.btnEmbedToWinForms.Size = new System.Drawing.Size(201, 86);
this.btnEmbedToWinForms.TabIndex = 0;
this.btnEmbedToWinForms.Text = "Embed to WinForms";
this.btnEmbedToWinForms.UseVisualStyleBackColor = true;
this.btnEmbedToWinForms.Click += new System.EventHandler(this.btnEmbedToWinForms_Click);
//
// btnEmbedToWpf
//
this.btnEmbedToWpf.Location = new System.Drawing.Point(219, 12);
this.btnEmbedToWpf.Name = "btnEmbedToWpf";
this.btnEmbedToWpf.Size = new System.Drawing.Size(201, 86);
this.btnEmbedToWpf.TabIndex = 1;
this.btnEmbedToWpf.Text = "Embed to WPF";
this.btnEmbedToWpf.UseVisualStyleBackColor = true;
this.btnEmbedToWpf.Click += new System.EventHandler(this.btnEmbedToWpf_Click);
//
// SelectorForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(432, 284);
this.Controls.Add(this.btnEmbedToWpf);
this.Controls.Add(this.btnEmbedToWinForms);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.Name = "SelectorForm";
this.Text = "Interop";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnEmbedToWinForms;
private System.Windows.Forms.Button btnEmbedToWpf;
}
}

30
samples/interop/WindowsInteropTest/SelectorForm.cs

@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsInteropTest
{
public partial class SelectorForm : Form
{
public SelectorForm()
{
InitializeComponent();
}
private void btnEmbedToWinForms_Click(object sender, EventArgs e)
{
new EmbedToWinFormsDemo().ShowDialog(this);
}
private void btnEmbedToWpf_Click(object sender, EventArgs e)
{
new EmbedToWpfDemo().ShowDialog();
}
}
}

120
samples/interop/WindowsInteropTest/SelectorForm.resx

@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

6
samples/interop/WindowsInteropTest/WindowsInteropTest.csproj

@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net461</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<TargetFrameworks>net461;net6.0-windows</TargetFrameworks>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj" />
<ProjectReference Include="..\..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Win32.Interoperability\Avalonia.Win32.Interoperability.csproj" />
<ProjectReference Include="..\..\ControlCatalog\ControlCatalog.csproj" />
</ItemGroup>
</Project>

7
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -45,7 +45,6 @@ namespace Avalonia.Android
.Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface())
.Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoaderStub>()
.Bind<IRenderTimer>().ToConstant(new ChoreographerTimer())
.Bind<IRenderLoop>().ToConstant(new RenderLoop())
.Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>();
if (Options.UseGpu)
@ -53,11 +52,7 @@ namespace Avalonia.Android
EglPlatformGraphics.TryInitialize();
}
Compositor = new Compositor(
AvaloniaLocator.Current.GetRequiredService<IRenderLoop>(),
AvaloniaLocator.Current.GetService<IPlatformGraphics>());
Compositor = new Compositor(AvaloniaLocator.Current.GetService<IPlatformGraphics>());
}
}

4
src/Android/Avalonia.Android/AvaloniaView.cs

@ -67,7 +67,7 @@ namespace Avalonia.Android
_timerSubscription = timer.SubscribeView(this);
}
_root.Renderer.Start();
_root.StartRendering();
if (_view.TryGetFeature<IInsetsManager>(out var insetsManager) == true)
{
@ -76,7 +76,7 @@ namespace Avalonia.Android
}
else
{
_root.Renderer.Stop();
_root.StopRendering();
_timerSubscription?.Dispose();
}
}

112
src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs

@ -5,8 +5,9 @@ using Avalonia.Input;
namespace Avalonia.Android.Platform.Input
{
internal class AndroidKeyboardDevice : KeyboardDevice, IKeyboardDevice {
private static readonly Dictionary<Keycode, Key> KeyDic = new Dictionary<Keycode, Key>
internal class AndroidKeyboardDevice : KeyboardDevice, IKeyboardDevice
{
private static readonly Dictionary<Keycode, Key> KeyDic = new Dictionary<Keycode, Key>
{
// { Keycode.Cancel?, Key.Cancel },
{ Keycode.Del, Key.Back },
@ -15,7 +16,7 @@ namespace Avalonia.Android.Platform.Input
{ Keycode.Clear, Key.Clear },
{ Keycode.Enter, Key.Return },
{ Keycode.MediaPause, Key.Pause },
//{ Keycode.?, Key.CapsLock }
{ Keycode.CapsLock, Key.CapsLock },
//{ Keycode.?, Key.HangulMode }
//{ Keycode.?, Key.JunjaMode }
//{ Keycode.?, Key.FinalMode }
@ -28,8 +29,8 @@ namespace Avalonia.Android.Platform.Input
{ Keycode.Space, Key.Space },
{ Keycode.PageUp, Key.Prior },
{ Keycode.PageDown, Key.PageDown },
// { Keycode.end?, Key.End },
{ Keycode.Home, Key.Home },
{ Keycode.MoveEnd, Key.End },
{ Keycode.MoveHome, Key.Home },
{ Keycode.DpadLeft, Key.Left },
{ Keycode.DpadUp, Key.Up },
{ Keycode.DpadRight, Key.Right },
@ -37,20 +38,20 @@ namespace Avalonia.Android.Platform.Input
// { Keycode.ButtonSelect?, Key.Select },
// { Keycode.print?, Key.Print },
//{ Keycode.execute?, Key.Execute },
// { Keycode.snap, Key.Snapshot }
//{ Keycode.snap?, Key.Snapshot }
{ Keycode.Insert, Key.Insert },
{ Keycode.ForwardDel, Key.Delete },
//{ Keycode.help, Key.Help },
//{ Keycode.?, Key.D0 }
//{ Keycode.?, Key.D1 }
//{ Keycode.?, Key.D2 }
//{ Keycode.?, Key.D3 }
//{ Keycode.?, Key.D4 }
//{ Keycode.?, Key.D5 }
//{ Keycode.?, Key.D6 }
//{ Keycode.?, Key.D7 }
//{ Keycode.?, Key.D8 }
//{ Keycode.?, Key.D9 }
{ Keycode.Help, Key.Help },
{ Keycode.Num0, Key.D0 },
{ Keycode.Num1, Key.D1 },
{ Keycode.Num2, Key.D2 },
{ Keycode.Num3, Key.D3 },
{ Keycode.Num4, Key.D4 },
{ Keycode.Num5, Key.D5 },
{ Keycode.Num6, Key.D6 },
{ Keycode.Num7, Key.D7 },
{ Keycode.Num8, Key.D8 },
{ Keycode.Num9, Key.D9 },
{ Keycode.A, Key.A },
{ Keycode.B, Key.B },
{ Keycode.C, Key.C },
@ -106,22 +107,22 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.?, Key.LWin }
//{ Keycode.?, Key.RWin }
//{ Keycode.?, Key.Apps }
//{ Keycode.?, Key.Sleep }
//{ Keycode.?, Key.NumPad0 }
//{ Keycode.?, Key.NumPad1 }
//{ Keycode.?, Key.NumPad2 }
//{ Keycode.?, Key.NumPad3 }
//{ Keycode.?, Key.NumPad4 }
//{ Keycode.?, Key.NumPad5 }
//{ Keycode.?, Key.NumPad6 }
//{ Keycode.?, Key.NumPad7 }
//{ Keycode.?, Key.NumPad8 }
//{ Keycode.?, Key.NumPad9 }
{ Keycode.Sleep, Key.Sleep },
{ Keycode.Numpad0, Key.NumPad0 },
{ Keycode.Numpad1, Key.NumPad1 },
{ Keycode.Numpad2, Key.NumPad2 },
{ Keycode.Numpad3, Key.NumPad3 },
{ Keycode.Numpad4, Key.NumPad4 },
{ Keycode.Numpad5, Key.NumPad5 },
{ Keycode.Numpad6, Key.NumPad6 },
{ Keycode.Numpad7, Key.NumPad7 },
{ Keycode.Numpad8, Key.NumPad8 },
{ Keycode.Numpad9, Key.NumPad9 },
{ Keycode.NumpadMultiply, Key.Multiply },
{ Keycode.NumpadAdd, Key.Add },
{ Keycode.NumpadComma, Key.Separator },
{ Keycode.NumpadSubtract, Key.Subtract },
//{ Keycode.numpaddecimal?, Key.Decimal }
{ Keycode.NumpadDot, Key.Decimal },
{ Keycode.NumpadDivide, Key.Divide },
{ Keycode.F1, Key.F1 },
{ Keycode.F2, Key.F2 },
@ -147,14 +148,14 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.R2, Key.F22 },
//{ Keycode.F23, Key.F23 },
//{ Keycode.R4, Key.F24 },
// { Keycode.numpad, Key.NumLock }
{ Keycode.NumLock, Key.NumLock },
{ Keycode.ScrollLock, Key.Scroll },
{ Keycode.ShiftLeft, Key.LeftShift },
//{ Keycode.?, Key.RightShift }
//{ Keycode.?, Key.LeftCtrl }
//{ Keycode.?, Key.RightCtrl }
//{ Keycode.?, Key.LeftAlt }
//{ Keycode.?, Key.RightAlt }
{ Keycode.ShiftRight, Key.RightShift },
{ Keycode.CtrlLeft, Key.LeftCtrl },
{ Keycode.CtrlRight, Key.RightCtrl },
{ Keycode.AltLeft, Key.LeftAlt },
{ Keycode.AltRight, Key.RightAlt },
//{ Keycode.?, Key.BrowserBack }
//{ Keycode.?, Key.BrowserForward }
//{ Keycode.?, Key.BrowserRefresh }
@ -163,28 +164,30 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.?, Key.BrowserFavorites }
//{ Keycode.?, Key.BrowserHome }
//{ Keycode.?, Key.VolumeMute }
//{ Keycode.?, Key.VolumeDown }
//{ Keycode.?, Key.VolumeUp }
//{ Keycode.?, Key.MediaNextTrack }
//{ Keycode.?, Key.MediaPreviousTrack }
//{ Keycode.?, Key.MediaStop }
//{ Keycode.?, Key.MediaPlayPause }
{ Keycode.VolumeDown, Key.VolumeDown },
{ Keycode.VolumeUp, Key.VolumeUp },
{ Keycode.MediaNext, Key.MediaNextTrack },
{ Keycode.MediaPrevious, Key.MediaPreviousTrack },
{ Keycode.MediaStop, Key.MediaStop },
{ Keycode.MediaPlayPause, Key.MediaPlayPause },
//{ Keycode.?, Key.LaunchMail }
//{ Keycode.?, Key.SelectMedia }
//{ Keycode.?, Key.LaunchApplication1 }
//{ Keycode.?, Key.LaunchApplication2 }
//{ Keycode.?, Key.OemSemicolon }
//{ Keycode.?, Key.OemPlus }
//{ Keycode.?, Key.OemComma }
//{ Keycode.?, Key.OemMinus }
//{ Keycode.?, Key.OemPeriod }
{ Keycode.Semicolon, Key.OemSemicolon },
{ Keycode.Plus, Key.OemPlus },
{ Keycode.Comma, Key.OemComma },
{ Keycode.Minus, Key.OemMinus },
{ Keycode.Period, Key.OemPeriod },
//{ Keycode.?, Key.Oem2 }
//{ Keycode.?, Key.OemTilde }
{ Keycode.Grave, Key.OemTilde },
//{ Keycode.?, Key.AbntC1 }
//{ Keycode.?, Key.AbntC2 }
//{ Keycode.?, Key.Oem4 }
//{ Keycode.?, Key.OemPipe }
//{ Keycode.?, Key.OemCloseBrackets }
{ Keycode.Apostrophe, Key.OemQuotes },
{ Keycode.Slash, Key.OemQuestion },
{ Keycode.LeftBracket, Key.OemOpenBrackets },
{ Keycode.RightBracket, Key.OemCloseBrackets },
//{ Keycode.?, Key.Oem7 }
//{ Keycode.?, Key.Oem8 }
//{ Keycode.?, Key.Oem102 }
@ -200,17 +203,18 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.?, Key.DbeEnterWordRegisterMode }
//{ Keycode.?, Key.DbeEnterImeConfigureMode }
//{ Keycode.?, Key.EraseEof }
//{ Keycode.?, Key.Play }
{ Keycode.MediaPlay, Key.Play },
//{ Keycode.?, Key.Zoom }
//{ Keycode.?, Key.NoName }
//{ Keycode.?, Key.DbeEnterDialogConversionMode }
//{ Keycode.?, Key.OemClear }
//{ Keycode.?, Key.DeadCharProcessed }
{ Keycode.Backslash, Key.OemBackslash }
};
internal static Key ConvertKey(Keycode key) {
Key result;
return KeyDic.TryGetValue(key, out result) ? result : Key.None;
internal static Key ConvertKey(Keycode key)
{
return KeyDic.TryGetValue(key, out var result) ? result : Key.None;
}
}
}
}

2
src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs

@ -10,7 +10,7 @@ using Avalonia.Platform;
namespace Avalonia.Android
{
internal abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformNativeSurfaceHandle
internal abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, INativePlatformHandleSurface
{
bool _invalidateQueued;
readonly object _lock = new object();

173
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.Versioning;
using Android.App;
using Android.Content;
using Android.Graphics;
@ -45,6 +46,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
private readonly AndroidInsetsManager _insetsManager;
private readonly ClipboardImpl _clipboard;
private ViewImpl _view;
private WindowTransparencyLevel _transparencyLevel;
public TopLevelImpl(AvaloniaView avaloniaView, bool placeOnTop = false)
{
@ -68,6 +70,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
_nativeControlHost = new AndroidNativeControlHostImpl(avaloniaView);
_storageProvider = new AndroidStorageProvider((Activity)avaloniaView.Context);
_transparencyLevel = WindowTransparencyLevel.None;
_systemNavigationManager = new AndroidSystemNavigationManagerImpl(avaloniaView.Context as IActivityNavigationService);
}
@ -103,9 +106,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public IEnumerable<object> Surfaces => new object[] { _gl, _framebuffer, Handle };
public IRenderer CreateRenderer(IRenderRoot root) =>
new CompositingRenderer(root, AndroidPlatform.Compositor, () => Surfaces);
public Compositor Compositor => AndroidPlatform.Compositor;
public virtual void Hide()
{
_view.Visibility = ViewStates.Invisible;
@ -274,7 +276,18 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public Action LostFocus { get; set; }
public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; }
public WindowTransparencyLevel TransparencyLevel { get; private set; }
public WindowTransparencyLevel TransparencyLevel
{
get => _transparencyLevel;
private set
{
if (_transparencyLevel != value)
{
_transparencyLevel = value;
TransparencyLevelChanged?.Invoke(value);
}
}
}
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant)
{
@ -299,91 +312,64 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public double Scaling => RenderScaling;
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel)
public void SetTransparencyLevelHint(IReadOnlyList<WindowTransparencyLevel> transparencyLevels)
{
if (TransparencyLevel != transparencyLevel)
if (_view.Context is not AvaloniaMainActivity activity)
return;
foreach (var level in transparencyLevels)
{
bool isBelowR = Build.VERSION.SdkInt < BuildVersionCodes.R;
bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R;
if (_view.Context is AvaloniaMainActivity activity)
if (!IsSupported(level))
{
continue;
}
if (level == TransparencyLevel)
{
return;
}
if (level == WindowTransparencyLevel.None)
{
if (OperatingSystem.IsAndroidVersionAtLeast(30))
{
activity.SetTranslucent(false);
}
activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.White));
}
else if (level == WindowTransparencyLevel.Transparent)
{
if (OperatingSystem.IsAndroidVersionAtLeast(30))
{
activity.SetTranslucent(true);
SetBlurBehind(activity, 0);
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
}
}
else if (level == WindowTransparencyLevel.Blur)
{
switch (transparencyLevel)
if (OperatingSystem.IsAndroidVersionAtLeast(31))
{
case WindowTransparencyLevel.AcrylicBlur:
case WindowTransparencyLevel.ForceAcrylicBlur:
case WindowTransparencyLevel.Mica:
case WindowTransparencyLevel.None:
if (!isBelowR)
{
activity.SetTranslucent(false);
}
if (isAboveR)
{
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
var attr = activity.Window?.Attributes;
if (attr != null)
{
attr.BlurBehindRadius = 0;
activity.Window.Attributes = attr;
}
}
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White));
if(transparencyLevel != WindowTransparencyLevel.None)
{
return;
}
break;
case WindowTransparencyLevel.Transparent:
if (!isBelowR)
{
activity.SetTranslucent(true);
}
if (isAboveR)
{
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
var attr = activity.Window?.Attributes;
if (attr != null)
{
attr.BlurBehindRadius = 0;
activity.Window.Attributes = attr;
}
}
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
break;
case WindowTransparencyLevel.Blur:
if (isAboveR)
{
activity.SetTranslucent(true);
activity.Window?.AddFlags(WindowManagerFlags.BlurBehind);
var attr = activity.Window?.Attributes;
if (attr != null)
{
attr.BlurBehindRadius = 120;
activity.Window.Attributes = attr;
}
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
}
else
{
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White));
return;
}
break;
activity.SetTranslucent(true);
SetBlurBehind(activity, 120);
activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
}
TransparencyLevel = transparencyLevel;
}
TransparencyLevel = level;
return;
}
// If we get here, we didn't find a supported level. Use the default of None.
if (OperatingSystem.IsAndroidVersionAtLeast(30))
{
activity.SetTranslucent(false);
}
activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.White));
}
public virtual object TryGetFeature(Type featureType)
{
if (featureType == typeof(IStorageProvider))
@ -418,6 +404,31 @@ namespace Avalonia.Android.Platform.SkiaPlatform
return null;
}
private static bool IsSupported(WindowTransparencyLevel level)
{
if (level == WindowTransparencyLevel.None)
return true;
if (level == WindowTransparencyLevel.Transparent)
return OperatingSystem.IsAndroidVersionAtLeast(30);
if (level == WindowTransparencyLevel.Blur)
return OperatingSystem.IsAndroidVersionAtLeast(31);
return false;
}
private static void SetBlurBehind(AvaloniaMainActivity activity, int radius)
{
if (radius == 0)
activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind);
else
activity.Window?.AddFlags(WindowManagerFlags.BlurBehind);
if (OperatingSystem.IsAndroidVersionAtLeast(31) && activity.Window?.Attributes is { } attr)
{
attr.BlurBehindRadius = radius;
activity.Window.Attributes = attr;
}
}
}
internal class AvaloniaInputConnection : BaseInputConnection

8
src/Avalonia.Base/Animation/Animatable.cs

@ -17,7 +17,7 @@ namespace Avalonia.Animation
/// <summary>
/// Defines the <see cref="Clock"/> property.
/// </summary>
public static readonly StyledProperty<IClock> ClockProperty =
internal static readonly StyledProperty<IClock> ClockProperty =
AvaloniaProperty.Register<Animatable, IClock>(nameof(Clock), inherits: true);
/// <summary>
@ -36,7 +36,7 @@ namespace Avalonia.Animation
/// <summary>
/// Gets or sets the clock which controls the animations on the control.
/// </summary>
public IClock Clock
internal IClock Clock
{
get => GetValue(ClockProperty);
set => SetValue(ClockProperty, value);
@ -58,7 +58,7 @@ namespace Avalonia.Animation
/// This method should not be called from user code, it will be called automatically by the framework
/// when a control is added to the visual tree.
/// </remarks>
protected void EnableTransitions()
internal void EnableTransitions()
{
if (!_transitionsEnabled)
{
@ -83,7 +83,7 @@ namespace Avalonia.Animation
/// This method should not be called from user code, it will be called automatically by the framework
/// when a control is removed from the visual tree.
/// </remarks>
protected void DisableTransitions()
internal void DisableTransitions()
{
if (_transitionsEnabled)
{

27
src/Avalonia.Base/Animation/Animation.cs

@ -16,7 +16,7 @@ namespace Avalonia.Animation
/// <summary>
/// Tracks the progress of an animation.
/// </summary>
public class Animation : AvaloniaObject, IAnimation
public sealed class Animation : AvaloniaObject, IAnimation
{
/// <summary>
/// Defines the <see cref="Duration"/> property.
@ -186,7 +186,7 @@ namespace Avalonia.Animation
/// </summary>
/// <param name="setter">The animation setter.</param>
/// <returns>The property animator type.</returns>
public static (Type Type, Func<IAnimator> Factory)? GetAnimator(IAnimationSetter setter)
internal static (Type Type, Func<IAnimator> Factory)? GetAnimator(IAnimationSetter setter)
{
if (s_animators.TryGetValue(setter, out var type))
{
@ -200,11 +200,9 @@ namespace Avalonia.Animation
/// </summary>
/// <param name="setter">The animation setter.</param>
/// <param name="value">The property animator value.</param>
public static void SetAnimator(IAnimationSetter setter,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicMethods)]
Type value)
public static void SetAnimator(IAnimationSetter setter, CustomAnimatorBase value)
{
s_animators[setter] = (value, () => (IAnimator)Activator.CreateInstance(value)!);
s_animators[setter] = (value.WrapperType, value.CreateWrapper);
}
private readonly static List<(Func<AvaloniaProperty, bool> Condition, Type Animator, Func<IAnimator> Factory)> Animators = new()
@ -233,7 +231,7 @@ namespace Avalonia.Animation
/// <typeparam name="TAnimator">
/// The type of the animator to instantiate.
/// </typeparam>
public static void RegisterAnimator<TAnimator>(Func<AvaloniaProperty, bool> condition)
internal static void RegisterAnimator<TAnimator>(Func<AvaloniaProperty, bool> condition)
where TAnimator : IAnimator, new()
{
Animators.Insert(0, (condition, typeof(TAnimator), () => new TAnimator()));
@ -312,8 +310,11 @@ namespace Avalonia.Animation
return (newAnimatorInstances, subscriptions);
}
IDisposable IAnimation.Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete)
=> Apply(control, clock, match, onComplete);
/// <inheritdoc/>
public IDisposable Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete)
internal IDisposable Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete)
{
var (animators, subscriptions) = InterpretKeyframes(control);
if (animators.Count == 1)
@ -358,14 +359,20 @@ namespace Avalonia.Animation
return new CompositeDisposable(subscriptions);
}
public Task RunAsync(Animatable control, CancellationToken cancellationToken = default) =>
RunAsync(control, null, cancellationToken);
/// <inheritdoc/>
public Task RunAsync(Animatable control, IClock? clock = null)
internal Task RunAsync(Animatable control, IClock? clock)
{
return RunAsync(control, clock, default);
}
Task IAnimation.RunAsync(Animatable control, IClock? clock, CancellationToken cancellationToken)
=> RunAsync(control, clock, cancellationToken);
/// <inheritdoc/>
public Task RunAsync(Animatable control, IClock? clock = null, CancellationToken cancellationToken = default)
internal Task RunAsync(Animatable control, IClock? clock, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{

9
src/Avalonia.Base/Animation/AnimatorDrivenTransition.cs

@ -1,5 +1,6 @@
using System;
using Avalonia.Animation.Animators;
using Avalonia.Animation.Easings;
namespace Avalonia.Animation
{
@ -8,13 +9,11 @@ namespace Avalonia.Animation
/// </summary>
/// <typeparam name="T">Type of the transitioned value.</typeparam>
/// <typeparam name="TAnimator">Type of the animator.</typeparam>
public abstract class AnimatorDrivenTransition<T, TAnimator> : Transition<T> where TAnimator : Animator<T>, new()
internal static class AnimatorDrivenTransition<T, TAnimator> where TAnimator : Animator<T>, new()
{
private static readonly TAnimator s_animator = new TAnimator();
public override IObservable<T> DoTransition(IObservable<double> progress, T oldValue, T newValue)
{
return new AnimatorTransitionObservable<T, TAnimator>(s_animator, progress, Easing, oldValue, newValue);
}
public static IObservable<T> Transition(IEasing easing, IObservable<double> progress, T oldValue, T newValue) =>
new AnimatorTransitionObservable<T, TAnimator>(s_animator, progress, easing, oldValue, newValue);
}
}

4
src/Avalonia.Base/Animation/AnimatorKeyFrame.cs

@ -11,7 +11,7 @@ namespace Avalonia.Animation
/// Defines a KeyFrame that is used for
/// <see cref="Animator{T}"/> objects.
/// </summary>
public class AnimatorKeyFrame : AvaloniaObject
internal class AnimatorKeyFrame : AvaloniaObject
{
public static readonly DirectProperty<AnimatorKeyFrame, object?> ValueProperty =
AvaloniaProperty.RegisterDirect<AnimatorKeyFrame, object?>(nameof(Value), k => k.Value, (k, v) => k.Value = v);
@ -67,7 +67,7 @@ namespace Avalonia.Animation
}
}
[RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)]
[RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)]
public T GetTypedValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{
var typeConv = TypeDescriptor.GetConverter(typeof(T));

6
src/Avalonia.Base/Animation/AnimatorTransitionObservable.cs

@ -9,17 +9,15 @@ namespace Avalonia.Animation
/// </summary>
/// <typeparam name="T">Type of the transitioned value.</typeparam>
/// <typeparam name="TAnimator">Type of the animator.</typeparam>
public class AnimatorTransitionObservable<T, TAnimator> : TransitionObservableBase<T> where TAnimator : Animator<T>
internal class AnimatorTransitionObservable<T, TAnimator> : TransitionObservableBase<T> where TAnimator : Animator<T>
{
private readonly TAnimator _animator;
private readonly Easing _easing;
private readonly T _oldValue;
private readonly T _newValue;
public AnimatorTransitionObservable(TAnimator animator, IObservable<double> progress, Easing easing, T oldValue, T newValue) : base(progress, easing)
public AnimatorTransitionObservable(TAnimator animator, IObservable<double> progress, IEasing easing, T oldValue, T newValue) : base(progress, easing)
{
_animator = animator;
_easing = easing;
_oldValue = oldValue;
_newValue = newValue;
}

2
src/Avalonia.Base/Animation/Animators/Animator`1.cs

@ -11,7 +11,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Base class for <see cref="Animator{T}"/> objects
/// </summary>
public abstract class Animator<T> : AvaloniaList<AnimatorKeyFrame>, IAnimator
internal abstract class Animator<T> : AvaloniaList<AnimatorKeyFrame>, IAnimator
{
/// <summary>
/// List of type-converted keyframes.

2
src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs

@ -15,7 +15,7 @@ namespace Avalonia.Animation.Animators
/// redirect them to the properly registered
/// animators in this class.
/// </summary>
public class BaseBrushAnimator : Animator<IBrush?>
internal class BaseBrushAnimator : Animator<IBrush?>
{
private static readonly List<(Func<Type, bool> Match, Type AnimatorType, Func<IAnimator> AnimatorFactory)> _brushAnimators = new();

2
src/Avalonia.Base/Animation/Animators/BoolAnimator.cs

@ -3,7 +3,7 @@
/// <summary>
/// Animator that handles <see cref="bool"/> properties.
/// </summary>
public class BoolAnimator : Animator<bool>
internal class BoolAnimator : Animator<bool>
{
/// <inheritdocs/>
public override bool Interpolate(double progress, bool oldValue, bool newValue)

2
src/Avalonia.Base/Animation/Animators/BoxShadowAnimator.cs

@ -2,7 +2,7 @@ using Avalonia.Media;
namespace Avalonia.Animation.Animators
{
public class BoxShadowAnimator : Animator<BoxShadow>
internal class BoxShadowAnimator : Animator<BoxShadow>
{
static ColorAnimator s_colorAnimator = new ColorAnimator();
static DoubleAnimator s_doubleAnimator = new DoubleAnimator();

2
src/Avalonia.Base/Animation/Animators/BoxShadowsAnimator.cs

@ -2,7 +2,7 @@ using Avalonia.Media;
namespace Avalonia.Animation.Animators
{
public class BoxShadowsAnimator : Animator<BoxShadows>
internal class BoxShadowsAnimator : Animator<BoxShadows>
{
private static readonly BoxShadowAnimator s_boxShadowAnimator = new BoxShadowAnimator();
public override BoxShadows Interpolate(double progress, BoxShadows oldValue, BoxShadows newValue)

2
src/Avalonia.Base/Animation/Animators/ByteAnimator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="byte"/> properties.
/// </summary>
public class ByteAnimator : Animator<byte>
internal class ByteAnimator : Animator<byte>
{
const double maxVal = (double)byte.MaxValue;

2
src/Avalonia.Base/Animation/Animators/ColorAnimator.cs

@ -12,7 +12,7 @@ namespace Avalonia.Animation.Animators
/// Animator that interpolates <see cref="Color"/> through
/// gamma sRGB color space for better visual result.
/// </summary>
public class ColorAnimator : Animator<Color>
internal class ColorAnimator : Animator<Color>
{
/// <summary>
/// Opto-electronic conversion function for the sRGB color space.

2
src/Avalonia.Base/Animation/Animators/CornerRadiusAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="CornerRadius"/> properties.
/// </summary>
public class CornerRadiusAnimator : Animator<CornerRadius>
internal class CornerRadiusAnimator : Animator<CornerRadius>
{
public override CornerRadius Interpolate(double progress, CornerRadius oldValue, CornerRadius newValue)
{

2
src/Avalonia.Base/Animation/Animators/DecimalAnimator.cs

@ -3,7 +3,7 @@
/// <summary>
/// Animator that handles <see cref="decimal"/> properties.
/// </summary>
public class DecimalAnimator : Animator<decimal>
internal class DecimalAnimator : Animator<decimal>
{
/// <inheritdocs/>
public override decimal Interpolate(double progress, decimal oldValue, decimal newValue)

2
src/Avalonia.Base/Animation/Animators/DoubleAnimator.cs

@ -3,7 +3,7 @@
/// <summary>
/// Animator that handles <see cref="double"/> properties.
/// </summary>
public class DoubleAnimator : Animator<double>
internal class DoubleAnimator : Animator<double>
{
/// <inheritdocs/>
public override double Interpolate(double progress, double oldValue, double newValue)

2
src/Avalonia.Base/Animation/Animators/FloatAnimator.cs

@ -3,7 +3,7 @@
/// <summary>
/// Animator that handles <see cref="float"/> properties.
/// </summary>
public class FloatAnimator : Animator<float>
internal class FloatAnimator : Animator<float>
{
/// <inheritdocs/>
public override float Interpolate(double progress, float oldValue, float newValue)

2
src/Avalonia.Base/Animation/Animators/GradientBrushAnimator.cs

@ -13,7 +13,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="SolidColorBrush"/> values.
/// </summary>
public class GradientBrushAnimator : Animator<IGradientBrush?>
internal class GradientBrushAnimator : Animator<IGradientBrush?>
{
private static readonly RelativePointAnimator s_relativePointAnimator = new RelativePointAnimator();
private static readonly DoubleAnimator s_doubleAnimator = new DoubleAnimator();

2
src/Avalonia.Base/Animation/Animators/Int16Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="Int16"/> properties.
/// </summary>
public class Int16Animator : Animator<Int16>
internal class Int16Animator : Animator<Int16>
{
const double maxVal = (double)Int16.MaxValue;

2
src/Avalonia.Base/Animation/Animators/Int32Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="Int32"/> properties.
/// </summary>
public class Int32Animator : Animator<Int32>
internal class Int32Animator : Animator<Int32>
{
const double maxVal = (double)Int32.MaxValue;

2
src/Avalonia.Base/Animation/Animators/Int64Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="Int64"/> properties.
/// </summary>
public class Int64Animator : Animator<Int64>
internal class Int64Animator : Animator<Int64>
{
const double maxVal = (double)Int64.MaxValue;

2
src/Avalonia.Base/Animation/Animators/PointAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="Point"/> properties.
/// </summary>
public class PointAnimator : Animator<Point>
internal class PointAnimator : Animator<Point>
{
public override Point Interpolate(double progress, Point oldValue, Point newValue)
{

2
src/Avalonia.Base/Animation/Animators/RectAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="Rect"/> properties.
/// </summary>
public class RectAnimator : Animator<Rect>
internal class RectAnimator : Animator<Rect>
{
public override Rect Interpolate(double progress, Rect oldValue, Rect newValue)
{

2
src/Avalonia.Base/Animation/Animators/RelativePointAnimator.cs

@ -3,7 +3,7 @@
/// <summary>
/// Animator that handles <see cref="RelativePoint"/> properties.
/// </summary>
public class RelativePointAnimator : Animator<RelativePoint>
internal class RelativePointAnimator : Animator<RelativePoint>
{
private static readonly PointAnimator s_pointAnimator = new PointAnimator();

2
src/Avalonia.Base/Animation/Animators/SizeAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="Size"/> properties.
/// </summary>
public class SizeAnimator : Animator<Size>
internal class SizeAnimator : Animator<Size>
{
public override Size Interpolate(double progress, Size oldValue, Size newValue)
{

2
src/Avalonia.Base/Animation/Animators/SolidColorBrushAnimator.cs

@ -10,7 +10,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="SolidColorBrush"/> values.
/// </summary>
public class ISolidColorBrushAnimator : Animator<ISolidColorBrush?>
internal class ISolidColorBrushAnimator : Animator<ISolidColorBrush?>
{
private static readonly DoubleAnimator s_doubleAnimator = new DoubleAnimator();

2
src/Avalonia.Base/Animation/Animators/ThicknessAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="Thickness"/> properties.
/// </summary>
public class ThicknessAnimator : Animator<Thickness>
internal class ThicknessAnimator : Animator<Thickness>
{
public override Thickness Interpolate(double progress, Thickness oldValue, Thickness newValue)
{

2
src/Avalonia.Base/Animation/Animators/TransformAnimator.cs

@ -9,7 +9,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="Transform"/> properties.
/// </summary>
public class TransformAnimator : Animator<double>
internal class TransformAnimator : Animator<double>
{
DoubleAnimator? _doubleAnimator;

2
src/Avalonia.Base/Animation/Animators/TransformOperationsAnimator.cs

@ -4,7 +4,7 @@ using Avalonia.Media.Transformation;
namespace Avalonia.Animation.Animators
{
public class TransformOperationsAnimator : Animator<TransformOperations>
internal class TransformOperationsAnimator : Animator<TransformOperations>
{
public TransformOperationsAnimator()
{

2
src/Avalonia.Base/Animation/Animators/UInt16Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="UInt16"/> properties.
/// </summary>
public class UInt16Animator : Animator<UInt16>
internal class UInt16Animator : Animator<UInt16>
{
const double maxVal = (double)UInt16.MaxValue;

2
src/Avalonia.Base/Animation/Animators/UInt32Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="UInt32"/> properties.
/// </summary>
public class UInt32Animator : Animator<UInt32>
internal class UInt32Animator : Animator<UInt32>
{
const double maxVal = (double)UInt32.MaxValue;

2
src/Avalonia.Base/Animation/Animators/UInt64Animator.cs

@ -5,7 +5,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="UInt64"/> properties.
/// </summary>
public class UInt64Animator : Animator<UInt64>
internal class UInt64Animator : Animator<UInt64>
{
const double maxVal = (double)UInt64.MaxValue;

2
src/Avalonia.Base/Animation/Animators/VectorAnimator.cs

@ -7,7 +7,7 @@ namespace Avalonia.Animation.Animators
/// <summary>
/// Animator that handles <see cref="Vector"/> properties.
/// </summary>
public class VectorAnimator : Animator<Vector>
internal class VectorAnimator : Animator<Vector>
{
public override Vector Interpolate(double progress, Vector oldValue, Vector newValue)
{

5
src/Avalonia.Base/Animation/Clock.cs

@ -3,7 +3,10 @@ using Avalonia.Reactive;
namespace Avalonia.Animation
{
public class Clock : ClockBase
// Note: this class was always broken: it subscribes to the global clock immediately even it if
// doesn't actually have subscriptions
internal class Clock : ClockBase
{
public static IClock GlobalClock => AvaloniaLocator.Current.GetRequiredService<IGlobalClock>();

2
src/Avalonia.Base/Animation/ClockBase.cs

@ -3,7 +3,7 @@ using Avalonia.Reactive;
namespace Avalonia.Animation
{
public class ClockBase : IClock
internal class ClockBase : IClock
{
private readonly ClockObservable _observable;

3
src/Avalonia.Base/Animation/Easings/IEasing.cs

@ -1,8 +1,11 @@
using Avalonia.Metadata;
namespace Avalonia.Animation.Easings
{
/// <summary>
/// Defines the interface for easing classes.
/// </summary>
[NotClientImplementable]
public interface IEasing
{
/// <summary>

5
src/Avalonia.Base/Animation/Easings/SpringEasing.cs

@ -64,11 +64,6 @@ public class SpringEasing : Easing
Damping = damping;
InitialVelocity = initialVelocity;
}
public SpringEasing(Spring keySpline)
{
_internalSpring = keySpline;
}
public SpringEasing()
{

4
src/Avalonia.Base/Animation/IAnimation.cs

@ -14,11 +14,11 @@ namespace Avalonia.Animation
/// <summary>
/// Apply the animation to the specified control and run it when <paramref name="match" /> produces <c>true</c>.
/// </summary>
IDisposable Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete = null);
internal IDisposable Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete = null);
/// <summary>
/// Run the animation on the specified control.
/// </summary>
Task RunAsync(Animatable control, IClock clock, CancellationToken cancellationToken = default);
internal Task RunAsync(Animatable control, IClock clock, CancellationToken cancellationToken = default);
}
}

2
src/Avalonia.Base/Animation/IAnimationSetter.cs

@ -2,7 +2,7 @@ using Avalonia.Metadata;
namespace Avalonia.Animation
{
[NotClientImplementable]
[NotClientImplementable, PrivateApi]
public interface IAnimationSetter
{
AvaloniaProperty? Property { get; set; }

3
src/Avalonia.Base/Animation/IAnimator.cs

@ -7,8 +7,7 @@ namespace Avalonia.Animation
/// <summary>
/// Interface for Animator objects
/// </summary>
[NotClientImplementable]
public interface IAnimator : IList<AnimatorKeyFrame>
internal interface IAnimator : IList<AnimatorKeyFrame>
{
/// <summary>
/// The target property.

3
src/Avalonia.Base/Animation/IClock.cs

@ -3,8 +3,7 @@ using Avalonia.Metadata;
namespace Avalonia.Animation
{
[NotClientImplementable]
public interface IClock : IObservable<TimeSpan>
internal interface IClock : IObservable<TimeSpan>
{
PlayState PlayState { get; set; }
}

30
src/Avalonia.Base/Animation/ICustomAnimator.cs

@ -0,0 +1,30 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation;
public abstract class CustomAnimatorBase
{
internal abstract IAnimator CreateWrapper();
internal abstract Type WrapperType { get; }
}
public abstract class CustomAnimatorBase<T> : CustomAnimatorBase
{
public abstract T Interpolate(double progress, T oldValue, T newValue);
internal override Type WrapperType => typeof(AnimatorWrapper);
internal override IAnimator CreateWrapper() => new AnimatorWrapper(this);
internal class AnimatorWrapper : Animator<T>
{
private readonly CustomAnimatorBase<T> _parent;
public AnimatorWrapper(CustomAnimatorBase<T> parent)
{
_parent = parent;
}
public override T Interpolate(double progress, T oldValue, T newValue) => _parent.Interpolate(progress, oldValue, newValue);
}
}

3
src/Avalonia.Base/Animation/IGlobalClock.cs

@ -2,8 +2,7 @@ using Avalonia.Metadata;
namespace Avalonia.Animation
{
[NotClientImplementable]
public interface IGlobalClock : IClock
internal interface IGlobalClock : IClock
{
}
}

4
src/Avalonia.Base/Animation/ITransition.cs

@ -6,13 +6,13 @@ namespace Avalonia.Animation
/// <summary>
/// Interface for Transition objects.
/// </summary>
[NotClientImplementable]
[NotClientImplementable, PrivateApi]
public interface ITransition
{
/// <summary>
/// Applies the transition to the specified <see cref="Animatable"/>.
/// </summary>
IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue);
internal IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue);
/// <summary>
/// Gets the property to be animated.

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

Loading…
Cancel
Save