Browse Source

Merge remote-tracking branch 'origin/master' into wpf-winforms-interop-core

# Conflicts:
#	src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs
pull/11488/head
Max Katz 3 years ago
parent
commit
94e709972b
  1. 11
      Avalonia.Desktop.slnf
  2. 2
      build/SharedVersion.props
  3. 2
      nukebuild/Build.cs
  4. 48
      nukebuild/RefAssemblyGenerator.cs
  5. 1
      samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
  6. 5
      samples/ControlCatalog/MainView.xaml.cs
  7. 4
      samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs
  8. 2
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  9. 3
      samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs
  10. 29
      samples/ControlCatalog/Pages/TabControlPage.xaml
  11. 2
      samples/GpuInterop/MainWindow.axaml.cs
  12. 2
      samples/IntegrationTestApp/MainWindow.axaml.cs
  13. 21
      samples/MobileSandbox.Desktop/MobileSandbox.Desktop.csproj
  14. 15
      samples/MobileSandbox/MobileSandbox.csproj
  15. 2
      samples/RenderDemo/MainWindow.xaml.cs
  16. 4
      samples/RenderDemo/Pages/AnimationsPage.xaml
  17. 15
      samples/RenderDemo/Pages/AnimationsPage.xaml.cs
  18. 12
      samples/RenderDemo/Pages/CustomAnimatorPage.xaml
  19. 5
      samples/RenderDemo/Pages/CustomStringAnimator.cs
  20. 3
      samples/RenderDemo/Pages/Transform3DPage.axaml
  21. 4
      samples/RenderDemo/Pages/TransitionsPage.xaml
  22. 15
      samples/RenderDemo/Pages/TransitionsPage.xaml.cs
  23. 1
      samples/Sandbox/Sandbox.csproj
  24. 7
      src/Android/Avalonia.Android/AndroidPlatform.cs
  25. 4
      src/Android/Avalonia.Android/AvaloniaView.cs
  26. 2
      src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
  27. 173
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  28. 4
      src/Avalonia.Base/Animation/Animatable.cs
  29. 27
      src/Avalonia.Base/Animation/Animation.cs
  30. 9
      src/Avalonia.Base/Animation/AnimatorDrivenTransition.cs
  31. 2
      src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
  32. 6
      src/Avalonia.Base/Animation/AnimatorTransitionObservable.cs
  33. 2
      src/Avalonia.Base/Animation/Animators/Animator`1.cs
  34. 2
      src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs
  35. 2
      src/Avalonia.Base/Animation/Animators/BoolAnimator.cs
  36. 2
      src/Avalonia.Base/Animation/Animators/BoxShadowAnimator.cs
  37. 2
      src/Avalonia.Base/Animation/Animators/BoxShadowsAnimator.cs
  38. 2
      src/Avalonia.Base/Animation/Animators/ByteAnimator.cs
  39. 2
      src/Avalonia.Base/Animation/Animators/ColorAnimator.cs
  40. 2
      src/Avalonia.Base/Animation/Animators/CornerRadiusAnimator.cs
  41. 2
      src/Avalonia.Base/Animation/Animators/DecimalAnimator.cs
  42. 2
      src/Avalonia.Base/Animation/Animators/DoubleAnimator.cs
  43. 2
      src/Avalonia.Base/Animation/Animators/FloatAnimator.cs
  44. 2
      src/Avalonia.Base/Animation/Animators/GradientBrushAnimator.cs
  45. 2
      src/Avalonia.Base/Animation/Animators/Int16Animator.cs
  46. 2
      src/Avalonia.Base/Animation/Animators/Int32Animator.cs
  47. 2
      src/Avalonia.Base/Animation/Animators/Int64Animator.cs
  48. 2
      src/Avalonia.Base/Animation/Animators/PointAnimator.cs
  49. 2
      src/Avalonia.Base/Animation/Animators/RectAnimator.cs
  50. 2
      src/Avalonia.Base/Animation/Animators/RelativePointAnimator.cs
  51. 2
      src/Avalonia.Base/Animation/Animators/SizeAnimator.cs
  52. 2
      src/Avalonia.Base/Animation/Animators/SolidColorBrushAnimator.cs
  53. 2
      src/Avalonia.Base/Animation/Animators/ThicknessAnimator.cs
  54. 2
      src/Avalonia.Base/Animation/Animators/TransformAnimator.cs
  55. 2
      src/Avalonia.Base/Animation/Animators/TransformOperationsAnimator.cs
  56. 2
      src/Avalonia.Base/Animation/Animators/UInt16Animator.cs
  57. 2
      src/Avalonia.Base/Animation/Animators/UInt32Animator.cs
  58. 2
      src/Avalonia.Base/Animation/Animators/UInt64Animator.cs
  59. 2
      src/Avalonia.Base/Animation/Animators/VectorAnimator.cs
  60. 5
      src/Avalonia.Base/Animation/Clock.cs
  61. 2
      src/Avalonia.Base/Animation/ClockBase.cs
  62. 3
      src/Avalonia.Base/Animation/Easings/IEasing.cs
  63. 5
      src/Avalonia.Base/Animation/Easings/SpringEasing.cs
  64. 4
      src/Avalonia.Base/Animation/IAnimation.cs
  65. 2
      src/Avalonia.Base/Animation/IAnimationSetter.cs
  66. 3
      src/Avalonia.Base/Animation/IAnimator.cs
  67. 3
      src/Avalonia.Base/Animation/IClock.cs
  68. 30
      src/Avalonia.Base/Animation/ICustomAnimator.cs
  69. 3
      src/Avalonia.Base/Animation/IGlobalClock.cs
  70. 4
      src/Avalonia.Base/Animation/ITransition.cs
  71. 2
      src/Avalonia.Base/Animation/KeyFrame.cs
  72. 2
      src/Avalonia.Base/Animation/KeyFrames.cs
  73. 2
      src/Avalonia.Base/Animation/KeySpline.cs
  74. 26
      src/Avalonia.Base/Animation/RenderLoopClock.cs
  75. 2
      src/Avalonia.Base/Animation/Spring.cs
  76. 2
      src/Avalonia.Base/Animation/SpringTypeConverter.cs
  77. 7
      src/Avalonia.Base/Animation/Transition.cs
  78. 6
      src/Avalonia.Base/Animation/TransitionObservableBase.cs
  79. 2
      src/Avalonia.Base/Animation/Transitions.cs
  80. 6
      src/Avalonia.Base/Animation/Transitions/BoxShadowsTransition.cs
  81. 2
      src/Avalonia.Base/Animation/Transitions/BrushTransition.cs
  82. 7
      src/Avalonia.Base/Animation/Transitions/ColorTransition.cs
  83. 7
      src/Avalonia.Base/Animation/Transitions/CornerRadiusTransition.cs
  84. 5
      src/Avalonia.Base/Animation/Transitions/DoubleTransition.cs
  85. 5
      src/Avalonia.Base/Animation/Transitions/FloatTransition.cs
  86. 5
      src/Avalonia.Base/Animation/Transitions/IntegerTransition.cs
  87. 5
      src/Avalonia.Base/Animation/Transitions/PointTransition.cs
  88. 5
      src/Avalonia.Base/Animation/Transitions/RelativePointTransition.cs
  89. 5
      src/Avalonia.Base/Animation/Transitions/SizeTransition.cs
  90. 5
      src/Avalonia.Base/Animation/Transitions/ThicknessTransition.cs
  91. 2
      src/Avalonia.Base/Animation/Transitions/TransformOperationsTransition.cs
  92. 5
      src/Avalonia.Base/Animation/Transitions/VectorTransition.cs
  93. 4
      src/Avalonia.Base/AvaloniaLocator.cs
  94. 37
      src/Avalonia.Base/Data/TemplateBinding.cs
  95. 4
      src/Avalonia.Base/Input/AccessKeyHandler.cs
  96. 2
      src/Avalonia.Base/Input/DragDropDevice.cs
  97. 2
      src/Avalonia.Base/Input/IInputDevice.cs
  98. 2
      src/Avalonia.Base/Input/IInputManager.cs
  99. 1
      src/Avalonia.Base/Input/IKeyboardNavigationHandler.cs
  100. 2
      src/Avalonia.Base/Input/IMainMenu.cs

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"
]
}
}
}

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>

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);
}

48
nukebuild/RefAssemblyGenerator.cs

@ -71,10 +71,10 @@ public class RefAssemblyGenerator
foreach (var nested in type.NestedTypes)
ProcessType(nested, obsoleteCtor);
var hideMethods = (type.IsInterface && type.Name.EndsWith("Impl"))
var hideMembers = (type.IsInterface && type.Name.EndsWith("Impl"))
|| HasPrivateApi(type.CustomAttributes);
var injectMethod = hideMethods
var injectMethod = hideMembers
|| type.CustomAttributes.Any(a =>
a.AttributeType.FullName == "Avalonia.Metadata.NotClientImplementableAttribute");
@ -95,21 +95,57 @@ public class RefAssemblyGenerator
foreach (var m in type.Methods)
{
if (hideMethods || HasPrivateApi(m.CustomAttributes))
if (hideMembers || HasPrivateApi(m.CustomAttributes))
{
var dflags = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.FamORAssem |
MethodAttributes.FamANDAssem | MethodAttributes.Assembly;
m.Attributes = ((m.Attributes | dflags) ^ dflags) | MethodAttributes.Assembly;
HideMethod(m);
}
MarkAsUnstable(m, obsoleteCtor, forceUnstable);
}
foreach (var p in type.Properties)
{
if (HasPrivateApi(p.CustomAttributes))
{
if (p.SetMethod != null)
HideMethod(p.SetMethod);
if (p.GetMethod != null)
HideMethod(p.GetMethod);
}
}
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"))

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);

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;

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/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/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>

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)
{

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>

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();
}
}

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

4
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);

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);
}
}

2
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);

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.

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

@ -15,7 +15,7 @@ namespace Avalonia.Animation
/// Stores data regarding a specific key
/// point and value in an animation.
/// </summary>
public class KeyFrame : AvaloniaObject
public sealed class KeyFrame : AvaloniaObject
{
private TimeSpan _ktimeSpan;
private Cue _kCue;

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

@ -7,7 +7,7 @@ namespace Avalonia.Animation
/// <summary>
/// A collection of <see cref="KeyFrame"/>s.
/// </summary>
public class KeyFrames : AvaloniaList<KeyFrame>
public sealed class KeyFrames : AvaloniaList<KeyFrame>
{
/// <summary>
/// Initializes a new instance of the <see cref="KeyFrames"/> class.

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

@ -17,7 +17,7 @@ namespace Avalonia.Animation
/// See https://docs.microsoft.com/en-us/dotnet/api/system.windows.media.animation.keyspline
/// </summary>
[TypeConverter(typeof(KeySplineTypeConverter))]
public class KeySpline : AvaloniaObject
public sealed class KeySpline : AvaloniaObject
{
// Control points
private double _controlPointX1;

26
src/Avalonia.Base/Animation/RenderLoopClock.cs

@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using Avalonia.Rendering;
namespace Avalonia.Animation
{
public class RenderLoopClock : ClockBase, IRenderLoopTask, IGlobalClock
{
protected override void Stop()
{
AvaloniaLocator.Current.GetRequiredService<IRenderLoop>().Remove(this);
}
bool IRenderLoopTask.NeedsUpdate => HasSubscriptions;
void IRenderLoopTask.Render()
{
}
void IRenderLoopTask.Update(TimeSpan time)
{
Pulse(time);
}
}
}

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

@ -10,7 +10,7 @@ namespace Avalonia.Animation;
/// Determines how an animation is used based on spring formula.
/// </summary>
[TypeConverter(typeof(SpringTypeConverter))]
public class Spring
internal class Spring
{
private SpringSolver _springSolver;
private double _mass;

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

@ -7,7 +7,7 @@ namespace Avalonia.Animation;
/// <summary>
/// Converts string values to <see cref="Spring"/> values.
/// </summary>
public class SpringTypeConverter : TypeConverter
internal class SpringTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
{

7
src/Avalonia.Base/Animation/Transition.cs

@ -53,10 +53,13 @@ namespace Avalonia.Animation
/// <summary>
/// Apply interpolation to the property.
/// </summary>
public abstract IObservable<T> DoTransition(IObservable<double> progress, T oldValue, T newValue);
internal abstract IObservable<T> DoTransition(IObservable<double> progress, T oldValue, T newValue);
/// <inheritdocs/>
public virtual IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue)
IDisposable ITransition.Apply(Animatable control, IClock clock, object? oldValue, object? newValue)
=> Apply(control, clock, oldValue, newValue);
internal virtual IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue)
{
if (Property is null)
throw new InvalidOperationException("Transition has no property specified.");

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

@ -10,13 +10,13 @@ namespace Avalonia.Animation
/// Provides base for observables implementing transitions.
/// </summary>
/// <typeparam name="T">Type of the transitioned value.</typeparam>
public abstract class TransitionObservableBase<T> : SingleSubscriberObservableBase<T>, IObserver<double>
internal abstract class TransitionObservableBase<T> : SingleSubscriberObservableBase<T>, IObserver<double>
{
private readonly Easing _easing;
private readonly IEasing _easing;
private readonly IObservable<double> _progress;
private IDisposable? _progressSubscription;
protected TransitionObservableBase(IObservable<double> progress, Easing easing)
protected TransitionObservableBase(IObservable<double> progress, IEasing easing)
{
_progress = progress;
_easing = easing;

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

@ -7,7 +7,7 @@ namespace Avalonia.Animation
/// <summary>
/// A collection of <see cref="ITransition"/> definitions.
/// </summary>
public class Transitions : AvaloniaList<ITransition>
public sealed class Transitions : AvaloniaList<ITransition>
{
/// <summary>
/// Initializes a new instance of the <see cref="Transitions"/> class.

6
src/Avalonia.Base/Animation/Transitions/BoxShadowsTransition.cs

@ -1,3 +1,4 @@
using System;
using Avalonia.Animation.Animators;
using Avalonia.Media;
@ -6,7 +7,10 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="BoxShadows"/> type.
/// </summary>
public class BoxShadowsTransition : AnimatorDrivenTransition<BoxShadows, BoxShadowsAnimator>
public class BoxShadowsTransition : Transition<BoxShadows>
{
internal override IObservable<BoxShadows> DoTransition(IObservable<double> progress, BoxShadows oldValue,
BoxShadows newValue) =>
AnimatorDrivenTransition<BoxShadows, BoxShadowsAnimator>.Transition(Easing, progress, oldValue, newValue);
}
}

2
src/Avalonia.Base/Animation/Transitions/BrushTransition.cs

@ -16,7 +16,7 @@ namespace Avalonia.Animation
private static readonly GradientBrushAnimator s_gradientAnimator = new GradientBrushAnimator();
private static readonly ISolidColorBrushAnimator s_solidColorBrushAnimator = new ISolidColorBrushAnimator();
public override IObservable<IBrush?> DoTransition(IObservable<double> progress, IBrush? oldValue, IBrush? newValue)
internal override IObservable<IBrush?> DoTransition(IObservable<double> progress, IBrush? oldValue, IBrush? newValue)
{
if (oldValue is null || newValue is null)
{

7
src/Avalonia.Base/Animation/Transitions/ColorTransition.cs

@ -1,4 +1,5 @@
using Avalonia.Animation.Animators;
using System;
using Avalonia.Animation.Animators;
using Avalonia.Media;
namespace Avalonia.Animation
@ -6,7 +7,9 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="Color"/> type.
/// </summary>
public class ColorTransition : AnimatorDrivenTransition<Color, ColorAnimator>
public class ColorTransition : Transition<Color>
{
internal override IObservable<Color> DoTransition(IObservable<double> progress, Color oldValue, Color newValue)
=> AnimatorDrivenTransition<Color, ColorAnimator>.Transition(Easing, progress, oldValue, newValue);
}
}

7
src/Avalonia.Base/Animation/Transitions/CornerRadiusTransition.cs

@ -1,3 +1,4 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation
@ -5,7 +6,11 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="CornerRadius"/> type.
/// </summary>
public class CornerRadiusTransition : AnimatorDrivenTransition<CornerRadius, CornerRadiusAnimator>
public class CornerRadiusTransition : Transition<CornerRadius>
{
internal override IObservable<CornerRadius> DoTransition(IObservable<double> progress, CornerRadius oldValue,
CornerRadius newValue) =>
AnimatorDrivenTransition<CornerRadius, CornerRadiusAnimator>.Transition(Easing, progress, oldValue,
newValue);
}
}

5
src/Avalonia.Base/Animation/Transitions/DoubleTransition.cs

@ -1,3 +1,4 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation
@ -5,7 +6,9 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="double"/> types.
/// </summary>
public class DoubleTransition : AnimatorDrivenTransition<double, DoubleAnimator>
public class DoubleTransition : Transition<double>
{
internal override IObservable<double> DoTransition(IObservable<double> progress, double oldValue, double newValue) =>
AnimatorDrivenTransition<double, DoubleAnimator>.Transition(Easing, progress, oldValue, newValue);
}
}

5
src/Avalonia.Base/Animation/Transitions/FloatTransition.cs

@ -1,3 +1,4 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation
@ -5,7 +6,9 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="float"/> types.
/// </summary>
public class FloatTransition : AnimatorDrivenTransition<float, FloatAnimator>
public class FloatTransition : Transition<float>
{
internal override IObservable<float> DoTransition(IObservable<double> progress, float oldValue, float newValue) =>
AnimatorDrivenTransition<float, FloatAnimator>.Transition(Easing, progress, oldValue, newValue);
}
}

5
src/Avalonia.Base/Animation/Transitions/IntegerTransition.cs

@ -1,3 +1,4 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation
@ -5,7 +6,9 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="int"/> types.
/// </summary>
public class IntegerTransition : AnimatorDrivenTransition<int, Int32Animator>
public class IntegerTransition : Transition<int>
{
internal override IObservable<int> DoTransition(IObservable<double> progress, int oldValue, int newValue) =>
AnimatorDrivenTransition<int, Int32Animator>.Transition(Easing, progress, oldValue, newValue);
}
}

5
src/Avalonia.Base/Animation/Transitions/PointTransition.cs

@ -1,3 +1,4 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation
@ -5,7 +6,9 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="Point"/> type.
/// </summary>
public class PointTransition : AnimatorDrivenTransition<Point, PointAnimator>
public class PointTransition : Transition<Point>
{
internal override IObservable<Point> DoTransition(IObservable<double> progress, Point oldValue, Point newValue) =>
AnimatorDrivenTransition<Point, PointAnimator>.Transition(Easing, progress, oldValue, newValue);
}
}

5
src/Avalonia.Base/Animation/Transitions/RelativePointTransition.cs

@ -1,3 +1,4 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation
@ -5,7 +6,9 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="RelativePoint"/> type.
/// </summary>
public class RelativePointTransition : AnimatorDrivenTransition<RelativePoint, RelativePointAnimator>
public class RelativePointTransition : Transition<RelativePoint>
{
internal override IObservable<RelativePoint> DoTransition(IObservable<double> progress, RelativePoint oldValue, RelativePoint newValue) =>
AnimatorDrivenTransition<RelativePoint, RelativePointAnimator>.Transition(Easing, progress, oldValue, newValue);
}
}

5
src/Avalonia.Base/Animation/Transitions/SizeTransition.cs

@ -1,3 +1,4 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation
@ -5,7 +6,9 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="Size"/> type.
/// </summary>
public class SizeTransition : AnimatorDrivenTransition<Size, SizeAnimator>
public class SizeTransition : Transition<Size>
{
internal override IObservable<Size> DoTransition(IObservable<double> progress, Size oldValue, Size newValue) =>
AnimatorDrivenTransition<Size, SizeAnimator>.Transition(Easing, progress, oldValue, newValue);
}
}

5
src/Avalonia.Base/Animation/Transitions/ThicknessTransition.cs

@ -1,3 +1,4 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation
@ -5,7 +6,9 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="Thickness"/> type.
/// </summary>
public class ThicknessTransition : AnimatorDrivenTransition<Thickness, ThicknessAnimator>
public class ThicknessTransition : Transition<Thickness>
{
internal override IObservable<Thickness> DoTransition(IObservable<double> progress, Thickness oldValue, Thickness newValue) =>
AnimatorDrivenTransition<Thickness, ThicknessAnimator>.Transition(Easing, progress, oldValue, newValue);
}
}

2
src/Avalonia.Base/Animation/Transitions/TransformOperationsTransition.cs

@ -11,7 +11,7 @@ namespace Avalonia.Animation
{
private static readonly TransformOperationsAnimator s_operationsAnimator = new TransformOperationsAnimator();
public override IObservable<ITransform> DoTransition(
internal override IObservable<ITransform> DoTransition(
IObservable<double> progress,
ITransform oldValue,
ITransform newValue)

5
src/Avalonia.Base/Animation/Transitions/VectorTransition.cs

@ -1,3 +1,4 @@
using System;
using Avalonia.Animation.Animators;
namespace Avalonia.Animation
@ -5,7 +6,9 @@ namespace Avalonia.Animation
/// <summary>
/// Transition class that handles <see cref="AvaloniaProperty"/> with <see cref="Vector"/> type.
/// </summary>
public class VectorTransition : AnimatorDrivenTransition<Vector, VectorAnimator>
public class VectorTransition : Transition<Vector>
{
internal override IObservable<Vector> DoTransition(IObservable<double> progress, Vector oldValue, Vector newValue) =>
AnimatorDrivenTransition<Vector, VectorAnimator>.Transition(Easing, progress, oldValue, newValue);
}
}

4
src/Avalonia.Base/AvaloniaLocator.cs

@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using Avalonia.Metadata;
#pragma warning disable CS1591 // Enable me later
namespace Avalonia
{
[PrivateApi]
public class AvaloniaLocator : IAvaloniaDependencyResolver
{
private readonly IAvaloniaDependencyResolver? _parentScope;
@ -114,11 +116,13 @@ namespace Avalonia
}
}
[PrivateApi]
public interface IAvaloniaDependencyResolver
{
object? GetService(Type t);
}
[PrivateApi]
public static class LocatorExtensions
{
public static T? GetService<T>(this IAvaloniaDependencyResolver resolver)

37
src/Avalonia.Base/Data/TemplateBinding.cs

@ -3,18 +3,21 @@ using System.Globalization;
using Avalonia.Data.Converters;
using Avalonia.Reactive;
using Avalonia.Styling;
using Avalonia.Threading;
namespace Avalonia.Data
{
/// <summary>
/// A XAML binding to a property on a control's templated parent.
/// </summary>
public class TemplateBinding : SingleSubscriberObservableBase<object?>,
public class TemplateBinding : IObservable<object?>,
IBinding,
IDescription,
IAvaloniaSubject<object?>,
ISetterValue
ISetterValue,
IDisposable
{
private IObserver<object?>? _observer;
private bool _isSetterValue;
private StyledElement? _target;
private Type? _targetType;
@ -29,6 +32,28 @@ namespace Avalonia.Data
Property = property;
}
public IDisposable Subscribe(IObserver<object?> observer)
{
_ = observer ?? throw new ArgumentNullException(nameof(observer));
Dispatcher.UIThread.VerifyAccess();
if (_observer != null)
{
throw new InvalidOperationException("The observable can only be subscribed once.");
}
_observer = observer;
Subscribed();
return this;
}
public virtual void Dispose()
{
Unsubscribed();
_observer = null;
}
/// <inheritdoc/>
public InstancedBinding? Initiate(
AvaloniaObject target,
@ -111,7 +136,7 @@ namespace Avalonia.Data
/// <inheritdoc/>
void ISetterValue.Initialize(SetterBase setter) => _isSetterValue = true;
protected override void Subscribed()
private void Subscribed()
{
TemplatedParentChanged();
@ -121,7 +146,7 @@ namespace Avalonia.Data
}
}
protected override void Unsubscribed()
private void Unsubscribed()
{
if (_target?.TemplatedParent is { } templatedParent)
{
@ -147,12 +172,12 @@ namespace Avalonia.Data
value = Converter.Convert(value, _targetType ?? typeof(object), ConverterParameter, CultureInfo.CurrentCulture);
}
PublishNext(value);
_observer?.OnNext(value);
_hasProducedValue = true;
}
else if (_hasProducedValue)
{
PublishNext(AvaloniaProperty.UnsetValue);
_observer?.OnNext(AvaloniaProperty.UnsetValue);
_hasProducedValue = false;
}
}

4
src/Avalonia.Base/Input/AccessKeyHandler.cs

@ -65,14 +65,14 @@ namespace Avalonia.Input
{
if (_mainMenu != null)
{
_mainMenu.MenuClosed -= MainMenuClosed;
_mainMenu.Closed -= MainMenuClosed;
}
_mainMenu = value;
if (_mainMenu != null)
{
_mainMenu.MenuClosed += MainMenuClosed;
_mainMenu.Closed += MainMenuClosed;
}
}
}

2
src/Avalonia.Base/Input/DragDropDevice.cs

@ -2,9 +2,11 @@
using Avalonia.VisualTree;
using System.Linq;
using Avalonia.Input.Raw;
using Avalonia.Metadata;
namespace Avalonia.Input
{
[PrivateApi]
public class DragDropDevice : IDragDropDevice
{
public static readonly DragDropDevice Instance = new DragDropDevice();

2
src/Avalonia.Base/Input/IInputDevice.cs

@ -3,7 +3,7 @@ using Avalonia.Metadata;
namespace Avalonia.Input
{
[NotClientImplementable]
[NotClientImplementable, PrivateApi]
public interface IInputDevice
{
/// <summary>

2
src/Avalonia.Base/Input/IInputManager.cs

@ -8,7 +8,7 @@ namespace Avalonia.Input
/// Receives input from the windowing subsystem and dispatches it to interested parties
/// for processing.
/// </summary>
[NotClientImplementable]
[NotClientImplementable, PrivateApi]
public interface IInputManager
{
/// <summary>

1
src/Avalonia.Base/Input/IKeyboardNavigationHandler.cs

@ -15,6 +15,7 @@ namespace Avalonia.Input
/// <remarks>
/// This method can only be called once, typically by the owner itself on creation.
/// </remarks>
[PrivateApi]
void SetOwner(IInputRoot owner);
/// <summary>

2
src/Avalonia.Base/Input/IMainMenu.cs

@ -26,6 +26,6 @@ namespace Avalonia.Input
/// <summary>
/// Occurs when the main menu closes.
/// </summary>
event EventHandler<RoutedEventArgs>? MenuClosed;
event EventHandler<RoutedEventArgs>? Closed;
}
}

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

Loading…
Cancel
Save