Merge branch 'develop' into feature/timeline

This commit is contained in:
liuyushuai 2024-10-16 00:06:53 +08:00
commit 0b639f3329
1044 changed files with 32028 additions and 7457 deletions

View File

@ -7,22 +7,33 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI.Theme", "src\AtomUI.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI.Base", "src\AtomUI.Base\AtomUI.Base.csproj", "{8FFEB15F-7E48-4AF4-B708-8E96A68CF2D9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI.Icon", "src\AtomUI.Icon\AtomUI.Icon.csproj", "{B2A7349B-4B38-45CB-8D22-3E06D1E3650F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI.Icon.Generator", "src\AtomUI.Icon.Generator\AtomUI.Icon.Generator.csproj", "{954FB7F2-7706-4E2B-86D1-624F66C1EFF0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI.Icon.AntDesign", "src\AtomUI.Icon.AntDesign\AtomUI.Icon.AntDesign.csproj", "{021AE0B0-B148-4925-9C22-EBD5A7B43E95}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI.Generator", "src\AtomUI.Generator\AtomUI.Generator.csproj", "{30910056-F8F6-4429-B25E-722C57440210}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI.Demo.Desktop", "Samples\AtomUI.Demo.Desktop\AtomUI.Demo.Desktop.csproj", "{59931F42-8DD8-4DFC-9060-563841F39669}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI.TestBase", "tests\AtomUI.TestBase\AtomUI.TestBase.csproj", "{EADEF2AC-B7E5-436A-8B39-8BBECF8706AB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI.Base.Tests", "tests\AtomUI.Base.Tests\AtomUI.Base.Tests.csproj", "{E41D737A-5CF0-4B33-9F51-2C1B1541659C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI.Controls", "src\AtomUI.Controls\AtomUI.Controls.csproj", "{A07CB66E-7A5F-4C44-BB16-02A0A99D6C2D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{279BC2C9-A818-4D6C-9274-678649932057}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Generators", "Generators", "{B4C46C3E-0CCC-4861-95B6-CA08D501A46F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI", "packages\AtomUI\AtomUI.csproj", "{89A98C0D-B6F7-48CD-91C4-79FC0FED3615}"
ProjectSection(ProjectDependencies) = postProject
{87085491-3C99-4C8F-8FA6-F179B9569CE8} = {87085491-3C99-4C8F-8FA6-F179B9569CE8}
{8FFEB15F-7E48-4AF4-B708-8E96A68CF2D9} = {8FFEB15F-7E48-4AF4-B708-8E96A68CF2D9}
{A07CB66E-7A5F-4C44-BB16-02A0A99D6C2D} = {A07CB66E-7A5F-4C44-BB16-02A0A99D6C2D}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AtomUI.Platform.Win32", "src\AtomUI.Platform.Win32\AtomUI.Platform.Win32.csproj", "{9BF7EF51-4100-4EAE-8A95-FC5F1BD4A1E4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AtomUI.IconPkg", "src\AtomUI.IconPkg\AtomUI.IconPkg.csproj", "{70AC4A1D-2D88-4703-9AB2-89E753E1A04B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AtomUI.IconPkg.AntDesign", "src\AtomUI.IconPkg.AntDesign\AtomUI.IconPkg.AntDesign.csproj", "{796AC3CF-7A12-4183-9096-291738A62292}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AtomUI.IconPkg.Generator", "src\AtomUI.IconPkg.Generator\AtomUI.IconPkg.Generator.csproj", "{C8BFCDBE-0DC2-411F-B2E4-439A0A8E1752}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{5EB2524C-30A5-4031-B424-4510E36C753E}"
ProjectSection(SolutionItems) = preProject
build\Common.props = build\Common.props
@ -37,19 +48,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{5EB2524C
build\Version.props = build\Version.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{279BC2C9-A818-4D6C-9274-678649932057}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Generators", "Generators", "{B4C46C3E-0CCC-4861-95B6-CA08D501A46F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI", "packages\AtomUI\AtomUI.csproj", "{89A98C0D-B6F7-48CD-91C4-79FC0FED3615}"
ProjectSection(ProjectDependencies) = postProject
{021AE0B0-B148-4925-9C22-EBD5A7B43E95} = {021AE0B0-B148-4925-9C22-EBD5A7B43E95}
{87085491-3C99-4C8F-8FA6-F179B9569CE8} = {87085491-3C99-4C8F-8FA6-F179B9569CE8}
{8FFEB15F-7E48-4AF4-B708-8E96A68CF2D9} = {8FFEB15F-7E48-4AF4-B708-8E96A68CF2D9}
{A07CB66E-7A5F-4C44-BB16-02A0A99D6C2D} = {A07CB66E-7A5F-4C44-BB16-02A0A99D6C2D}
{B2A7349B-4B38-45CB-8D22-3E06D1E3650F} = {B2A7349B-4B38-45CB-8D22-3E06D1E3650F}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -64,25 +62,10 @@ Global
{8FFEB15F-7E48-4AF4-B708-8E96A68CF2D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FFEB15F-7E48-4AF4-B708-8E96A68CF2D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FFEB15F-7E48-4AF4-B708-8E96A68CF2D9}.Release|Any CPU.Build.0 = Release|Any CPU
{B2A7349B-4B38-45CB-8D22-3E06D1E3650F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B2A7349B-4B38-45CB-8D22-3E06D1E3650F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2A7349B-4B38-45CB-8D22-3E06D1E3650F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B2A7349B-4B38-45CB-8D22-3E06D1E3650F}.Release|Any CPU.Build.0 = Release|Any CPU
{954FB7F2-7706-4E2B-86D1-624F66C1EFF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{954FB7F2-7706-4E2B-86D1-624F66C1EFF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{954FB7F2-7706-4E2B-86D1-624F66C1EFF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{954FB7F2-7706-4E2B-86D1-624F66C1EFF0}.Release|Any CPU.Build.0 = Release|Any CPU
{021AE0B0-B148-4925-9C22-EBD5A7B43E95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{021AE0B0-B148-4925-9C22-EBD5A7B43E95}.Debug|Any CPU.Build.0 = Debug|Any CPU
{021AE0B0-B148-4925-9C22-EBD5A7B43E95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{021AE0B0-B148-4925-9C22-EBD5A7B43E95}.Release|Any CPU.Build.0 = Release|Any CPU
{30910056-F8F6-4429-B25E-722C57440210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{30910056-F8F6-4429-B25E-722C57440210}.Debug|Any CPU.Build.0 = Debug|Any CPU
{30910056-F8F6-4429-B25E-722C57440210}.Release|Any CPU.ActiveCfg = Release|Any CPU
{30910056-F8F6-4429-B25E-722C57440210}.Release|Any CPU.Build.0 = Release|Any CPU
{59931F42-8DD8-4DFC-9060-563841F39669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59931F42-8DD8-4DFC-9060-563841F39669}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59931F42-8DD8-4DFC-9060-563841F39669}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EADEF2AC-B7E5-436A-8B39-8BBECF8706AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EADEF2AC-B7E5-436A-8B39-8BBECF8706AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EADEF2AC-B7E5-436A-8B39-8BBECF8706AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -96,14 +79,28 @@ Global
{89A98C0D-B6F7-48CD-91C4-79FC0FED3615}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{89A98C0D-B6F7-48CD-91C4-79FC0FED3615}.Debug|Any CPU.Build.0 = Debug|Any CPU
{89A98C0D-B6F7-48CD-91C4-79FC0FED3615}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BF7EF51-4100-4EAE-8A95-FC5F1BD4A1E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9BF7EF51-4100-4EAE-8A95-FC5F1BD4A1E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9BF7EF51-4100-4EAE-8A95-FC5F1BD4A1E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BF7EF51-4100-4EAE-8A95-FC5F1BD4A1E4}.Release|Any CPU.Build.0 = Release|Any CPU
{70AC4A1D-2D88-4703-9AB2-89E753E1A04B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70AC4A1D-2D88-4703-9AB2-89E753E1A04B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70AC4A1D-2D88-4703-9AB2-89E753E1A04B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70AC4A1D-2D88-4703-9AB2-89E753E1A04B}.Release|Any CPU.Build.0 = Release|Any CPU
{796AC3CF-7A12-4183-9096-291738A62292}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{796AC3CF-7A12-4183-9096-291738A62292}.Debug|Any CPU.Build.0 = Debug|Any CPU
{796AC3CF-7A12-4183-9096-291738A62292}.Release|Any CPU.ActiveCfg = Release|Any CPU
{796AC3CF-7A12-4183-9096-291738A62292}.Release|Any CPU.Build.0 = Release|Any CPU
{C8BFCDBE-0DC2-411F-B2E4-439A0A8E1752}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C8BFCDBE-0DC2-411F-B2E4-439A0A8E1752}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C8BFCDBE-0DC2-411F-B2E4-439A0A8E1752}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C8BFCDBE-0DC2-411F-B2E4-439A0A8E1752}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{954FB7F2-7706-4E2B-86D1-624F66C1EFF0} = {B4C46C3E-0CCC-4861-95B6-CA08D501A46F}
{30910056-F8F6-4429-B25E-722C57440210} = {B4C46C3E-0CCC-4861-95B6-CA08D501A46F}
{59931F42-8DD8-4DFC-9060-563841F39669} = {279BC2C9-A818-4D6C-9274-678649932057}
{EADEF2AC-B7E5-436A-8B39-8BBECF8706AB} = {279BC2C9-A818-4D6C-9274-678649932057}
{E41D737A-5CF0-4B33-9F51-2C1B1541659C} = {279BC2C9-A818-4D6C-9274-678649932057}
EndGlobalSection

View File

@ -6,37 +6,43 @@
<ItemGroup>
<PackageReference Include="Avalonia"/>
<PackageReference Include="Avalonia.Svg"/>
<PackageReference Include="Avalonia.Win32"/>
<PackageReference Include="System.Reactive"/>
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'DEBUG' ">
<ProjectReference Include="../../src/AtomUI.Base/AtomUI.Base.csproj" />
<ProjectReference Include="../../src/AtomUI.Controls/AtomUI.Controls.csproj" />
<ProjectReference Include="../../src/AtomUI.Icon/AtomUI.Icon.csproj" />
<ProjectReference Include="../../src/AtomUI.Icon.AntDesign/AtomUI.Icon.AntDesign.csproj" />
<ProjectReference Include="../../src/AtomUI.Theme/AtomUI.Theme.csproj" />
<ProjectReference Include="..\..\src\AtomUI.Base\AtomUI.Base.csproj" />
<ProjectReference Include="..\..\src\AtomUI.Controls\AtomUI.Controls.csproj" />
<ProjectReference Include="..\..\src\AtomUI.IconPkg\AtomUI.IconPkg.csproj" />
<ProjectReference Include="..\..\src\AtomUI.IconPkg.AntDesign\AtomUI.IconPkg.AntDesign.csproj" />
<ProjectReference Include="..\..\src\AtomUI.Theme\AtomUI.Theme.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'DEBUG' And $([MSBuild]::IsOSPlatform('Windows')) ">
<ProjectReference Include="..\..\src\AtomUI.Platform.Win32\AtomUI.Platform.Win32.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'RELEASE' ">
<Reference Include="../../_output/Bin/Release/AtomUI.Base.dll" />
<Reference Include="../../_output/Bin/Release/AtomUI.Controls.dll" />
<Reference Include="../../_output/Bin/Release/AtomUI.Icon.dll" />
<Reference Include="../../_output/Bin/Release/AtomUI.Icon.AntDesign.dll" />
<Reference Include="../../_output/Bin/Release/AtomUI.Theme.dll" />
<Reference Include="..\..\_output\Bin\Release\AtomUI.Base.dll" />
<Reference Include="..\..\_output\Bin\Release\AtomUI.Controls.dll" />
<Reference Include="..\..\_output\Bin\Release\AtomUI.IconPkg.dll" />
<Reference Include="..\..\_output\Bin\Release\AtomUI.IconPkg.AntDesign.dll" />
<Reference Include="..\..\_output\Bin\Release\AtomUI.Theme.dll" />
<Reference Include="..\..\_output\Bin\Release\AtomUI.Platform.Win32.dll" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'RELEASE' ">
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Base.dll" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Controls.dll" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Icon.dll" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Icon.AntDesign.dll" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Theme.dll" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Base.pdb" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Controls.dll" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Controls.pdb" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Icon.pdb" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Icon.AntDesign.pdb" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.IconPkg.dll" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.IconPkg.pdb" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.IconPkg.AntDesign.dll" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.IconPkg.AntDesign.pdb" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Theme.dll" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Theme.pdb" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Platform.Win32.dll" />
<Content Pack="true" Visible="false" PackagePath="lib\$(TargetFramework)" Include="$(MSBuildThisFileDirectory)..\..\_output\Bin\Release\AtomUI.Platform.Win32.pdb" />
</ItemGroup>
</Project>

View File

@ -18,4 +18,8 @@
<InternalsVisibleTo Include="AtomUI.Controls"/>
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::IsOSPlatform('Windows'))">
<ProjectReference Include="..\AtomUI.Platform.Win32\AtomUI.Platform.Win32.csproj" />
</ItemGroup>
</Project>

View File

@ -1,188 +1,73 @@
using System.Diagnostics;
using System.Reactive.Linq;
using AtomUI.Media;
using Avalonia;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Media.Transformation;
using Avalonia.Threading;
namespace AtomUI.MotionScene;
public enum TransitionKind
internal class AbstractMotion : IMotion
{
Double,
TransformOperations
}
public bool IsRunning { get; }
public record class MotionConfig
{
public AvaloniaProperty Property { get; set; }
public object? StartValue { get; set; }
public object? EndValue { get; set; }
public Easing MotionEasing { get; set; } = new LinearEasing();
public TimeSpan MotionDuration { get; set; } = TimeSpan.FromMilliseconds(300);
public TransitionKind TransitionKind { get; set; }
public RelativePoint RenderTransformOrigin { get; protected set; }
public IList<Animation> Animations { get; }
public TimeSpan Duration { get; }
public Easing Easing { get; }
public FillMode PropertyValueFillMode { get; }
public MotionConfig(AvaloniaProperty targetProperty, object? startValue = null, object? endValue = null)
public AbstractMotion(TimeSpan duration, Easing? easing = null, FillMode fillMode = FillMode.Forward)
{
Property = targetProperty;
StartValue = startValue;
EndValue = endValue;
}
}
public abstract class AbstractMotion : AvaloniaObject, IMotion
{
public bool IsRunning { get; } = false;
private readonly Dictionary<AvaloniaProperty, MotionConfig> _motionConfigs;
private readonly List<ITransition> _transitions;
public IObservable<bool>? CompletedObservable { get; private set; }
// 定义我们目前支持的动效属性
public static readonly StyledProperty<double> MotionOpacityProperty =
Visual.OpacityProperty.AddOwner<AbstractMotion>();
public static readonly StyledProperty<double> MotionWidthProperty =
Layoutable.WidthProperty.AddOwner<AbstractMotion>();
public static readonly StyledProperty<double> MotionHeightProperty =
Layoutable.HeightProperty.AddOwner<AbstractMotion>();
public static readonly StyledProperty<RelativePoint> MotionRenderTransformOriginProperty =
Visual.RenderTransformOriginProperty.AddOwner<AbstractMotion>();
public static readonly StyledProperty<ITransform?> MotionRenderTransformProperty =
Visual.RenderTransformProperty.AddOwner<AbstractMotion>();
protected double MotionOpacity
{
get => GetValue(MotionOpacityProperty);
set => SetValue(MotionOpacityProperty, value);
Animations = new List<Animation>();
Duration = duration;
Easing = easing ?? new LinearEasing();
PropertyValueFillMode = fillMode;
}
protected double MotionWidth
public async Task RunAsync(MotionActorControl actor,
Action? aboutToStart = null,
Action? completedAction = null,
CancellationToken cancellationToken = default)
{
get => GetValue(MotionWidthProperty);
set => SetValue(MotionWidthProperty, value);
}
protected double MotionHeight
{
get => GetValue(MotionHeightProperty);
set => SetValue(MotionHeightProperty, value);
}
internal RelativePoint MotionRenderTransformOrigin
{
get => GetValue(MotionRenderTransformOriginProperty);
set => SetValue(MotionRenderTransformOriginProperty, value);
}
protected ITransform? MotionRenderTransform
{
get => GetValue(MotionRenderTransformProperty);
set => SetValue(MotionRenderTransformProperty, value);
}
public AbstractMotion()
{
_motionConfigs = new Dictionary<AvaloniaProperty, MotionConfig>();
_transitions = new List<ITransition>();
}
/// <summary>
/// 创建动效动画对象
/// </summary>
/// <param name="motionTarget"></param>
/// <returns></returns>
internal List<ITransition> BuildTransitions(Control motionTarget)
{
foreach (var entry in _motionConfigs)
Configure();
await Dispatcher.UIThread.InvokeAsync(async () =>
{
var config = entry.Value;
NotifyPreBuildTransition(config, motionTarget);
var transition = NotifyBuildTransition(config);
_transitions.Add(transition);
}
var completedObservables = new IObservable<bool>[_transitions.Count];
for (var i = 0; i < _transitions.Count; ++i)
{
var transition = _transitions[i];
if (transition is INotifyTransitionCompleted notifyTransitionCompleted)
using var originRestore = new RenderTransformOriginRestore(actor);
actor.RenderTransformOrigin = RenderTransformOrigin;
actor.NotifyMotionPreStart();
NotifyPreStart();
if (aboutToStart is not null)
{
completedObservables[i] = notifyTransitionCompleted.CompletedObservable;
aboutToStart();
}
}
CompletedObservable =
Observable.CombineLatest(completedObservables).Select(list => { return list.All(v => v); });
return _transitions;
actor.IsVisible = true;
foreach (var animation in Animations)
{
await animation.RunAsync(actor, cancellationToken);
}
actor.NotifyMotionCompleted();
NotifyCompleted();
if (completedAction is not null)
{
completedAction();
}
});
}
// 生命周期接口
internal virtual void NotifyPreStart()
protected virtual void Configure()
{
}
internal virtual void NotifyStarted()
protected virtual void NotifyPreStart()
{
}
internal virtual void NotifyCompleted()
protected virtual void NotifyCompleted()
{
}
internal virtual void NotifyConfigMotionTarget(Control motionTarget)
{
}
internal virtual void NotifyRestoreMotionTarget(Control motionTarget)
{
}
protected virtual void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
}
protected virtual ITransition NotifyBuildTransition(MotionConfig config)
{
TransitionBase transition = default!;
if (config.TransitionKind == TransitionKind.Double)
{
transition = new NotifiableDoubleTransition();
}
else if (config.TransitionKind == TransitionKind.TransformOperations)
{
transition = new NotifiableTransformOperationsTransition();
}
transition.Property = config.Property;
transition.Duration = config.MotionDuration;
transition.Easing = config.MotionEasing;
return transition;
}
protected MotionConfig? GetMotionConfig(AvaloniaProperty property)
{
if (_motionConfigs.TryGetValue(property, out var motionConfig))
{
return motionConfig;
}
return null;
}
protected void AddMotionConfig(MotionConfig config)
{
Debug.Assert(!_motionConfigs.ContainsKey(config.Property));
_motionConfigs.Add(config.Property, config);
}
/// <summary>
/// 计算顶层动画渲染层的大小
/// </summary>
@ -208,42 +93,69 @@ public abstract class AbstractMotion : AvaloniaObject, IMotion
return motionTargetPosition;
}
public IList<AvaloniaProperty> GetActivatedProperties()
{
return _motionConfigs.Keys.ToList();
}
public IList<MotionConfig> GetMotionConfigs()
{
return _motionConfigs.Values.ToList();
}
protected TransformOperations BuildScaleTransform(double scaleX, double scaleY)
protected static TransformOperations BuildScaleTransform(double scaleX, double scaleY)
{
var builder = new TransformOperations.Builder(1);
builder.AppendScale(scaleX, scaleY);
return builder.Build();
}
protected TransformOperations BuildScaleTransform(double scale)
protected static TransformOperations BuildScaleTransform(double scale)
{
return BuildScaleTransform(scale, scale);
}
protected TransformOperations BuildScaleXTransform(double scale)
protected static TransformOperations BuildScaleXTransform(double scale)
{
return BuildScaleTransform(scale, 1.0);
}
protected TransformOperations BuildScaleYTransform(double scale)
protected static TransformOperations BuildScaleYTransform(double scale)
{
return BuildScaleTransform(1.0, scale);
}
protected TransformOperations BuildTranslateTransform(double offsetX, double offsetY)
protected static TransformOperations BuildTranslateTransform(double offsetX, double offsetY)
{
var builder = new TransformOperations.Builder(1);
builder.AppendTranslate(offsetX, offsetY);
return builder.Build();
}
protected static TransformOperations BuildTranslateScaleAndTransform(
double scaleX, double scaleY, double offsetX, double offsetY)
{
var builder = new TransformOperations.Builder(2);
builder.AppendScale(scaleX, scaleY);
builder.AppendTranslate(offsetX, offsetY);
return builder.Build();
}
protected Animation CreateAnimation()
{
var animation = new Animation
{
Duration = Duration,
Easing = Easing,
FillMode = PropertyValueFillMode
};
return animation;
}
}
internal class RenderTransformOriginRestore : IDisposable
{
RelativePoint _origin;
Control _target;
public RenderTransformOriginRestore(Control target)
{
_target = target;
_origin = target.RenderTransformOrigin;
}
public void Dispose()
{
_target.RenderTransformOrigin = _origin;
}
}

View File

@ -1,139 +0,0 @@
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Layout;
namespace AtomUI.MotionScene;
public class CollapseMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? HeightConfig => GetMotionConfig(MotionHeightProperty);
/// <summary>
/// 收起的方向,垂直还是水平方向
/// </summary>
public Orientation Orientation { get; set; } = Orientation.Vertical;
public void ConfigureHeight(TimeSpan duration, Easing? easing = null)
{
easing ??= new CubicEaseInOut();
var config = new MotionConfig(Orientation == Orientation.Vertical
? MotionHeightProperty
: MotionWidthProperty)
{
TransitionKind = TransitionKind.Double,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CubicEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
protected override void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
base.NotifyPreBuildTransition(config, motionTarget);
if (config.Property == MotionHeightProperty)
{
if (!double.IsNaN(motionTarget.Height))
{
config.StartValue = Math.Ceiling(motionTarget.Height);
}
else
{
config.StartValue = Math.Ceiling(motionTarget.DesiredSize.Height);
}
}
else if (config.Property == MotionWidthProperty)
{
if (!double.IsNaN(motionTarget.Width))
{
config.StartValue = Math.Ceiling(motionTarget.Width);
}
else
{
config.StartValue = Math.Ceiling(motionTarget.DesiredSize.Width);
}
}
}
}
public class ExpandMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? HeightConfig => GetMotionConfig(MotionHeightProperty);
/// <summary>
/// 展开的方向,垂直还是水平方向
/// </summary>
public Orientation Orientation { get; set; } = Orientation.Vertical;
public void ConfigureHeight(TimeSpan duration, Easing? easing = null)
{
easing ??= new CubicEaseInOut();
var config = new MotionConfig(Orientation == Orientation.Vertical
? MotionHeightProperty
: MotionWidthProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CubicEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
protected override void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
base.NotifyPreBuildTransition(config, motionTarget);
if (config.Property == MotionHeightProperty)
{
if (!double.IsNaN(motionTarget.Height))
{
config.EndValue = Math.Ceiling(motionTarget.Height);
}
else
{
config.EndValue = Math.Ceiling(motionTarget.DesiredSize.Height);
}
}
else if (config.Property == MotionWidthProperty)
{
if (!double.IsNaN(motionTarget.Width))
{
config.EndValue = Math.Ceiling(motionTarget.Width);
}
else
{
config.EndValue = Math.Ceiling(motionTarget.DesiredSize.Width);
}
}
}
}

View File

@ -5,21 +5,23 @@ using Avalonia.Styling;
namespace AtomUI.MotionScene;
internal static partial class MotionFactory
internal class CollapseMotion : AbstractMotion
{
public static MotionConfigX BuildCollapseMotion(Direction direction, TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
public Direction Direction { get; }
public CollapseMotion(Direction direction,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CubicEaseOut(), fillMode)
{
easing ??= new CubicEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var isHorizontal = direction == Direction.Left || direction == Direction.Right;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
Direction = direction;
}
protected override void Configure()
{
var isHorizontal = Direction == Direction.Left || Direction == Direction.Right;
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
@ -85,41 +87,44 @@ internal static partial class MotionFactory
}
animation.Children.Add(endFrame);
if (direction == Direction.Left)
if (Direction == Direction.Left)
{
transformOrigin = new RelativePoint(1, 0.5, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(1, 0.5, RelativeUnit.Relative);
}
else if (direction == Direction.Right)
else if (Direction == Direction.Right)
{
transformOrigin = new RelativePoint(0, 0.5, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0, 0.5, RelativeUnit.Relative);
}
else if (direction == Direction.Top)
else if (Direction == Direction.Top)
{
transformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
}
else
{
transformOrigin = new RelativePoint(0.5, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.5, 0.0, RelativeUnit.Relative);
}
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
internal class ExpandMotion : AbstractMotion
{
public Direction Direction { get; }
public ExpandMotion(Direction direction,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CubicEaseIn(), fillMode)
{
Direction = direction;
}
public static MotionConfigX BuildExpandMotion(Direction direction, TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new CubicEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var isHorizontal = direction == Direction.Left || direction == Direction.Right;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var isHorizontal = Direction == Direction.Left || Direction == Direction.Right;
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -185,24 +190,23 @@ internal static partial class MotionFactory
animation.Children.Add(endFrame);
if (direction == Direction.Left)
if (Direction == Direction.Left)
{
transformOrigin = new RelativePoint(1.0, 0.5, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(1.0, 0.5, RelativeUnit.Relative);
}
else if (direction == Direction.Right)
else if (Direction == Direction.Right)
{
transformOrigin = new RelativePoint(0.0, 0.5, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.0, 0.5, RelativeUnit.Relative);
}
else if (direction == Direction.Top)
else if (Direction == Direction.Top)
{
transformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
}
else
{
transformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
}
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}

View File

@ -1,172 +0,0 @@
using System.Reactive.Disposables;
using AtomUI.MotionScene;
using Avalonia;
using Avalonia.Threading;
namespace AtomUI.Controls.MotionScene;
public class Director : IDirector
{
public event EventHandler<MotionEventArgs>? MotionPreStart;
public event EventHandler<MotionEventArgs>? MotionStarted;
public event EventHandler<MotionEventArgs>? MotionCompleted;
public static IDirector? Instance => AvaloniaLocator.Current.GetService<IDirector>();
private readonly Dictionary<IMotionActor, MotionActorState> _states;
private CompositeDisposable? _compositeDisposable;
public Director()
{
_states = new Dictionary<IMotionActor, MotionActorState>();
}
/// <summary>
/// 目前的实现暂时一个 Actor 只能投递一次,后面可以实现一个等待队列
/// </summary>
/// <param name="actor"></param>
public void Schedule(MotionActor actor)
{
if (_states.ContainsKey(actor))
{
return;
}
actor.NotifyPostedToDirector();
SceneLayer? sceneLayer = default;
if (actor.DispatchInSceneLayer)
{
sceneLayer = PrepareSceneLayer(actor);
}
_compositeDisposable = new CompositeDisposable();
_compositeDisposable.Add(Disposable.Create(sceneLayer, state =>
{
if (sceneLayer is not null)
{
Dispatcher.UIThread.InvokeAsync(async () =>
{
await Task.Delay(300);
sceneLayer.Hide();
sceneLayer.Dispose();
});
}
}));
var state = new MotionActorState(actor, _compositeDisposable);
_states.Add(actor, state);
if (actor.DispatchInSceneLayer)
{
state.SceneLayer = sceneLayer;
var ghost = actor.GetAnimatableGhost();
sceneLayer!.SetMotionTarget(ghost);
actor.NotifyMotionTargetAddedToScene(ghost);
sceneLayer.Show();
sceneLayer.Topmost = true;
actor.NotifySceneShowed();
}
HandleMotionPreStart(actor);
ExecuteMotionAction(actor);
HandleMotionStarted(actor);
}
private SceneLayer PrepareSceneLayer(MotionActor actor)
{
if (actor.SceneParent is null)
{
throw new ArgumentException(
"When the DispatchInSceneLayer property is true, the SceneParent property cannot be null.");
}
// TODO 这里除了 Popup 这种顶层元素以外,还会不会有其他的顶层元素种类
// 暂时先处理 Popup 这种情况
var sceneLayer = new SceneLayer(actor.SceneParent, actor.SceneParent.PlatformImpl!.CreatePopup()!);
actor.NotifySceneLayerCreated(sceneLayer);
return sceneLayer;
}
private void ExecuteMotionAction(MotionActor actor)
{
// 根据 Motion 配置的对 Actor 对象的属性赋值
actor.EnableMotion();
foreach (var motionConfig in actor.Motion.GetMotionConfigs())
{
var property = motionConfig.Property;
var endValue = motionConfig.EndValue;
actor.SetValue(property, endValue);
}
}
private class MotionActorState : IDisposable
{
private readonly IDisposable _cleanup;
public IMotionActor MotionActor { get; }
public SceneLayer? SceneLayer;
public MotionActorState(IMotionActor motionActor, IDisposable cleanup)
{
MotionActor = motionActor;
_cleanup = cleanup;
}
public void Dispose()
{
_cleanup.Dispose();
}
}
private void HandleMotionPreStart(MotionActor actor)
{
actor.NotifyMotionPreStart();
MotionPreStart?.Invoke(this, new MotionEventArgs(actor));
if (actor.Motion.CompletedObservable is null)
{
throw new InvalidOperationException("The CompletedObservable property of the Motion is empty.");
}
// 设置相关的完成检测
_compositeDisposable?.Add(actor.Motion.CompletedObservable.Subscribe(
status => { actor.CompletedStatus = status; }, () => { HandleMotionCompleted(actor); }));
// 设置动画对象初始值
foreach (var motionConfig in actor.Motion.GetMotionConfigs())
{
var property = motionConfig.Property;
var startValue = motionConfig.StartValue;
actor.SetValue(property, startValue);
}
}
private void HandleMotionStarted(MotionActor actor)
{
actor.NotifyMotionStarted();
MotionStarted?.Invoke(this, new MotionEventArgs(actor));
}
private void HandleMotionCompleted(MotionActor actor)
{
if (_states.TryGetValue(actor, out var state))
{
if (state.SceneLayer is not null)
{
state.SceneLayer.Opacity = 0;
}
actor.NotifyMotionCompleted();
MotionCompleted?.Invoke(this, new MotionEventArgs(actor));
state.Dispose();
_states.Remove(actor);
}
}
}
public class MotionEventArgs : EventArgs
{
public MotionActor MotionActor;
public MotionEventArgs(MotionActor motionActor)
{
MotionActor = motionActor;
}
}

View File

@ -1,43 +0,0 @@
using Avalonia.Animation.Easings;
namespace AtomUI.MotionScene;
public class FadeInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public void ConfigureOpacity(double originOpacity, TimeSpan duration, Easing? easing = null)
{
easing ??= new LinearEasing();
originOpacity = Math.Clamp(originOpacity, 0d, 1d);
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = originOpacity,
EndValue = 1.0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
}
public class FadeOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public void ConfigureOpacity(double originOpacity, TimeSpan duration, Easing? easing = null)
{
easing ??= new LinearEasing();
originOpacity = Math.Clamp(originOpacity, 0d, 1d);
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = originOpacity,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
}

View File

@ -0,0 +1,96 @@
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Styling;
namespace AtomUI.MotionScene;
internal class FadeInMotion : AbstractMotion
{
public FadeInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new LinearEasing(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
startFrame.Setters.Add(opacitySetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
endFrame.Setters.Add(opacitySetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class FadeOutMotion : AbstractMotion
{
public FadeOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new LinearEasing(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
startFrame.Setters.Add(opacitySetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
endFrame.Setters.Add(opacitySetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}

View File

@ -1,6 +0,0 @@
namespace AtomUI.MotionScene;
public interface IDirector
{
public void Schedule(MotionActor actor);
}

View File

@ -1,17 +1,20 @@
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
namespace AtomUI.MotionScene;
public interface IMotion
internal interface IMotion
{
public bool IsRunning { get; }
public RelativePoint RenderTransformOrigin { get; }
public IList<Animation> Animations { get; }
public TimeSpan Duration { get; }
public Easing Easing { get; }
public FillMode PropertyValueFillMode { get; }
/// <summary>
/// 获取当前动效激活的动画属性列表
/// </summary>
/// <returns></returns>
public IList<AvaloniaProperty> GetActivatedProperties();
public IList<MotionConfig> GetMotionConfigs();
public IObservable<bool>? CompletedObservable { get; }
public Task RunAsync(MotionActorControl actor,
Action? aboutToStart = null,
Action? completedAction = null,
CancellationToken cancellationToken = default);
}

View File

@ -1,16 +0,0 @@
using Avalonia.Controls;
namespace AtomUI.MotionScene;
internal interface IMotionActor
{
public event EventHandler? PreStart;
public event EventHandler? Started;
public event EventHandler? Completed;
public bool CompletedStatus { get; }
public Control MotionTarget { get; set; }
public IMotion Motion { get; }
public bool DispatchInSceneLayer { get; set; }
}

View File

@ -3,4 +3,5 @@
internal interface INotifyCaptureGhostBitmap
{
public void NotifyCaptureGhostBitmap();
public void NotifyClearGhostBitmap();
}

View File

@ -1,393 +0,0 @@
using System.Reflection;
using AtomUI.Media;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.VisualTree;
namespace AtomUI.MotionScene;
/// <summary>
/// 动效配置类,只要给 Director 提供动效相关信息
/// 动效驱动 Actor 的属性,然后由 Actor 驱动动画控件,防止污染动画控件的 Transitions 配置
/// </summary>
public class MotionActor : Animatable, IMotionActor
{
public event EventHandler? PreStart;
public event EventHandler? Started;
public event EventHandler? Completed;
public event EventHandler? SceneShowed;
public static readonly StyledProperty<double> MotionOpacityProperty =
Visual.OpacityProperty.AddOwner<MotionActor>();
public static readonly StyledProperty<double> MotionWidthProperty =
Layoutable.WidthProperty.AddOwner<MotionActor>();
public static readonly StyledProperty<double> MotionHeightProperty =
Layoutable.HeightProperty.AddOwner<MotionActor>();
public static readonly StyledProperty<ITransform?> MotionRenderTransformProperty =
Visual.RenderTransformProperty.AddOwner<MotionActor>();
private static readonly MethodInfo EnableTransitionsMethodInfo;
private static readonly MethodInfo DisableTransitionsMethodInfo;
public bool CompletedStatus { get; internal set; } = true;
protected double MotionOpacity
{
get => GetValue(MotionOpacityProperty);
set => SetValue(MotionOpacityProperty, value);
}
protected double MotionWidth
{
get => GetValue(MotionWidthProperty);
set => SetValue(MotionWidthProperty, value);
}
protected double MotionHeight
{
get => GetValue(MotionHeightProperty);
set => SetValue(MotionHeightProperty, value);
}
protected ITransform? MotionRenderTransform
{
get => GetValue(MotionRenderTransformProperty);
set => SetValue(MotionRenderTransformProperty, value);
}
private double _originOpacity;
private double _originWidth;
private double _originHeight;
private ITransform? _originRenderTransform;
private RelativePoint _originRenderTransformOrigin;
private readonly Dictionary<AvaloniaProperty, AnimationState> _transitionsMap;
private class AnimationState
{
public ITransition? Transition { get; set; }
public object? StartValue { get; set; }
public object? EndValue { get; set; }
}
/// <summary>
/// 动画实体
/// </summary>
public Control MotionTarget { get; set; }
/// <summary>
/// 当 DispatchInSceneLayer 为 true 的时候,必须指定一个动画 SceneLayer 的父窗口,最好不要是 Popup
/// </summary>
public TopLevel? SceneParent { get; set; }
public IMotion Motion => _motion;
public bool DispatchInSceneLayer { get; set; } = true;
protected Control? _ghost;
protected AbstractMotion _motion;
static MotionActor()
{
EnableTransitionsMethodInfo =
typeof(Animatable).GetMethod("EnableTransitions", BindingFlags.Instance | BindingFlags.NonPublic)!;
DisableTransitionsMethodInfo =
typeof(Animatable).GetMethod("DisableTransitions", BindingFlags.Instance | BindingFlags.NonPublic)!;
MotionWidthProperty.Changed.AddClassHandler<MotionActor>(HandlePropertyChanged);
MotionHeightProperty.Changed.AddClassHandler<MotionActor>(HandlePropertyChanged);
MotionOpacityProperty.Changed.AddClassHandler<MotionActor>(HandlePropertyChanged);
MotionRenderTransformProperty.Changed.AddClassHandler<MotionActor>(HandlePropertyChanged);
}
private static void HandlePropertyChanged(MotionActor actor, AvaloniaPropertyChangedEventArgs args)
{
var property = args.Property;
var oldValue = args.OldValue;
var newValue = args.NewValue;
var priority = args.Priority;
if (!actor._transitionsMap.ContainsKey(property))
{
return;
}
var state = actor._transitionsMap[property];
if (actor.IsAnimating(property) && priority == BindingPriority.Animation)
{
// 判断新值是否相等
if (property.PropertyType == typeof(double))
{
var currentValue = (double)newValue!;
var endValue = (double)state.EndValue!;
if (MathUtils.AreClose(currentValue, endValue))
{
var transition = state.Transition;
if (transition is INotifyTransitionCompleted notifyTransitionCompleted)
{
notifyTransitionCompleted.NotifyTransitionCompleted(true);
}
}
}
else if (property.PropertyType.IsAssignableTo(typeof(ITransform)))
{
var currentValue = (ITransform)newValue!;
var endValue = (ITransform)state.EndValue!;
if (currentValue.Value == endValue.Value)
{
var transition = state.Transition;
if (transition is INotifyTransitionCompleted notifyTransitionCompleted)
{
notifyTransitionCompleted.NotifyTransitionCompleted(true);
}
}
}
}
}
public MotionActor(Control motionTarget, AbstractMotion motion)
{
MotionTarget = motionTarget;
_motion = motion;
_transitionsMap = new Dictionary<AvaloniaProperty, AnimationState>();
}
public bool IsSupportMotionProperty(AvaloniaProperty property)
{
if (property == AbstractMotion.MotionOpacityProperty ||
property == AbstractMotion.MotionWidthProperty ||
property == AbstractMotion.MotionHeightProperty ||
property == AbstractMotion.MotionRenderTransformProperty)
{
return true;
}
return false;
}
protected virtual void BuildGhost()
{
}
public Control GetAnimatableGhost()
{
return _ghost ?? MotionTarget;
}
/// <summary>
/// 当在 DispatchInSceneLayer 渲染的时候Ghost 的全局坐标
/// </summary>
/// <returns></returns>
public Point CalculateGhostPosition()
{
Point point = default;
if (!DispatchInSceneLayer)
{
var visualParent = MotionTarget.GetVisualParent();
if (visualParent is not null)
{
var parentPoint = MotionTarget.TranslatePoint(new Point(0, 0), visualParent);
if (parentPoint.HasValue)
{
point = parentPoint.Value;
}
else
{
point = MotionTarget.Bounds.Position;
}
}
}
else
{
point = CalculateTopLevelGhostPosition();
}
return point;
}
protected virtual Point CalculateTopLevelGhostPosition()
{
return default;
}
/// <summary>
/// 在这个接口中Actor 根据自己的需求对 sceneLayer 进行设置,主要就是位置和大小
/// </summary>
/// <param name="sceneLayer"></param>
public virtual void NotifySceneLayerCreated(SceneLayer sceneLayer)
{
if (!DispatchInSceneLayer)
{
return;
}
var ghost = GetAnimatableGhost();
Size motionTargetSize;
// Popup.Child can't be null here, it was set in ShowAtCore.
if (ghost.DesiredSize == default)
{
// Popup may not have been shown yet. Measure content
motionTargetSize = LayoutHelper.MeasureChild(ghost, Size.Infinity, new Thickness());
}
else
{
motionTargetSize = ghost.DesiredSize;
}
var sceneSize = _motion.CalculateSceneSize(motionTargetSize);
var scenePosition = _motion.CalculateScenePosition(motionTargetSize, CalculateGhostPosition());
sceneLayer.MoveAndResize(scenePosition, sceneSize);
}
public virtual void NotifyPostedToDirector()
{
DisableMotion();
BuildGhost();
var transitions = new Transitions();
foreach (var transition in _motion.BuildTransitions(GetAnimatableGhost()))
{
transitions.Add(transition);
}
Transitions = transitions;
}
/// <summary>
/// 当动画目标控件被添加到动画场景中之后调用,这里需要根据 Motion 的种类设置初始位置和大小
/// </summary>
/// <param name="motionTarget"></param>
public virtual void NotifyMotionTargetAddedToScene(Control motionTarget)
{
Canvas.SetLeft(motionTarget, 0);
Canvas.SetTop(motionTarget, 0);
}
public virtual void NotifySceneShowed()
{
SceneShowed?.Invoke(this, EventArgs.Empty);
}
internal void EnableMotion()
{
EnableTransitionsMethodInfo.Invoke(this, new object[] { });
}
internal void DisableMotion()
{
DisableTransitionsMethodInfo.Invoke(this, new object[] { });
}
internal virtual void NotifyMotionPreStart()
{
if (Transitions is not null)
{
foreach (var transition in Transitions)
{
_transitionsMap.Add(transition.Property, new AnimationState
{
Transition = transition
});
}
}
foreach (var motionConfig in _motion.GetMotionConfigs())
{
var property = motionConfig.Property;
var state = _transitionsMap[property];
state.StartValue = motionConfig.StartValue;
state.EndValue = motionConfig.EndValue;
}
SaveMotionTargetState();
_motion.NotifyPreStart();
_motion.NotifyConfigMotionTarget(GetAnimatableGhost());
PreStart?.Invoke(this, EventArgs.Empty);
}
internal virtual void NotifyMotionStarted()
{
_motion.NotifyStarted();
Started?.Invoke(this, EventArgs.Empty);
}
internal virtual void NotifyMotionCompleted()
{
RestoreMotionTargetState();
Completed?.Invoke(this, EventArgs.Empty);
_motion.NotifyCompleted();
_motion.NotifyRestoreMotionTarget(GetAnimatableGhost());
_transitionsMap.Clear();
}
private void SaveMotionTargetState()
{
var target = GetAnimatableGhost();
foreach (var motionConfig in _motion.GetMotionConfigs())
{
if (motionConfig.Property == MotionHeightProperty)
{
_originHeight = target.Height;
}
else if (motionConfig.Property == MotionWidthProperty)
{
_originWidth = target.Width;
}
else if (motionConfig.Property == MotionOpacityProperty)
{
_originOpacity = target.Opacity;
}
else if (motionConfig.Property == MotionRenderTransformProperty)
{
_originRenderTransform = target.RenderTransform;
_originRenderTransformOrigin = target.RenderTransformOrigin;
}
}
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == MotionWidthProperty ||
change.Property == MotionHeightProperty ||
change.Property == MotionOpacityProperty ||
change.Property == MotionRenderTransformProperty)
{
var ghost = GetAnimatableGhost();
ghost.SetCurrentValue(change.Property, change.NewValue);
}
}
private void RestoreMotionTargetState()
{
var target = GetAnimatableGhost();
if (target == MotionTarget)
{
foreach (var motionConfig in _motion.GetMotionConfigs())
{
if (motionConfig.Property == MotionHeightProperty)
{
target.SetValue(MotionHeightProperty, _originHeight);
}
else if (motionConfig.Property == MotionWidthProperty)
{
target.SetValue(MotionWidthProperty, _originWidth);
}
else if (motionConfig.Property == MotionOpacityProperty)
{
target.SetValue(MotionOpacityProperty, _originOpacity);
}
else if (motionConfig.Property == MotionRenderTransformProperty)
{
target.SetValue(MotionRenderTransformProperty, _originRenderTransform);
target.SetValue(MotionRenderTransformProperty, _originRenderTransform);
target.SetValue(Visual.RenderTransformOriginProperty, _originRenderTransformOrigin);
}
}
}
}
}

View File

@ -6,13 +6,13 @@ using Avalonia.Media.Transformation;
namespace AtomUI.MotionScene;
public class MotionActorControl : Decorator
internal class MotionActorControl : Decorator
{
#region
public static readonly StyledProperty<TransformOperations?> MotionTransformProperty =
AvaloniaProperty.Register<MotionActorControl, TransformOperations?>(nameof(MotionTransform));
public static readonly StyledProperty<bool> UseRenderTransformProperty =
AvaloniaProperty.Register<LayoutTransformControl, bool>(nameof(UseRenderTransform));
@ -27,11 +27,18 @@ public class MotionActorControl : Decorator
get => GetValue(UseRenderTransformProperty);
set => SetValue(UseRenderTransformProperty, value);
}
public Control? MotionTransformRoot => Child;
#endregion
#region
public event EventHandler? PreStart;
public event EventHandler? Completed;
#endregion
/// <summary>
/// RenderTransform/MatrixTransform applied to MotionTransformRoot.
/// </summary>
@ -58,6 +65,11 @@ public class MotionActorControl : Decorator
/// Actual DesiredSize of Child element (the value it returned from its MeasureOverride method).
/// </summary>
private Size _childActualSize;
/// <summary>
/// 动画是否在
/// </summary>
private bool _animating = false;
static MotionActorControl()
{
@ -96,6 +108,7 @@ public class MotionActorControl : Decorator
MotionTransformRoot.RenderTransform = _matrixTransform;
MotionTransformRoot.RenderTransformOrigin = new RelativePoint(0, 0, RelativeUnit.Absolute);
}
ApplyMotionTransform();
}
@ -116,7 +129,7 @@ public class MotionActorControl : Decorator
{
return;
}
_transformation = matrix;
_matrixTransform.Matrix = UseRenderTransform ? matrix : FilterScaleTransform(matrix);
RenderTransform = _matrixTransform;
@ -162,7 +175,7 @@ public class MotionActorControl : Decorator
// Determine the largest available size after the transformation
Size finalSizeTransformed = ComputeLargestTransformedSize(finalSize);
if (IsSizeSmaller(finalSizeTransformed, MotionTransformRoot.DesiredSize))
{
// Some elements do not like being given less space than they asked for (ex: TextBlock)
@ -211,7 +224,7 @@ public class MotionActorControl : Decorator
return base.MeasureOverride(availableSize);
}
Size measureSize ;
Size measureSize;
if (_childActualSize == default)
{
// Determine the largest size after the transformation
@ -224,7 +237,7 @@ public class MotionActorControl : Decorator
}
// Perform a measure on the MotionTransformRoot (containing Child)
if (MotionTransformRoot.DesiredSize == default)
if (MotionTransformRoot.DesiredSize == default || _animating == false)
{
MotionTransformRoot.Measure(measureSize);
}
@ -393,4 +406,17 @@ public class MotionActorControl : Decorator
{
return (a.Width + AcceptableDelta < b.Width) || (a.Height + AcceptableDelta < b.Height);
}
internal virtual void NotifyMotionPreStart()
{
PreStart?.Invoke(this, EventArgs.Empty);
_animating = true;
}
internal virtual void NotifyMotionCompleted()
{
_animating = false;
InvalidateMeasure();
Completed?.Invoke(this, EventArgs.Empty);
}
}

View File

@ -1,57 +0,0 @@
using Avalonia;
using Avalonia.Animation;
using Avalonia.Media.Transformation;
namespace AtomUI.MotionScene;
internal record MotionConfigX
{
public RelativePoint RenderTransformOrigin { get; }
public IList<Animation> Animations { get; }
public MotionConfigX(RelativePoint renderTransformOrigin, IList<Animation> animations)
{
RenderTransformOrigin = renderTransformOrigin;
Animations = animations;
}
}
internal static partial class MotionFactory
{
public static TransformOperations BuildScaleTransform(double scaleX, double scaleY)
{
var builder = new TransformOperations.Builder(1);
builder.AppendScale(scaleX, scaleY);
return builder.Build();
}
public static TransformOperations BuildScaleTransform(double scale)
{
return BuildScaleTransform(scale, scale);
}
public static TransformOperations BuildScaleXTransform(double scale)
{
return BuildScaleTransform(scale, 1.0);
}
public static TransformOperations BuildScaleYTransform(double scale)
{
return BuildScaleTransform(1.0, scale);
}
public static TransformOperations BuildTranslateTransform(double offsetX, double offsetY)
{
var builder = new TransformOperations.Builder(1);
builder.AppendTranslate(offsetX, offsetY);
return builder.Build();
}
public static TransformOperations BuildTranslateScaleAndTransform(double scaleX, double scaleY, double offsetX, double offsetY)
{
var builder = new TransformOperations.Builder(2);
builder.AppendScale(scaleX, scaleY);
builder.AppendTranslate(offsetX, offsetY);
return builder.Build();
}
}

View File

@ -1,52 +1,90 @@
using Avalonia;
using Avalonia.Controls;
using System.Reactive.Disposables;
using Avalonia.Threading;
namespace AtomUI.MotionScene;
internal static class MotionInvoker
{
public static void Invoke(MotionActorControl target,
MotionConfigX motionConfig,
public static void Invoke(MotionActorControl actor,
AbstractMotion motion,
Action? aboutToStart = null,
Action? completedAction = null,
CancellationToken cancellationToken = default)
{
Dispatcher.UIThread.InvokeAsync(async () =>
Dispatcher.UIThread.Invoke(async () =>
{
using var originRestore = new RenderTransformOriginRestore(target);
target.RenderTransformOrigin = motionConfig.RenderTransformOrigin;
if (aboutToStart != null)
{
aboutToStart();
}
await motion.RunAsync(actor, aboutToStart, completedAction, cancellationToken);
});
}
foreach (var animation in motionConfig.Animations)
{
await animation.RunAsync(target, cancellationToken);
}
public static async Task InvokeAsync(MotionActorControl actor,
AbstractMotion motion,
Action? aboutToStart = null,
Action? completedAction = null,
CancellationToken cancellationToken = default)
{
await motion.RunAsync(actor, aboutToStart, completedAction, cancellationToken);
}
if (completedAction != null)
public static void InvokeInPopupLayer(SceneMotionActorControl actor,
AbstractMotion motion,
Action? aboutToStart = null,
Action? completedAction = null,
CancellationToken cancellationToken = default)
{
Dispatcher.UIThread.Invoke(async () =>
{
await InvokeInPopupLayerAsync(actor, motion, aboutToStart, completedAction, cancellationToken);
});
}
public static async Task InvokeInPopupLayerAsync(SceneMotionActorControl actor,
AbstractMotion motion,
Action? aboutToStart = null,
Action? completedAction = null,
CancellationToken cancellationToken = default)
{
actor.BuildGhost();
SceneLayer sceneLayer = PrepareSceneLayer(motion, actor);
var compositeDisposable = new CompositeDisposable();
compositeDisposable.Add(Disposable.Create(sceneLayer, (state) =>
{
Dispatcher.UIThread.Invoke(async () =>
{
await Task.Delay(300);
sceneLayer.Hide();
sceneLayer.Dispose();
});
}));
sceneLayer.SetMotionActor(actor);
actor.NotifyMotionTargetAddedToScene();
sceneLayer.Show();
sceneLayer.Topmost = true;
actor.NotifySceneShowed();
actor.IsVisible = false;
await motion.RunAsync(actor, aboutToStart, () =>
{
compositeDisposable.Dispose();
if (completedAction is not null)
{
completedAction();
}
});
}
}
internal class RenderTransformOriginRestore : IDisposable
{
RelativePoint _origin;
Control _target;
public RenderTransformOriginRestore(Control target)
{
_target = target;
_origin = target.RenderTransformOrigin;
}, cancellationToken);
}
public void Dispose()
private static SceneLayer PrepareSceneLayer(AbstractMotion motion, SceneMotionActorControl actor)
{
_target.RenderTransformOrigin = _origin;
if (actor.SceneParent is null)
{
throw new ArgumentException(
"When the DispatchInSceneLayer property is true, the SceneParent property cannot be null.");
}
// TODO 这里除了 Popup 这种顶层元素以外,还会不会有其他的顶层元素种类
// 暂时先处理 Popup 这种情况
var sceneLayer = new SceneLayer(actor.SceneParent, actor.SceneParent.PlatformImpl!.CreatePopup()!);
actor.NotifySceneLayerCreated(motion, sceneLayer);
return sceneLayer;
}
}

View File

@ -1,407 +0,0 @@
using Avalonia;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
namespace AtomUI.MotionScene;
public class MoveDownInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
EndValue = BuildTranslateTransform(0, 0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
protected override void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
base.NotifyPreBuildTransition(config, motionTarget);
if (config.Property == MotionRenderTransformProperty)
{
config.StartValue = BuildTranslateTransform(0, -motionTarget.DesiredSize.Height);
}
}
internal override Size CalculateSceneSize(Size motionTargetSize)
{
return motionTargetSize.WithHeight(motionTargetSize.Height * 2);
}
internal override Point CalculateScenePosition(Size motionTargetSize, Point motionTargetPosition)
{
return motionTargetPosition.WithY(motionTargetPosition.Y - motionTargetSize.Height);
}
}
public class MoveDownOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildTranslateTransform(0, 0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
protected override void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
base.NotifyPreBuildTransition(config, motionTarget);
if (config.Property == MotionRenderTransformProperty)
{
config.EndValue = BuildTranslateTransform(0, -motionTarget.DesiredSize.Height);
}
}
internal override Size CalculateSceneSize(Size motionTargetSize)
{
return motionTargetSize.WithHeight(motionTargetSize.Height * 2);
}
internal override Point CalculateScenePosition(Size motionTargetSize, Point motionTargetPosition)
{
return motionTargetPosition.WithY(motionTargetPosition.Y - motionTargetSize.Height);
}
}
public class MoveLeftInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
EndValue = BuildTranslateTransform(0, 0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
protected override void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
base.NotifyPreBuildTransition(config, motionTarget);
if (config.Property == MotionRenderTransformProperty)
{
config.StartValue = BuildTranslateTransform(-motionTarget.DesiredSize.Width, 0);
}
}
internal override Size CalculateSceneSize(Size motionTargetSize)
{
return motionTargetSize.WithHeight(motionTargetSize.Width * 2);
}
internal override Point CalculateScenePosition(Size motionTargetSize, Point motionTargetPosition)
{
return motionTargetPosition.WithX(motionTargetPosition.X - motionTargetSize.Width);
}
}
public class MoveLeftOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildTranslateTransform(0, 0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
protected override void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
base.NotifyPreBuildTransition(config, motionTarget);
if (config.Property == MotionRenderTransformProperty)
{
config.EndValue = BuildTranslateTransform(-motionTarget.DesiredSize.Width, 0);
}
}
internal override Size CalculateSceneSize(Size motionTargetSize)
{
return motionTargetSize.WithHeight(motionTargetSize.Width * 2);
}
internal override Point CalculateScenePosition(Size motionTargetSize, Point motionTargetPosition)
{
return motionTargetPosition.WithX(motionTargetPosition.X - motionTargetSize.Width);
}
}
public class MoveRightInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
EndValue = BuildTranslateTransform(0, 0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
protected override void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
base.NotifyPreBuildTransition(config, motionTarget);
if (config.Property == MotionRenderTransformProperty)
{
config.StartValue = BuildTranslateTransform(motionTarget.DesiredSize.Width, 0);
}
}
internal override Size CalculateSceneSize(Size motionTargetSize)
{
return motionTargetSize.WithHeight(motionTargetSize.Width * 2);
}
}
public class MoveRightOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildTranslateTransform(0, 0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
protected override void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
base.NotifyPreBuildTransition(config, motionTarget);
if (config.Property == MotionRenderTransformProperty)
{
config.EndValue = BuildTranslateTransform(motionTarget.DesiredSize.Width, 0);
}
}
internal override Size CalculateSceneSize(Size motionTargetSize)
{
return motionTargetSize.WithHeight(motionTargetSize.Width * 2);
}
}
public class MoveUpInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
EndValue = BuildTranslateTransform(0, 0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
protected override void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
base.NotifyPreBuildTransition(config, motionTarget);
if (config.Property == MotionRenderTransformProperty)
{
config.StartValue = BuildTranslateTransform(0, motionTarget.DesiredSize.Height);
}
}
internal override Size CalculateSceneSize(Size motionTargetSize)
{
return motionTargetSize.WithHeight(motionTargetSize.Height * 2);
}
}
public class MoveUpOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildTranslateTransform(0, 0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
protected override void NotifyPreBuildTransition(MotionConfig config, Control motionTarget)
{
base.NotifyPreBuildTransition(config, motionTarget);
if (config.Property == MotionRenderTransformProperty)
{
config.EndValue = BuildTranslateTransform(0, motionTarget.DesiredSize.Height);
}
}
internal override Size CalculateSceneSize(Size motionTargetSize)
{
return motionTargetSize.WithHeight(motionTargetSize.Height * 2);
}
}

View File

@ -6,23 +6,22 @@ using Avalonia.Styling;
namespace AtomUI.MotionScene;
internal static partial class MotionFactory
internal class MoveDownInMotion : AbstractMotion
{
public static MotionConfigX BuildMoveDownInMotion(double offset,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.None)
{
easing ??= new QuinticEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
public double Offset { get; }
public MoveDownInMotion(double offset,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new QuinticEaseOut(), fillMode)
{
Offset = offset;
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -38,7 +37,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 0.01, 0.0, offset)
Value = BuildTranslateScaleAndTransform(1.0, 0.01, 0.0, Offset)
};
startFrame.Setters.Add(transformSetter);
}
@ -59,7 +58,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 1.0, 0.0, offset / 4)
Value = BuildTranslateScaleAndTransform(1.0, 1.0, 0.0, Offset / 4)
};
middleFrame.Setters.Add(transformSetter);
}
@ -85,27 +84,38 @@ internal static partial class MotionFactory
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
internal override Size CalculateSceneSize(Size actorSize)
{
return actorSize.WithHeight(actorSize.Height * 2);
}
public static MotionConfigX BuildMoveDownOutMotion(double offset,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.None)
internal override Point CalculateScenePosition(Size actorSize, Point actorPosition)
{
easing ??= new QuinticEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
return actorPosition.WithY(actorPosition.Y + actorSize.Height);
}
}
internal class MoveDownOutMotion : AbstractMotion
{
public double Offset { get; }
public MoveDownOutMotion(double offset,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new QuinticEaseIn(), fillMode)
{
Offset = offset;
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -143,7 +153,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 1.0, 0.0, offset / 4)
Value = BuildTranslateScaleAndTransform(1.0, 1.0, 0.0, Offset / 4)
};
middleFrame.Setters.Add(transformSetter);
}
@ -164,30 +174,38 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 0.0, 0.0, offset)
Value = BuildTranslateScaleAndTransform(1.0, 0.0, 0.0, Offset)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
internal override Size CalculateSceneSize(Size actorSize)
{
return actorSize.WithHeight(actorSize.Height * 2);
}
}
internal class MoveUpInMotion : AbstractMotion
{
public double Offset { get; }
public MoveUpInMotion(double offset,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new QuinticEaseOut(), fillMode)
{
Offset = offset;
}
public static MotionConfigX BuildMoveUpInMotion(double offset, TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new QuinticEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -203,7 +221,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 0.01, 0.0, -offset)
Value = BuildTranslateScaleAndTransform(1.0, 0.01, 0.0, -Offset)
};
startFrame.Setters.Add(transformSetter);
}
@ -224,7 +242,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 1.0, 0.0, -offset / 4)
Value = BuildTranslateScaleAndTransform(1.0, 1.0, 0.0, -Offset / 4)
};
middleFrame.Setters.Add(transformSetter);
}
@ -250,25 +268,38 @@ internal static partial class MotionFactory
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
internal override Size CalculateSceneSize(Size actorSize)
{
return actorSize.WithHeight(actorSize.Height * 2);
}
internal override Point CalculateScenePosition(Size actorSize, Point actorPosition)
{
return actorPosition.WithY(actorPosition.Y - actorSize.Height);
}
}
internal class MoveUpOutMotion : AbstractMotion
{
public double Offset { get; }
public MoveUpOutMotion(double offset,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new QuinticEaseIn(), fillMode)
{
Offset = offset;
}
public static MotionConfigX BuildMoveUpOutMotion(double offset, TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new QuinticEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -313,7 +344,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 1.0, 0.0, -offset / 4)
Value = BuildTranslateScaleAndTransform(1.0, 1.0, 0.0, -Offset / 4)
};
middleFrame.Setters.Add(transformSetter);
@ -335,31 +366,39 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 0.0, 0.0, -offset)
Value = BuildTranslateScaleAndTransform(1.0, 0.0, 0.0, -Offset)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
internal override Size CalculateSceneSize(Size actorSize)
{
return actorSize.WithHeight(actorSize.Height * 2);
}
}
internal class MoveLeftInMotion : AbstractMotion
{
public double Offset { get; }
public MoveLeftInMotion(double offset,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new QuinticEaseOut(), fillMode)
{
Offset = offset;
}
public static MotionConfigX BuildMoveLeftInMotion(double offset, TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new QuinticEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -375,7 +414,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 0.01, -offset, 0.0)
Value = BuildTranslateScaleAndTransform(1.0, 0.01, -Offset, 0.0)
};
startFrame.Setters.Add(transformSetter);
@ -397,7 +436,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 1.0, -offset / 2, 0.0)
Value = BuildTranslateScaleAndTransform(1.0, 1.0, -Offset / 2, 0.0)
};
middleFrame.Setters.Add(transformSetter);
@ -425,25 +464,38 @@ internal static partial class MotionFactory
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
internal override Size CalculateSceneSize(Size actorSize)
{
return actorSize.WithWidth(actorSize.Width * 2);
}
public static MotionConfigX BuildMoveLeftOutMotion(double offset, TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
internal override Point CalculateScenePosition(Size actorSize, Point actorPosition)
{
easing ??= new QuinticEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
return actorPosition.WithX(actorPosition.X - actorSize.Width);
}
}
internal class MoveLeftOutMotion : AbstractMotion
{
public double Offset { get; }
public MoveLeftOutMotion(double offset,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new QuinticEaseIn(), fillMode)
{
Offset = offset;
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -479,7 +531,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 1.0, -offset / 2, 0.0)
Value = BuildTranslateScaleAndTransform(1.0, 1.0, -Offset / 2, 0.0)
};
middleFrame.Setters.Add(transformSetter);
}
@ -500,29 +552,38 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 0.0, -offset, 0.0)
Value = BuildTranslateScaleAndTransform(1.0, 0.0, -Offset, 0.0)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
internal override Size CalculateSceneSize(Size actorSize)
{
return actorSize.WithHeight(actorSize.Width * 2);
}
}
internal class MoveRightInMotion : AbstractMotion
{
public double Offset { get; }
public MoveRightInMotion(double offset,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new QuinticEaseOut(), fillMode)
{
Offset = offset;
}
public static MotionConfigX BuildMoveRightInMotion(double offset, TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new QuinticEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
@ -539,7 +600,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 0.01, offset, 0.0)
Value = BuildTranslateScaleAndTransform(1.0, 0.01, Offset, 0.0)
};
startFrame.Setters.Add(transformSetter);
}
@ -560,7 +621,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 1.0, offset / 2, 0.0)
Value = BuildTranslateScaleAndTransform(1.0, 1.0, Offset / 2, 0.0)
};
middleFrame.Setters.Add(transformSetter);
}
@ -586,25 +647,38 @@ internal static partial class MotionFactory
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
internal override Size CalculateSceneSize(Size actorSize)
{
return actorSize.WithHeight(actorSize.Width * 2);
}
internal override Point CalculateScenePosition(Size actorSize, Point actorPosition)
{
return actorPosition.WithY(actorPosition.X + actorSize.Height);
}
}
internal class MoveRightOutMotion : AbstractMotion
{
public double Offset { get; }
public MoveRightOutMotion(double offset,
TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new QuinticEaseIn(), fillMode)
{
Offset = offset;
}
public static MotionConfigX BuildMoveRightOutMotion(double offset, TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new QuinticEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -641,7 +715,7 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 1.0, offset / 2, 0.0)
Value = BuildTranslateScaleAndTransform(1.0, 1.0, Offset / 2, 0.0)
};
middleFrame.Setters.Add(transformSetter);
}
@ -662,14 +736,18 @@ internal static partial class MotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildTranslateScaleAndTransform(1.0, 0.0, offset, 0.0)
Value = BuildTranslateScaleAndTransform(1.0, 0.0, Offset, 0.0)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
internal override Size CalculateSceneSize(Size actorSize)
{
return actorSize.WithHeight(actorSize.Width * 2);
}
}

View File

@ -1,19 +1,20 @@
using System.Reflection;
using AtomUI.Platform.Windows;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.VisualTree;
using AtomUI.Platform.Windows;
namespace AtomUI.MotionScene;
public class SceneLayer : WindowBase, IHostedVisualTreeRoot, IDisposable
internal class SceneLayer : WindowBase, IHostedVisualTreeRoot, IDisposable
{
private readonly IManagedPopupPositionerPopup? _managedPopupPositionerPopup;
private static readonly FieldInfo ManagedPopupPositionerPopupInfo;
private readonly Canvas _layout;
private SceneMotionActorControl? _motionActorControl;
static SceneLayer()
{
@ -88,9 +89,10 @@ public class SceneLayer : WindowBase, IHostedVisualTreeRoot, IDisposable
PlatformImpl?.Dispose();
}
public void SetMotionTarget(Control motionTarget)
public void SetMotionActor(SceneMotionActorControl actorControl)
{
_layout.Children.Add(motionTarget);
_motionActorControl = actorControl;
_layout.Children.Add(actorControl);
}
// 这个地方我们可以需要定制
@ -149,12 +151,9 @@ public class SceneLayer : WindowBase, IHostedVisualTreeRoot, IDisposable
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
foreach (var child in _layout.Children)
if (_motionActorControl is not null)
{
if (child is INotifyCaptureGhostBitmap captureGhost)
{
captureGhost.NotifyCaptureGhostBitmap();
}
_motionActorControl.NotifySceneLayerHostWinOpened();
}
}
}

View File

@ -0,0 +1,107 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Layout;
namespace AtomUI.MotionScene;
internal class SceneMotionActorControl : MotionActorControl
{
public event EventHandler? SceneShowed;
#region
/// <summary>
/// 动画实体
/// </summary>
public Control MotionTarget { get; set; }
#endregion
#region
/// <summary>
/// 当 DispatchInSceneLayer 为 true 的时候,必须指定一个动画 SceneLayer 的父窗口,最好不要是 Popup
/// </summary>
public TopLevel? SceneParent { get; set; }
#endregion
protected Control? _ghost;
public SceneMotionActorControl(Control motionTarget)
{
MotionTarget = motionTarget;
UseRenderTransform = true;
}
internal virtual void BuildGhost()
{
}
public Control GetAnimatableGhost()
{
return _ghost ?? this;
}
protected virtual Point CalculateTopLevelGhostPosition()
{
return default;
}
/// <summary>
/// 在这个接口中Actor 根据自己的需求对 sceneLayer 进行设置,主要就是位置和大小
/// </summary>
/// <param name="motion"></param>
/// <param name="sceneLayer"></param>
public virtual void NotifySceneLayerCreated(AbstractMotion motion, SceneLayer sceneLayer)
{
var ghost = GetAnimatableGhost();
Size motionTargetSize;
// Popup.Child can't be null here, it was set in ShowAtCore.
if (ghost.DesiredSize == default)
{
// Popup may not have been shown yet. Measure content
motionTargetSize = LayoutHelper.MeasureChild(ghost, Size.Infinity, new Thickness());
}
else
{
motionTargetSize = ghost.DesiredSize;
}
var sceneSize = motion.CalculateSceneSize(motionTargetSize);
var scenePosition = motion.CalculateScenePosition(motionTargetSize, CalculateTopLevelGhostPosition());
sceneLayer.MoveAndResize(scenePosition, sceneSize);
}
/// <summary>
/// 当动画目标控件被添加到动画场景中之后调用,这里需要根据 Motion 的种类设置初始位置和大小
/// </summary>
public virtual void NotifyMotionTargetAddedToScene()
{
Canvas.SetLeft(this, 0);
Canvas.SetTop(this, 0);
}
public virtual void NotifySceneShowed()
{
SceneShowed?.Invoke(this, EventArgs.Empty);
}
internal virtual void NotifySceneLayerHostWinOpened()
{
if (_ghost is INotifyCaptureGhostBitmap captureGhost)
{
captureGhost.NotifyCaptureGhostBitmap();
}
}
internal override void NotifyMotionCompleted()
{
base.NotifyMotionCompleted();
if (_ghost is INotifyCaptureGhostBitmap notifyCaptureGhostBitmap)
{
notifyCaptureGhostBitmap.NotifyClearGhostBitmap();
}
}
}

View File

@ -1,329 +0,0 @@
using Avalonia;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
namespace AtomUI.MotionScene;
public class SlideUpInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleYTransform(0.8),
EndValue = BuildScaleYTransform(1.0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
}
public class SlideUpOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseIn();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseIn();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = BuildScaleYTransform(1.0),
EndValue = BuildScaleYTransform(0.8),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
}
public class SlideDownInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public SlideDownInMotion()
{
MotionRenderTransformOrigin = RelativePoint.BottomRight;
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleYTransform(0.8),
EndValue = BuildScaleYTransform(1.0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}
public class SlideDownOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public SlideDownOutMotion()
{
MotionRenderTransformOrigin = RelativePoint.BottomRight;
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseIn();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseIn();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleYTransform(1.0),
EndValue = BuildScaleYTransform(0.8),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}
public class SlideLeftInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleXTransform(0.8),
EndValue = BuildScaleXTransform(1.0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
}
public class SlideLeftOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseIn();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseIn();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = BuildScaleXTransform(1.0),
EndValue = BuildScaleXTransform(0.8),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
}
public class SlideRightInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public SlideRightInMotion()
{
MotionRenderTransformOrigin = new RelativePoint(1, 0, RelativeUnit.Relative);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleXTransform(0.8),
EndValue = BuildScaleXTransform(1.0),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}
public class SlideRightOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public SlideRightOutMotion()
{
MotionRenderTransformOrigin = new RelativePoint(1, 0, RelativeUnit.Relative);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseIn();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new QuinticEaseIn();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleXTransform(1.0),
EndValue = BuildScaleXTransform(0.8),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}

View File

@ -5,21 +5,18 @@ using Avalonia.Styling;
namespace AtomUI.MotionScene;
internal static partial class MotionFactory
internal class SlideUpInMotion : AbstractMotion
{
public static MotionConfigX BuildSlideUpInMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
public SlideUpInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CubicEaseOut(), fillMode)
{
easing ??= new CubicEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -59,25 +56,24 @@ internal static partial class MotionFactory
endFrame.Setters.Add(scaleYSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
internal class SlideUpOutMotion : AbstractMotion
{
public SlideUpOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CubicEaseIn(), fillMode)
{
}
public static MotionConfigX BuildSlideUpOutMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new CubicEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -118,25 +114,24 @@ internal static partial class MotionFactory
endFrame.Setters.Add(scaleYSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
internal class SlideDownInMotion : AbstractMotion
{
public SlideDownInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CubicEaseOut(), fillMode)
{
}
public static MotionConfigX BuildSlideDownInMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new CubicEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -177,25 +172,24 @@ internal static partial class MotionFactory
endFrame.Setters.Add(scaleYSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
internal class SlideDownOutMotion : AbstractMotion
{
public SlideDownOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CubicEaseIn(), fillMode)
{
}
public static MotionConfigX BuildSlideDownOutMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new CubicEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -236,25 +230,24 @@ internal static partial class MotionFactory
endFrame.Setters.Add(scaleYSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
internal class SlideLeftInMotion : AbstractMotion
{
public SlideLeftInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CubicEaseOut(), fillMode)
{
}
public static MotionConfigX BuildSlideLeftInMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new CubicEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -295,25 +288,24 @@ internal static partial class MotionFactory
endFrame.Setters.Add(scaleXSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
internal class SlideLeftOutMotion : AbstractMotion
{
public SlideLeftOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CubicEaseIn(), fillMode)
{
}
public static MotionConfigX BuildSlideLeftOutMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new CubicEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -354,25 +346,82 @@ internal static partial class MotionFactory
endFrame.Setters.Add(scaleXSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
internal class SlideRightInMotion : AbstractMotion
{
public SlideRightInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CubicEaseOut(), fillMode)
{
}
public static MotionConfigX BuildSlideRightInMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new CubicEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Duration = duration,
Easing = easing,
FillMode = fillMode
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
startFrame.Setters.Add(opacitySetter);
var scaleXSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleXTransform(1.0)
};
startFrame.Setters.Add(scaleXSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
endFrame.Setters.Add(opacitySetter);
var scaleXSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleXTransform(0.0)
};
endFrame.Setters.Add(scaleXSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class SlideRightOutMotion : AbstractMotion
{
public SlideRightOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CubicEaseIn(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -413,68 +462,8 @@ internal static partial class MotionFactory
endFrame.Setters.Add(scaleXSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
public static MotionConfigX BuildSlideRightOutMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
{
easing ??= new CubicEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
startFrame.Setters.Add(opacitySetter);
var scaleXSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleXTransform(1.0)
};
startFrame.Setters.Add(scaleXSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
endFrame.Setters.Add(opacitySetter);
var scaleXSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleXTransform(0.0)
};
endFrame.Setters.Add(scaleXSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
}
}
}

View File

@ -1,514 +0,0 @@
using Avalonia;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
namespace AtomUI.MotionScene;
public class ZoomInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(0.2),
EndValue = BuildScaleTransform(1),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
}
public class ZoomOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(1),
EndValue = BuildScaleTransform(0.2),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
}
public class ZoomBigInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(0.8),
EndValue = BuildScaleTransform(1),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
}
public class ZoomBigOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(1),
EndValue = BuildScaleTransform(0.8),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
}
public class ZoomUpInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public ZoomUpInMotion()
{
MotionRenderTransformOrigin = new RelativePoint(0.5, 0, RelativeUnit.Relative);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(0.8),
EndValue = BuildScaleTransform(1),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}
public class ZoomUpOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public ZoomUpOutMotion()
{
MotionRenderTransformOrigin = new RelativePoint(0.5, 0, RelativeUnit.Relative);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(1),
EndValue = BuildScaleTransform(0.8),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}
public class ZoomLeftInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public ZoomLeftInMotion()
{
MotionRenderTransformOrigin = new RelativePoint(0, 0.5, RelativeUnit.Relative);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(0.8),
EndValue = BuildScaleTransform(1),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}
public class ZoomLeftOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public ZoomLeftOutMotion()
{
MotionRenderTransformOrigin = new RelativePoint(0, 0.5, RelativeUnit.Relative);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(1),
EndValue = BuildScaleTransform(0.8),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}
public class ZoomRightInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public ZoomRightInMotion()
{
MotionRenderTransformOrigin = new RelativePoint(1, 0.5, RelativeUnit.Relative);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(0.8),
EndValue = BuildScaleTransform(1),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}
public class ZoomRightOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public ZoomRightOutMotion()
{
MotionRenderTransformOrigin = new RelativePoint(1, 0.5, RelativeUnit.Relative);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(1),
EndValue = BuildScaleTransform(0.8),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}
public class ZoomDownInMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public ZoomDownInMotion()
{
MotionRenderTransformOrigin = new RelativePoint(0.5, 1, RelativeUnit.Relative);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 0d,
EndValue = 1d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(0.8),
EndValue = BuildScaleTransform(1),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}
public class ZoomDownOutMotion : AbstractMotion
{
public MotionConfig? OpacityConfig => GetMotionConfig(MotionOpacityProperty);
public MotionConfig? RenderTransformConfig => GetMotionConfig(MotionRenderTransformProperty);
public ZoomDownOutMotion()
{
MotionRenderTransformOrigin = new RelativePoint(0.5, 1, RelativeUnit.Relative);
}
public void ConfigureOpacity(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionOpacityProperty)
{
TransitionKind = TransitionKind.Double,
StartValue = 1d,
EndValue = 0d,
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
public void ConfigureRenderTransform(TimeSpan duration, Easing? easing = null)
{
easing ??= new CircularEaseInOut();
var config = new MotionConfig(MotionRenderTransformProperty)
{
TransitionKind = TransitionKind.TransformOperations,
StartValue = BuildScaleTransform(1),
EndValue = BuildScaleTransform(0.8),
MotionDuration = duration,
MotionEasing = easing
};
AddMotionConfig(config);
}
internal override void NotifyConfigMotionTarget(Control motionTarget)
{
base.NotifyConfigMotionTarget(motionTarget);
motionTarget.RenderTransformOrigin = MotionRenderTransformOrigin;
}
}

View File

@ -0,0 +1,714 @@
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Styling;
namespace AtomUI.MotionScene;
internal class ZoomInMotion : AbstractMotion
{
public ZoomInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.01)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomOutMotion : AbstractMotion
{
public ZoomOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.01)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomBigInMotion : AbstractMotion
{
public ZoomBigInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.85)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomBigOutMotion : AbstractMotion
{
public ZoomBigOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.85)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomUpInMotion : AbstractMotion
{
public ZoomUpInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.01)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(0.5, 0.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomUpOutMotion : AbstractMotion
{
public ZoomUpOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.01)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(0.5, 0.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomLeftInMotion : AbstractMotion
{
public ZoomLeftInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.01)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(0.0, 0.5, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomLeftOutMotion : AbstractMotion
{
public ZoomLeftOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.01)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(0.0, 0.5, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomRightInMotion : AbstractMotion
{
public ZoomRightInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.01)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(1.0, 0.5, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomRightOutMotion : AbstractMotion
{
public ZoomRightOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.01)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(1.0, 0.5, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomDownInMotion : AbstractMotion
{
public ZoomDownInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.01)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}
internal class ZoomDownOutMotion : AbstractMotion
{
public ZoomDownOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 1.0
};
startFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(1.0)
};
startFrame.Setters.Add(transformSetter);
}
animation.Children.Add(startFrame);
var endFrame = new KeyFrame
{
Cue = new Cue(1.0)
};
{
var opacitySetter = new Setter
{
Property = Visual.OpacityProperty,
Value = 0.0
};
endFrame.Setters.Add(opacitySetter);
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = BuildScaleTransform(0.01)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
RenderTransformOrigin = new RelativePoint(0.5, 1.0, RelativeUnit.Relative);
Animations.Add(animation);
}
}

View File

@ -1,75 +0,0 @@
using System.Reflection;
using System.Runtime.Loader;
using Avalonia.Controls;
namespace AtomUI.Platform.Windows;
internal static class WindowExt
{
public const uint WS_EX_TRANSPARENT = 32; // 0x00000020
public const uint WS_EX_LAYERED = 0x00080000;
private static readonly Type WindowImplType;
private static readonly MethodInfo GetExtendedStyleInfo;
private static readonly MethodInfo SetExtendedStyleInfo;
static WindowExt()
{
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("Avalonia.Win32"));
WindowImplType = assembly.GetType("Avalonia.Win32.WindowImpl")!;
GetExtendedStyleInfo =
WindowImplType.GetMethod("GetExtendedStyle", BindingFlags.Instance | BindingFlags.NonPublic)!;
SetExtendedStyleInfo =
WindowImplType.GetMethod("SetExtendedStyle", BindingFlags.Instance | BindingFlags.NonPublic)!;
}
public static void SetTransparentForMouseEvents(this WindowBase window, bool flag)
{
var impl = window.PlatformImpl!;
var currentStyles = GetExtendedStyle(impl);
// 不是确定这样处理是否合适
if (flag)
{
currentStyles |= WS_EX_TRANSPARENT | WS_EX_LAYERED;
}
else
{
currentStyles &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
}
SetExtendedStyle(impl, currentStyles, false);
}
public static void SetTransparentForMouseEvents(this Window window, bool flag)
{
var impl = window.PlatformImpl!;
var currentStyles = GetExtendedStyle(impl);
// 不是确定这样处理是否合适
if (flag)
{
currentStyles |= WS_EX_TRANSPARENT | WS_EX_LAYERED;
}
else
{
currentStyles &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
}
SetExtendedStyle(impl, currentStyles, false);
}
private static uint GetExtendedStyle(object instance)
{
return (uint)GetExtendedStyleInfo.Invoke(instance, new object[] { })!;
}
private static void SetExtendedStyle(object instance, uint styles, bool save)
{
SetExtendedStyleInfo.Invoke(instance, new object[] { styles, save });
}
public static bool IsTransparentForMouseEvents(this WindowBase window)
{
var impl = window.PlatformImpl!;
var styles = GetExtendedStyle(impl);
return (styles & WS_EX_TRANSPARENT) != 0;
}
}

View File

@ -0,0 +1,26 @@
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
namespace AtomUI.Utils;
public class AnimationUtils
{
protected AnimationUtils() {}
public static ITransition CreateTransition<T>(AvaloniaProperty targetProperty,
TimeSpan? duration = null,
Easing? easing = null)
where T : TransitionBase, new()
{
easing ??= new LinearEasing();
duration ??= TimeSpan.FromMilliseconds(300);
var transition = new T
{
Property = targetProperty,
Easing = easing,
Duration = duration.Value
};
return transition;
}
}

View File

@ -1,7 +1,7 @@
using AtomUI.Data;
using AtomUI.IconPkg;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
@ -185,7 +185,7 @@ public class AddOnDecoratedBox : ContentControl
if (change.Property == LeftAddOnProperty || change.Property == RightAddOnProperty)
{
if (change.NewValue is PathIcon icon)
if (change.NewValue is Icon icon)
{
SetupIconTypeAddOnSize(icon);
}
@ -201,19 +201,19 @@ public class AddOnDecoratedBox : ContentControl
if (change.Property == SizeTypeProperty)
{
if (LeftAddOn is PathIcon leftIconAddOn)
if (LeftAddOn is Icon leftIconAddOn)
{
SetupIconTypeAddOnSize(leftIconAddOn);
}
if (RightAddOn is PathIcon rightIconAddOn)
if (RightAddOn is Icon rightIconAddOn)
{
SetupIconTypeAddOnSize(rightIconAddOn);
}
}
}
private void SetupIconTypeAddOnSize(PathIcon icon)
private void SetupIconTypeAddOnSize(Icon icon)
{
if (SizeType == SizeType.Large)
{

View File

@ -1,6 +1,6 @@
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;

View File

@ -1,7 +1,7 @@
using AtomUI.Controls.Utils;
using AtomUI.Data;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;

View File

@ -1,7 +1,9 @@
using AtomUI.Media;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Media;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
@ -185,10 +187,7 @@ internal class AddOnDecoratedInnerBoxTheme : BaseControlTheme
protected virtual void BuildClearButton(StackPanel addOnLayout, INameScope scope)
{
var closeIcon = new PathIcon
{
Kind = "CloseCircleFilled"
};
var closeIcon = AntDesignIconPackage.CloseCircleFilled();
var clearButton = new IconButton
{
Name = ClearButtonPart,
@ -199,11 +198,11 @@ internal class AddOnDecoratedInnerBoxTheme : BaseControlTheme
GlobalTokenResourceKey.IconSize);
TokenResourceBinder.CreateGlobalTokenBinding(clearButton, IconButton.IconWidthProperty,
GlobalTokenResourceKey.IconSize);
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextQuaternary);
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorTextTertiary);
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
clearButton.RegisterInNameScope(scope);
@ -241,7 +240,7 @@ internal class AddOnDecoratedInnerBoxTheme : BaseControlTheme
largeStyle.Add(innerBoxContentStyle);
}
{
var iconStyle = new Style(selector => selector.Nesting().Template().Descendant().OfType<PathIcon>());
var iconStyle = new Style(selector => selector.Nesting().Template().Descendant().OfType<Icon>());
iconStyle.Add(Layoutable.WidthProperty, GlobalTokenResourceKey.IconSizeLG);
iconStyle.Add(Layoutable.HeightProperty, GlobalTokenResourceKey.IconSizeLG);
largeStyle.Add(iconStyle);
@ -259,7 +258,7 @@ internal class AddOnDecoratedInnerBoxTheme : BaseControlTheme
middleStyle.Add(innerBoxContentStyle);
}
{
var iconStyle = new Style(selector => selector.Nesting().Template().Descendant().OfType<PathIcon>());
var iconStyle = new Style(selector => selector.Nesting().Template().Descendant().OfType<Icon>());
iconStyle.Add(Layoutable.WidthProperty, GlobalTokenResourceKey.IconSize);
iconStyle.Add(Layoutable.HeightProperty, GlobalTokenResourceKey.IconSize);
middleStyle.Add(iconStyle);
@ -277,7 +276,7 @@ internal class AddOnDecoratedInnerBoxTheme : BaseControlTheme
smallStyle.Add(innerBoxContentStyle);
}
{
var iconStyle = new Style(selector => selector.Nesting().Template().Descendant().OfType<PathIcon>());
var iconStyle = new Style(selector => selector.Nesting().Template().Descendant().OfType<Icon>());
iconStyle.Add(Layoutable.WidthProperty, GlobalTokenResourceKey.IconSizeSM);
iconStyle.Add(Layoutable.HeightProperty, GlobalTokenResourceKey.IconSizeSM);
smallStyle.Add(iconStyle);
@ -511,8 +510,8 @@ internal class AddOnDecoratedInnerBoxTheme : BaseControlTheme
selector.Nesting().PropertyEquals(AddOnDecoratedInnerBox.StatusProperty, AddOnDecoratedStatus.Error));
{
var iconStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(LeftAddOnPart),
selector.Nesting().Template().Name(RightAddOnPart)).Nesting().Descendant().OfType<PathIcon>());
iconStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorError);
selector.Nesting().Template().Name(RightAddOnPart)).Nesting().Descendant().OfType<Icon>());
iconStyle.Add(Icon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorError);
errorStyle.Add(iconStyle);
}
Add(errorStyle);
@ -523,8 +522,8 @@ internal class AddOnDecoratedInnerBoxTheme : BaseControlTheme
selector.Nesting().PropertyEquals(AddOnDecoratedInnerBox.StatusProperty, AddOnDecoratedStatus.Warning));
{
var iconStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(LeftAddOnPart),
selector.Nesting().Template().Name(RightAddOnPart)).Nesting().Descendant().OfType<PathIcon>());
iconStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorWarning);
selector.Nesting().Template().Name(RightAddOnPart)).Nesting().Descendant().OfType<Icon>());
iconStyle.Add(Icon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorWarning);
warningStyle.Add(iconStyle);
}
Add(warningStyle);

View File

@ -1,6 +1,7 @@
using AtomUI.Theme.Data;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
@ -33,8 +34,8 @@ public class Alert : TemplatedControl
public static readonly StyledProperty<bool> IsClosableProperty =
AvaloniaProperty.Register<Alert, bool>(nameof(IsClosable));
public static readonly StyledProperty<PathIcon?> CloseIconProperty =
AvaloniaProperty.Register<Alert, PathIcon?>(nameof(CloseIcon));
public static readonly StyledProperty<Icon?> CloseIconProperty =
AvaloniaProperty.Register<Alert, Icon?>(nameof(CloseIcon));
public static readonly StyledProperty<string> MessageProperty =
AvaloniaProperty.Register<Alert, string>(nameof(Message));
@ -69,7 +70,7 @@ public class Alert : TemplatedControl
set => SetValue(IsClosableProperty, value);
}
public PathIcon? CloseIcon
public Icon? CloseIcon
{
get => GetValue(CloseIconProperty);
set => SetValue(CloseIconProperty, value);
@ -144,13 +145,10 @@ public class Alert : TemplatedControl
{
if (CloseIcon is null)
{
CloseIcon = new PathIcon
{
Kind = "CloseOutlined"
};
TokenResourceBinder.CreateTokenBinding(CloseIcon, PathIcon.NormalFilledBrushProperty,
CloseIcon = AntDesignIconPackage.CloseOutlined();
TokenResourceBinder.CreateTokenBinding(CloseIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorIcon);
TokenResourceBinder.CreateTokenBinding(CloseIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateTokenBinding(CloseIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorIconHover);
}
}

View File

@ -1,7 +1,9 @@
using AtomUI.Data;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
@ -142,13 +144,13 @@ internal class AlertTheme : BaseControlTheme
private void BuildInfoIconStyle()
{
var infoIconSelector = default(Selector).Nesting().Template().OfType<PathIcon>().Name(InfoIconPart);
var infoIconSelector = default(Selector).Nesting().Template().OfType<Icon>().Name(InfoIconPart);
{
var successStyle = new Style(selector =>
selector.Nesting().PropertyEquals(Alert.TypeProperty, AlertType.Success));
var infoIconStyle = new Style(selector => infoIconSelector);
infoIconStyle.Add(PathIcon.KindProperty, "CheckCircleFilled");
infoIconStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorSuccess);
infoIconStyle.Add(Icon.IconInfoProperty, AntDesignIconPackage.Current.GetIconInfo(AntDesignIconKind.CheckCircleFilled));
infoIconStyle.Add(Icon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorSuccess);
successStyle.Add(infoIconStyle);
Add(successStyle);
}
@ -157,8 +159,8 @@ internal class AlertTheme : BaseControlTheme
var infoStyle = new Style(selector =>
selector.Nesting().PropertyEquals(Alert.TypeProperty, AlertType.Info));
var infoIconStyle = new Style(selector => infoIconSelector);
infoIconStyle.Add(PathIcon.KindProperty, "InfoCircleFilled");
infoIconStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorPrimary);
infoIconStyle.Add(Icon.IconInfoProperty, AntDesignIconPackage.Current.GetIconInfo(AntDesignIconKind.InfoCircleFilled));
infoIconStyle.Add(Icon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorPrimary);
infoStyle.Add(infoIconStyle);
Add(infoStyle);
}
@ -167,8 +169,8 @@ internal class AlertTheme : BaseControlTheme
var warningStyle = new Style(selector =>
selector.Nesting().PropertyEquals(Alert.TypeProperty, AlertType.Warning));
var infoIconStyle = new Style(selector => infoIconSelector);
infoIconStyle.Add(PathIcon.KindProperty, "ExclamationCircleFilled");
infoIconStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorWarning);
infoIconStyle.Add(Icon.IconInfoProperty, AntDesignIconPackage.Current.GetIconInfo(AntDesignIconKind.ExclamationCircleFilled));
infoIconStyle.Add(Icon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorWarning);
warningStyle.Add(infoIconStyle);
Add(warningStyle);
}
@ -177,8 +179,8 @@ internal class AlertTheme : BaseControlTheme
var errorStyle = new Style(selector =>
selector.Nesting().PropertyEquals(Alert.TypeProperty, AlertType.Error));
var infoIconStyle = new Style(selector => infoIconSelector);
infoIconStyle.Add(PathIcon.KindProperty, "CloseCircleFilled");
infoIconStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorError);
infoIconStyle.Add(Icon.IconInfoProperty, AntDesignIconPackage.Current.GetIconInfo(AntDesignIconKind.CloseCircleFilled));
infoIconStyle.Add(Icon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorError);
errorStyle.Add(infoIconStyle);
Add(errorStyle);
}
@ -311,9 +313,9 @@ internal class AlertTheme : BaseControlTheme
return closeBtn;
}
private PathIcon CreateInfoIcon(INameScope scope)
private Icon CreateInfoIcon(INameScope scope)
{
var infoIcon = new PathIcon
var infoIcon = new Icon
{
Name = InfoIconPart
};

View File

@ -1,78 +1,79 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Layout;
namespace AtomUI.Controls;
public enum ArrowPosition
{
/// <summary>
/// Preferred location is below the target element.
/// </summary>
Bottom,
/// <summary>
/// Preferred location is below the target element.
/// </summary>
Bottom,
/// <summary>
/// Preferred location is to the right of the target element.
/// </summary>
Right,
/// <summary>
/// Preferred location is to the right of the target element.
/// </summary>
Right,
/// <summary>
/// Preferred location is to the left of the target element.
/// </summary>
Left,
/// <summary>
/// Preferred location is to the left of the target element.
/// </summary>
Left,
/// <summary>
/// Preferred location is above the target element.
/// </summary>
Top,
/// <summary>
/// Preferred location is above the target element.
/// </summary>
Top,
/// <summary>
/// Preferred location is above the target element, with the left edge of the popup
/// aligned with the left edge of the target element.
/// </summary>
TopEdgeAlignedLeft,
/// <summary>
/// Preferred location is above the target element, with the left edge of the popup
/// aligned with the left edge of the target element.
/// </summary>
TopEdgeAlignedLeft,
/// <summary>
/// Preferred location is above the target element, with the right edge of popup aligned with right edge of the target
/// element.
/// </summary>
TopEdgeAlignedRight,
/// <summary>
/// Preferred location is above the target element, with the right edge of popup aligned with right edge of the target
/// element.
/// </summary>
TopEdgeAlignedRight,
/// <summary>
/// Preferred location is below the target element, with the left edge of popup aligned with left edge of the target
/// element.
/// </summary>
BottomEdgeAlignedLeft,
/// <summary>
/// Preferred location is below the target element, with the left edge of popup aligned with left edge of the target
/// element.
/// </summary>
BottomEdgeAlignedLeft,
/// <summary>
/// Preferred location is below the target element, with the right edge of popup aligned with right edge of the target
/// element.
/// </summary>
BottomEdgeAlignedRight,
/// <summary>
/// Preferred location is below the target element, with the right edge of popup aligned with right edge of the target
/// element.
/// </summary>
BottomEdgeAlignedRight,
/// <summary>
/// Preferred location is to the left of the target element, with the top edge of popup aligned with top edge of the
/// target element.
/// </summary>
LeftEdgeAlignedTop,
/// <summary>
/// Preferred location is to the left of the target element, with the top edge of popup aligned with top edge of the
/// target element.
/// </summary>
LeftEdgeAlignedTop,
/// <summary>
/// Preferred location is to the left of the target element, with the bottom edge of popup aligned with bottom edge of
/// the target element.
/// </summary>
LeftEdgeAlignedBottom,
/// <summary>
/// Preferred location is to the left of the target element, with the bottom edge of popup aligned with bottom edge of
/// the target element.
/// </summary>
LeftEdgeAlignedBottom,
/// <summary>
/// Preferred location is to the right of the target element, with the top edge of popup aligned with top edge of the
/// target element.
/// </summary>
RightEdgeAlignedTop,
/// <summary>
/// Preferred location is to the right of the target element, with the top edge of popup aligned with top edge of the
/// target element.
/// </summary>
RightEdgeAlignedTop,
/// <summary>
/// Preferred location is to the right of the target element, with the bottom edge of popup aligned with bottom edge of
/// the target element.
/// </summary>
RightEdgeAlignedBottom
/// <summary>
/// Preferred location is to the right of the target element, with the bottom edge of popup aligned with bottom edge of
/// the target element.
/// </summary>
RightEdgeAlignedBottom
}
public class ArrowDecoratedBox : ContentControl, IShadowMaskInfoProvider
@ -205,9 +206,16 @@ public class ArrowDecoratedBox : ContentControl, IShadowMaskInfoProvider
{
return default;
}
var targetRect = _arrowIndicatorLayout.Bounds;
var center = targetRect.Center;
var controlSize = Bounds.Size;
if (_arrowIndicatorLayout.Bounds == default)
{
LayoutHelper.MeasureChild(this, Size.Infinity, Padding);
Arrange(new Rect(DesiredSize));
}
var targetRect = _arrowIndicatorLayout.Bounds;
var center = targetRect.Center;
var controlSize = Bounds.Size;
// 计算中点
var direction = GetDirection(ArrowPosition);
@ -234,10 +242,10 @@ public class ArrowDecoratedBox : ContentControl, IShadowMaskInfoProvider
{
return;
}
var offsetX = 0d;
var offsetY = 0d;
var position = ArrowPosition;
var size = _arrowIndicatorLayout.DesiredSize;
var offsetX = 0d;
var offsetY = 0d;
var position = ArrowPosition;
var size = _arrowIndicatorLayout.DesiredSize;
var minValue = Math.Min(size.Width, size.Height);
var maxValue = Math.Max(size.Width, size.Height);

View File

@ -21,6 +21,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AtomUI.IconPkg.AntDesign\AtomUI.IconPkg.AntDesign.csproj" />
<ProjectReference Include="..\AtomUI.Theme\AtomUI.Theme.csproj"/>
<ProjectReference Include="..\AtomUI.Generator\AtomUI.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>

View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=primitives_005Catomlayer/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -6,21 +6,18 @@ using Avalonia.Styling;
namespace AtomUI.Controls.Badge;
internal static class BadgeMotionFactory
internal class BadgeZoomBadgeInMotion : AbstractMotion
{
public static MotionConfigX BuildBadgeZoomBadgeInMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
public BadgeZoomBadgeInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new ExponentialEaseOut(), fillMode)
{
easing ??= new ExponentialEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
}
protected override void Configure()
{
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -36,7 +33,7 @@ internal static class BadgeMotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = MotionFactory.BuildScaleTransform(0.0)
Value = BuildScaleTransform(0.01)
};
startFrame.Setters.Add(transformSetter);
}
@ -57,30 +54,29 @@ internal static class BadgeMotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = MotionFactory.BuildScaleTransform(1.0)
Value = BuildScaleTransform(1.0)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
internal class BadgeZoomBadgeOutMotion : AbstractMotion
{
public BadgeZoomBadgeOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new ExponentialEaseIn(), fillMode)
{
}
public static MotionConfigX BuildBadgeZoomBadgeOutMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new ExponentialEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -96,7 +92,7 @@ internal static class BadgeMotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = MotionFactory.BuildScaleTransform(1.0)
Value = BuildScaleTransform(1.0)
};
startFrame.Setters.Add(transformSetter);
}
@ -117,30 +113,29 @@ internal static class BadgeMotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = MotionFactory.BuildScaleTransform(0.0)
Value = BuildScaleTransform(0.01)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
internal class CountBadgeNoWrapperZoomBadgeInMotion : AbstractMotion
{
public CountBadgeNoWrapperZoomBadgeInMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseOut(), fillMode)
{
}
public static MotionConfigX BuildCountBadgeNoWrapperZoomBadgeInMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new CircularEaseOut();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -156,7 +151,7 @@ internal static class BadgeMotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = MotionFactory.BuildScaleTransform(0.0, 0.0)
Value = BuildScaleTransform(0.01, 0.01)
};
startFrame.Setters.Add(transformSetter);
}
@ -177,30 +172,29 @@ internal static class BadgeMotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = MotionFactory.BuildScaleTransform(1.0, 1.0)
Value = BuildScaleTransform(1.0, 1.0)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
internal class CountBadgeNoWrapperZoomBadgeOutMotion : AbstractMotion
{
public CountBadgeNoWrapperZoomBadgeOutMotion(TimeSpan duration,
Easing? easing = null,
FillMode fillMode = FillMode.Forward)
: base(duration, easing ?? new CircularEaseIn(), fillMode)
{
}
public static MotionConfigX BuildCountBadgeNoWrapperZoomBadgeOutMotion(TimeSpan duration, Easing? easing = null,
FillMode fillMode = FillMode.None)
protected override void Configure()
{
easing ??= new CircularEaseIn();
var animations = new List<Animation>();
RelativePoint transformOrigin = default;
var animation = new Animation
{
Duration = duration,
Easing = easing,
FillMode = fillMode
};
var animation = CreateAnimation();
var startFrame = new KeyFrame
{
Cue = new Cue(0.0)
@ -216,7 +210,7 @@ internal static class BadgeMotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = MotionFactory.BuildScaleTransform(1.0, 1.0)
Value = BuildScaleTransform(1.0, 1.0)
};
startFrame.Setters.Add(transformSetter);
}
@ -237,14 +231,14 @@ internal static class BadgeMotionFactory
var transformSetter = new Setter
{
Property = MotionActorControl.MotionTransformProperty,
Value = MotionFactory.BuildScaleTransform(0.0, 0.0)
Value = BuildScaleTransform(0.01, 0.01)
};
endFrame.Setters.Add(transformSetter);
}
animation.Children.Add(endFrame);
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
animations.Add(animation);
return new MotionConfigX(transformOrigin, animations);
Animations.Add(animation);
}
}
}

View File

@ -1,7 +1,7 @@
using AtomUI.Data;
using AtomUI.Theme.Data;
using AtomUI.Theme.Palette;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;

View File

@ -1,9 +1,8 @@
using AtomUI.Controls.Badge;
using AtomUI.MotionScene;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Media;
@ -142,7 +141,6 @@ internal class CountBadgeAdorner : TemplatedControl
#endregion
private Panel? _rootLayout;
private MotionActorControl? _indicatorMotionActor;
private CancellationTokenSource? _motionCancellationTokenSource;
private bool _needInitialHide;
@ -231,9 +229,8 @@ internal class CountBadgeAdorner : TemplatedControl
if (_indicatorMotionActor is not null)
{
_indicatorMotionActor.IsVisible = false;
var zoomBadgeInMotionConfig = BadgeMotionFactory.BuildBadgeZoomBadgeInMotion(MotionDuration, null,
FillMode.Forward);
MotionInvoker.Invoke(_indicatorMotionActor, zoomBadgeInMotionConfig, () =>
var motion = new BadgeZoomBadgeInMotion(MotionDuration);
MotionInvoker.Invoke(_indicatorMotionActor, motion, () =>
{
_indicatorMotionActor.IsVisible = true;
}, null, _motionCancellationTokenSource!.Token);
@ -244,12 +241,11 @@ internal class CountBadgeAdorner : TemplatedControl
{
if (_indicatorMotionActor is not null)
{
var zoomBadgeOutMotionConfig = BadgeMotionFactory.BuildBadgeZoomBadgeOutMotion(MotionDuration, null,
FillMode.Forward);
var motion = new BadgeZoomBadgeOutMotion(MotionDuration);
_motionCancellationTokenSource?.Cancel();
_motionCancellationTokenSource = new CancellationTokenSource();
MotionInvoker.Invoke(_indicatorMotionActor, zoomBadgeOutMotionConfig, null, () =>
MotionInvoker.Invoke(_indicatorMotionActor, motion, null, () =>
{
completedAction();
}, _motionCancellationTokenSource.Token);

View File

@ -1,7 +1,7 @@
using AtomUI.Controls.Badge;
using AtomUI.MotionScene;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
@ -15,13 +15,13 @@ internal class DotBadgeAdorner : TemplatedControl
public static readonly StyledProperty<IBrush?> BadgeDotColorProperty =
AvaloniaProperty.Register<DotBadgeAdorner, IBrush?>(
nameof(BadgeDotColor));
public static readonly DirectProperty<DotBadgeAdorner, DotBadgeStatus?> StatusProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, DotBadgeStatus?>(
nameof(Status),
o => o.Status,
(o, v) => o.Status = v);
internal IBrush? BadgeDotColor
{
get => GetValue(BadgeDotColorProperty);
@ -73,7 +73,7 @@ internal class DotBadgeAdorner : TemplatedControl
get => GetValue(OffsetProperty);
set => SetValue(OffsetProperty, value);
}
#region
internal static readonly StyledProperty<TimeSpan> MotionDurationProperty =
@ -85,9 +85,9 @@ internal class DotBadgeAdorner : TemplatedControl
get => GetValue(MotionDurationProperty);
set => SetValue(MotionDurationProperty, value);
}
#endregion
private MotionActorControl? _indicatorMotionActor;
private CancellationTokenSource? _motionCancellationTokenSource;
@ -109,28 +109,23 @@ internal class DotBadgeAdorner : TemplatedControl
if (_indicatorMotionActor is not null)
{
_indicatorMotionActor.IsVisible = false;
var zoomBadgeInMotionConfig = BadgeMotionFactory.BuildBadgeZoomBadgeInMotion(MotionDuration, null,
FillMode.Forward);
MotionInvoker.Invoke(_indicatorMotionActor, zoomBadgeInMotionConfig, () =>
{
_indicatorMotionActor.IsVisible = true;
}, null, _motionCancellationTokenSource!.Token);
_motionCancellationTokenSource?.Cancel();
_motionCancellationTokenSource = new CancellationTokenSource();
var motion = new BadgeZoomBadgeInMotion(MotionDuration, null, FillMode.Forward);
MotionInvoker.Invoke(_indicatorMotionActor, motion, () => _indicatorMotionActor.IsVisible = true,
null, _motionCancellationTokenSource.Token);
}
}
private void ApplyHideMotion(Action completedAction)
{
if (_indicatorMotionActor is not null)
{
var zoomBadgeOutMotionConfig = BadgeMotionFactory.BuildBadgeZoomBadgeOutMotion(MotionDuration, null,
FillMode.Forward);
_motionCancellationTokenSource?.Cancel();
_motionCancellationTokenSource = new CancellationTokenSource();
MotionInvoker.Invoke(_indicatorMotionActor, zoomBadgeOutMotionConfig, null, () =>
{
completedAction();
}, _motionCancellationTokenSource.Token);
_motionCancellationTokenSource = new CancellationTokenSource();
var motion = new BadgeZoomBadgeOutMotion(MotionDuration, null, FillMode.Forward);
MotionInvoker.Invoke(_indicatorMotionActor, motion, null, () => completedAction(),
_motionCancellationTokenSource.Token);
}
}
@ -145,7 +140,7 @@ internal class DotBadgeAdorner : TemplatedControl
}
}
}
private void SetupBadgeColor()
{
if (Status is not null)
@ -190,6 +185,7 @@ internal class DotBadgeAdorner : TemplatedControl
offsetY -= dotSize.Height / 3;
_indicatorMotionActor.Arrange(new Rect(new Point(offsetX, offsetY), dotSize));
}
return size;
}
@ -199,16 +195,16 @@ internal class DotBadgeAdorner : TemplatedControl
{
return;
}
adornerLayer.Children.Remove(this);
AdornerLayer.SetAdornedElement(this, adorned);
AdornerLayer.SetIsClipEnabled(this, false);
adornerLayer.Children.Add(this);
_motionCancellationTokenSource?.Cancel();
_motionCancellationTokenSource = new CancellationTokenSource();
_motionCancellationTokenSource = new CancellationTokenSource();
ApplyShowMotion();
}

View File

@ -1,5 +1,5 @@
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;

View File

@ -1,8 +1,9 @@
using AtomUI.Media;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Media;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia.Animation;
using Avalonia.Controls;
@ -104,15 +105,12 @@ internal class ButtonSpinnerTheme : BaseControlTheme
TokenResourceBinder.CreateTokenBinding(spinnerLayout, Layoutable.WidthProperty,
ButtonSpinnerTokenResourceKey.HandleWidth);
var increaseButtonIcon = AntDesignIconPackage.UpOutlined();
var increaseButtonIcon = new PathIcon
{
Kind = "UpOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(increaseButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(increaseButtonIcon, Icon.ActiveFilledBrushProperty,
ButtonSpinnerTokenResourceKey.HandleHoverColor);
TokenResourceBinder.CreateGlobalTokenBinding(increaseButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(increaseButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorPrimaryActive);
var increaseButton = new IconButton
@ -140,14 +138,11 @@ internal class ButtonSpinnerTheme : BaseControlTheme
ButtonSpinnerTokenResourceKey.HandleIconSize);
increaseButton.RegisterInNameScope(scope);
var decreaseButtonIcon = new PathIcon
{
Kind = "DownOutlined"
};
var decreaseButtonIcon = AntDesignIconPackage.DownOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(decreaseButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(decreaseButtonIcon, Icon.ActiveFilledBrushProperty,
ButtonSpinnerTokenResourceKey.HandleHoverColor);
TokenResourceBinder.CreateGlobalTokenBinding(decreaseButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(decreaseButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorPrimaryActive);
var decreaseButton = new IconButton

View File

@ -1,4 +1,5 @@
using AtomUI.Icon;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia;
@ -31,12 +32,9 @@ internal abstract class BaseButtonTheme : BaseControlTheme
{
return new FuncControlTemplate<Button>((button, scope) =>
{
var loadingIcon = new PathIcon
{
Kind = "LoadingOutlined",
Name = LoadingIconPart
};
var loadingIcon = AntDesignIconPackage.LoadingOutlined();
loadingIcon.Name = LoadingIconPart;
loadingIcon.RegisterInNameScope(scope);
CreateTemplateParentBinding(loadingIcon, Layoutable.WidthProperty, Button.IconSizeProperty);
@ -271,7 +269,7 @@ internal abstract class BaseButtonTheme : BaseControlTheme
var loadingIconStyle = new Style(selector => selector.Nesting().Template().Name(LoadingIconPart));
loadingIconStyle.Add(Visual.IsVisibleProperty, true);
loadingIconStyle.Add(PathIcon.LoadingAnimationProperty, IconAnimation.Spin);
loadingIconStyle.Add(Icon.LoadingAnimationProperty, IconAnimation.Spin);
loadingStyle.Add(loadingIconStyle);
}
loadingStyle.Add(Visual.OpacityProperty, GlobalTokenResourceKey.OpacityLoading);

View File

@ -1,12 +1,10 @@
using AtomUI.Controls.Utils;
using AtomUI.Data;
using AtomUI.Icon;
using AtomUI.IconPkg;
using AtomUI.Media;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.TokenSystem;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
@ -66,8 +64,8 @@ public class Button : AvaloniaButton,
public static readonly StyledProperty<ButtonSizeType> SizeTypeProperty =
AvaloniaProperty.Register<Button, ButtonSizeType>(nameof(SizeType), ButtonSizeType.Middle);
public static readonly StyledProperty<PathIcon?> IconProperty
= AvaloniaProperty.Register<Button, PathIcon?>(nameof(Icon));
public static readonly StyledProperty<Icon?> IconProperty
= AvaloniaProperty.Register<Button, Icon?>(nameof(Icon));
public static readonly StyledProperty<string?> TextProperty
= AvaloniaProperty.Register<Button, string?>(nameof(Text));
@ -111,7 +109,7 @@ public class Button : AvaloniaButton,
set => SetValue(SizeTypeProperty, value);
}
public PathIcon? Icon
public Icon? Icon
{
get => GetValue(IconProperty);
set => SetValue(IconProperty, value);
@ -216,7 +214,7 @@ public class Button : AvaloniaButton,
protected ControlStyleState _styleState;
private bool _initialized;
private PathIcon? _loadingIcon;
private Icon? _loadingIcon;
static Button()
{
@ -318,7 +316,6 @@ public class Button : AvaloniaButton,
};
}
}
_initialized = true;
}
}
@ -383,24 +380,28 @@ public class Button : AvaloniaButton,
UpdatePseudoClasses();
}
if (e.Property == IconProperty)
{
SetupIcon();
}
if (e.Property == IsDangerProperty ||
e.Property == IsGhostProperty ||
e.Property == ButtonTypeProperty)
{
SetupIconBrush();
}
if (e.Property == BorderBrushProperty ||
e.Property == ButtonTypeProperty ||
e.Property == IsEnabledProperty)
{
SetupEffectiveBorderThickness();
}
if (VisualRoot is not null)
{
if (e.Property == IconProperty)
{
SetupIcon();
SetupIconBrush();
}
if (e.Property == IsDangerProperty ||
e.Property == IsGhostProperty ||
e.Property == ButtonTypeProperty)
{
SetupIconBrush();
}
}
}
private void SetupControlTheme()
@ -479,7 +480,7 @@ public class Button : AvaloniaButton,
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
_loadingIcon = e.NameScope.Find<PathIcon>(BaseButtonTheme.LoadingIconPart);
_loadingIcon = e.NameScope.Find<Icon>(BaseButtonTheme.LoadingIconPart);
HandleTemplateApplied(e.NameScope);
SetupTransitions();
}
@ -620,44 +621,38 @@ public class Button : AvaloniaButton,
else if (ButtonType == ButtonType.Link)
{
normalFilledBrushKey = GlobalTokenResourceKey.ColorLink;
selectedFilledBrushKey = ButtonTokenResourceKey.DefaultActiveColor;
activeFilledBrushKey = ButtonTokenResourceKey.DefaultHoverColor;
if (IsGhost)
{
normalFilledBrushKey = GlobalTokenResourceKey.ColorLink;
selectedFilledBrushKey = GlobalTokenResourceKey.ColorPrimaryActive;
activeFilledBrushKey = GlobalTokenResourceKey.ColorPrimaryHover;
}
selectedFilledBrushKey = GlobalTokenResourceKey.ColorLinkActive;
activeFilledBrushKey = GlobalTokenResourceKey.ColorLinkHover;
if (IsDanger)
{
normalFilledBrushKey = GlobalTokenResourceKey.ColorError;
selectedFilledBrushKey = GlobalTokenResourceKey.ColorErrorActive;
activeFilledBrushKey = GlobalTokenResourceKey.ColorErrorBorderHover;
activeFilledBrushKey = GlobalTokenResourceKey.ColorErrorHover;
}
}
if (Icon is not null)
{
TokenResourceBinder.CreateGlobalTokenBinding(Icon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateTokenBinding(Icon, Icon.NormalFilledBrushProperty,
normalFilledBrushKey);
TokenResourceBinder.CreateGlobalTokenBinding(Icon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateTokenBinding(Icon, Icon.SelectedFilledBrushProperty,
selectedFilledBrushKey);
TokenResourceBinder.CreateGlobalTokenBinding(Icon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateTokenBinding(Icon, Icon.ActiveFilledBrushProperty,
activeFilledBrushKey);
TokenResourceBinder.CreateGlobalTokenBinding(Icon, PathIcon.DisabledFilledBrushProperty,
TokenResourceBinder.CreateTokenBinding(Icon, Icon.DisabledFilledBrushProperty,
disabledFilledBrushKey);
}
if (_loadingIcon is not null)
{
TokenResourceBinder.CreateGlobalTokenBinding(_loadingIcon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateTokenBinding(_loadingIcon, Icon.NormalFilledBrushProperty,
normalFilledBrushKey);
TokenResourceBinder.CreateGlobalTokenBinding(_loadingIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateTokenBinding(_loadingIcon, Icon.SelectedFilledBrushProperty,
selectedFilledBrushKey);
TokenResourceBinder.CreateGlobalTokenBinding(_loadingIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateTokenBinding(_loadingIcon, Icon.ActiveFilledBrushProperty,
activeFilledBrushKey);
TokenResourceBinder.CreateGlobalTokenBinding(_loadingIcon, PathIcon.DisabledFilledBrushProperty,
TokenResourceBinder.CreateTokenBinding(_loadingIcon, Icon.DisabledFilledBrushProperty,
disabledFilledBrushKey);
}

View File

@ -1,8 +1,9 @@
using AtomUI.Data;
using AtomUI.Icon;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.TokenSystem;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Diagnostics;
@ -129,7 +130,7 @@ public class DropdownButton : Button
#endregion
private PathIcon? _openIndicatorIcon;
private Icon? _openIndicatorIcon;
private MenuFlyoutPresenter? _menuFlyoutPresenter;
private readonly FlyoutStateHelper _flyoutStateHelper;
@ -160,12 +161,10 @@ public class DropdownButton : Button
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
_openIndicatorIcon = new PathIcon
{
Kind = "DownOutlined"
};
BindUtils.RelayBind(this, IconSizeProperty, _openIndicatorIcon, WidthProperty);
BindUtils.RelayBind(this, IconSizeProperty, _openIndicatorIcon, HeightProperty);
_openIndicatorIcon = AntDesignIconPackage.DownOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(_openIndicatorIcon, Icon.WidthProperty, GlobalTokenResourceKey.IconSizeSM);
TokenResourceBinder.CreateGlobalTokenBinding(_openIndicatorIcon, Icon.HeightProperty, GlobalTokenResourceKey.IconSizeSM);
base.OnApplyTemplate(e);
TokenResourceBinder.CreateGlobalTokenBinding(this, MarginToAnchorProperty, GlobalTokenResourceKey.MarginXXS);
@ -264,13 +263,13 @@ public class DropdownButton : Button
{
if (_openIndicatorIcon is not null)
{
TokenResourceBinder.CreateGlobalTokenBinding(_openIndicatorIcon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(_openIndicatorIcon, Icon.NormalFilledBrushProperty,
normalFilledBrushKey);
TokenResourceBinder.CreateGlobalTokenBinding(_openIndicatorIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(_openIndicatorIcon, Icon.SelectedFilledBrushProperty,
selectedFilledBrushKey);
TokenResourceBinder.CreateGlobalTokenBinding(_openIndicatorIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(_openIndicatorIcon, Icon.ActiveFilledBrushProperty,
activeFilledBrushKey);
TokenResourceBinder.CreateGlobalTokenBinding(_openIndicatorIcon, PathIcon.DisabledFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(_openIndicatorIcon, Icon.DisabledFilledBrushProperty,
disabledFilledBrushKey);
}
}

View File

@ -1,5 +1,5 @@
using AtomUI.Data;
using AtomUI.Icon;
using AtomUI.IconPkg;
using AtomUI.Theme.Styling;
using Avalonia;
using Avalonia.Controls;
@ -15,14 +15,14 @@ public class IconButton : AvaloniaButton, ICustomHitTest
{
#region
public static readonly StyledProperty<PathIcon?> IconProperty
= AvaloniaProperty.Register<IconButton, PathIcon?>(nameof(Icon));
public static readonly StyledProperty<Icon?> IconProperty
= AvaloniaProperty.Register<IconButton, Icon?>(nameof(Icon));
public static readonly StyledProperty<IconAnimation> LoadingAnimationProperty =
PathIcon.LoadingAnimationProperty.AddOwner<IconButton>();
Icon.LoadingAnimationProperty.AddOwner<IconButton>();
public static readonly StyledProperty<TimeSpan> LoadingAnimationDurationProperty =
PathIcon.LoadingAnimationDurationProperty.AddOwner<IconButton>();
Icon.LoadingAnimationDurationProperty.AddOwner<IconButton>();
public static readonly StyledProperty<double> IconWidthProperty
= AvaloniaProperty.Register<IconButton, double>(nameof(IconWidth));
@ -33,7 +33,7 @@ public class IconButton : AvaloniaButton, ICustomHitTest
public static readonly StyledProperty<bool> IsEnableHoverEffectProperty
= AvaloniaProperty.Register<IconButton, bool>(nameof(IsEnableHoverEffect));
public PathIcon? Icon
public Icon? Icon
{
get => GetValue(IconProperty);
set => SetValue(IconProperty, value);
@ -97,7 +97,7 @@ public class IconButton : AvaloniaButton, ICustomHitTest
{
if (e.Property == IconProperty)
{
var oldIcon = e.GetOldValue<PathIcon?>();
var oldIcon = e.GetOldValue<Icon?>();
if (oldIcon is not null)
{
((ISetLogicalParent)oldIcon).SetParent(null);
@ -118,9 +118,9 @@ public class IconButton : AvaloniaButton, ICustomHitTest
{
if (Icon is not null)
{
BindUtils.RelayBind(this, LoadingAnimationProperty, Icon, PathIcon.LoadingAnimationProperty);
BindUtils.RelayBind(this, LoadingAnimationProperty, Icon, Icon.LoadingAnimationProperty);
BindUtils.RelayBind(this, LoadingAnimationDurationProperty, Icon,
PathIcon.LoadingAnimationDurationProperty);
Icon.LoadingAnimationDurationProperty);
BindUtils.RelayBind(this, IconHeightProperty, Icon, HeightProperty);
BindUtils.RelayBind(this, IconWidthProperty, Icon, WidthProperty);
}

View File

@ -1,7 +1,8 @@
using AtomUI.Media;
using AtomUI.Controls.Utils;
using AtomUI.IconPkg;
using AtomUI.Media;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
@ -65,7 +66,7 @@ internal class IconButtonTheme : BaseControlTheme
protected override void BuildInstanceStyles(Control control)
{
var iconStyle = new Style(selector => selector.Name(IconContentPart).Child().OfType<PathIcon>());
var iconStyle = new Style(selector => selector.Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Layoutable.HorizontalAlignmentProperty, HorizontalAlignment.Center);
iconStyle.Add(Layoutable.VerticalAlignmentProperty, VerticalAlignment.Center);
control.Styles.Add(iconStyle);

View File

@ -31,37 +31,31 @@ internal class LinkButtonTheme : BaseButtonTheme
{
var enabledStyle = new Style(selector => selector.Nesting());
// 正常状态
enabledStyle.Add(TemplatedControl.BackgroundProperty,
new DynamicResourceExtension(ButtonTokenResourceKey.DefaultBg));
enabledStyle.Add(TemplatedControl.ForegroundProperty,
new DynamicResourceExtension(GlobalTokenResourceKey.ColorLink));
enabledStyle.Add(TemplatedControl.BackgroundProperty, ButtonTokenResourceKey.DefaultBg);
enabledStyle.Add(TemplatedControl.ForegroundProperty, GlobalTokenResourceKey.ColorLink);
// 正常 hover
{
var hoverStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.PointerOver));
hoverStyle.Add(TemplatedControl.ForegroundProperty,
new DynamicResourceExtension(GlobalTokenResourceKey.ColorLinkHover));
hoverStyle.Add(TemplatedControl.ForegroundProperty, GlobalTokenResourceKey.ColorLinkHover);
enabledStyle.Add(hoverStyle);
}
// 正常按下
{
var pressedStyle = new Style(selector =>
selector.Nesting().Class(StdPseudoClass.PointerOver).Class(StdPseudoClass.Pressed));
pressedStyle.Add(TemplatedControl.ForegroundProperty,
new DynamicResourceExtension(GlobalTokenResourceKey.ColorLinkActive));
pressedStyle.Add(TemplatedControl.ForegroundProperty, GlobalTokenResourceKey.ColorLinkActive);
enabledStyle.Add(pressedStyle);
}
// 危险按钮状态
var dangerStyle = new Style(selector => selector.Nesting().PropertyEquals(Button.IsDangerProperty, true));
dangerStyle.Add(TemplatedControl.ForegroundProperty,
new DynamicResourceExtension(GlobalTokenResourceKey.ColorError));
dangerStyle.Add(TemplatedControl.ForegroundProperty, GlobalTokenResourceKey.ColorError);
// 危险状态 hover
{
var hoverStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.PointerOver));
hoverStyle.Add(TemplatedControl.ForegroundProperty,
new DynamicResourceExtension(GlobalTokenResourceKey.ColorErrorHover));
hoverStyle.Add(TemplatedControl.ForegroundProperty, GlobalTokenResourceKey.ColorErrorHover);
dangerStyle.Add(hoverStyle);
}
@ -69,8 +63,7 @@ internal class LinkButtonTheme : BaseButtonTheme
{
var pressedStyle = new Style(selector =>
selector.Nesting().Class(StdPseudoClass.PointerOver).Class(StdPseudoClass.Pressed));
pressedStyle.Add(TemplatedControl.ForegroundProperty,
new DynamicResourceExtension(GlobalTokenResourceKey.ColorErrorActive));
pressedStyle.Add(TemplatedControl.ForegroundProperty, GlobalTokenResourceKey.ColorErrorActive);
dangerStyle.Add(pressedStyle);
}
enabledStyle.Add(dangerStyle);
@ -84,8 +77,7 @@ internal class LinkButtonTheme : BaseButtonTheme
{
var ghostStyle = new Style(selector => selector.Nesting().PropertyEquals(Button.IsGhostProperty, true));
// 正常状态
ghostStyle.Add(TemplatedControl.BackgroundProperty,
new DynamicResourceExtension(GlobalTokenResourceKey.ColorTransparent));
ghostStyle.Add(TemplatedControl.BackgroundProperty, GlobalTokenResourceKey.ColorTransparent);
Add(ghostStyle);
}
@ -93,8 +85,7 @@ internal class LinkButtonTheme : BaseButtonTheme
private void BuildDisabledStyle()
{
var disabledStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Disabled));
disabledStyle.Add(TemplatedControl.ForegroundProperty,
new DynamicResourceExtension(GlobalTokenResourceKey.ColorTextDisabled));
disabledStyle.Add(TemplatedControl.ForegroundProperty, GlobalTokenResourceKey.ColorTextDisabled);
Add(disabledStyle);
}
}

View File

@ -1,5 +1,7 @@
using System.Windows.Input;
using AtomUI.Data;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Input;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
@ -78,11 +80,11 @@ public class SplitButton : ContentControl, ICommandSource, ISizeTypeAware
public static readonly StyledProperty<SizeType> SizeTypeProperty =
Button.SizeTypeProperty.AddOwner<SplitButton>();
public static readonly StyledProperty<PathIcon?> IconProperty
public static readonly StyledProperty<Icon?> IconProperty
= Button.IconProperty.AddOwner<SplitButton>();
public static readonly StyledProperty<PathIcon?> FlyoutButtonIconProperty
= AvaloniaProperty.Register<SplitButton, PathIcon?>(nameof(FlyoutButtonIcon));
public static readonly StyledProperty<Icon?> FlyoutButtonIconProperty
= AvaloniaProperty.Register<SplitButton, Icon?>(nameof(FlyoutButtonIcon));
public static readonly StyledProperty<bool> IsDangerProperty =
Button.IsDangerProperty.AddOwner<SplitButton>();
@ -198,13 +200,13 @@ public class SplitButton : ContentControl, ICommandSource, ISizeTypeAware
set => SetValue(SizeTypeProperty, value);
}
public PathIcon? Icon
public Icon? Icon
{
get => GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
public PathIcon? FlyoutButtonIcon
public Icon? FlyoutButtonIcon
{
get => GetValue(FlyoutButtonIconProperty);
set => SetValue(FlyoutButtonIconProperty, value);
@ -431,13 +433,7 @@ public class SplitButton : ContentControl, ICommandSource, ISizeTypeAware
_primaryButton.Click += HandlePrimaryButtonClick;
}
if (FlyoutButtonIcon is null)
{
FlyoutButtonIcon = new PathIcon
{
Kind = "EllipsisOutlined"
};
}
FlyoutButtonIcon ??= AntDesignIconPackage.EllipsisOutlined();
SetupEffectiveButtonType();
SetupFlyoutProperties();

View File

@ -1,6 +1,6 @@
using AtomUI.Controls.Utils;
using AtomUI.Data;
using AtomUI.Icon;
using AtomUI.IconPkg;
using AtomUI.Theme.Styling;
using Avalonia;
using Avalonia.Controls.Primitives;
@ -13,11 +13,11 @@ public class ToggleIconButton : ToggleButton
{
#region
public static readonly StyledProperty<PathIcon?> CheckedIconProperty
= AvaloniaProperty.Register<ToggleIconButton, PathIcon?>(nameof(CheckedIcon));
public static readonly StyledProperty<Icon?> CheckedIconProperty
= AvaloniaProperty.Register<ToggleIconButton, Icon?>(nameof(CheckedIcon));
public static readonly StyledProperty<PathIcon?> UnCheckedIconProperty
= AvaloniaProperty.Register<ToggleIconButton, PathIcon?>(nameof(UnCheckedIcon));
public static readonly StyledProperty<Icon?> UnCheckedIconProperty
= AvaloniaProperty.Register<ToggleIconButton, Icon?>(nameof(UnCheckedIcon));
public static readonly StyledProperty<double> IconWidthProperty
= AvaloniaProperty.Register<ToggleIconButton, double>(nameof(IconWidth));
@ -25,13 +25,13 @@ public class ToggleIconButton : ToggleButton
public static readonly StyledProperty<double> IconHeightProperty
= AvaloniaProperty.Register<ToggleIconButton, double>(nameof(IconHeight));
public PathIcon? CheckedIcon
public Icon? CheckedIcon
{
get => GetValue(CheckedIconProperty);
set => SetValue(CheckedIconProperty, value);
}
public PathIcon? UnCheckedIcon
public Icon? UnCheckedIcon
{
get => GetValue(UnCheckedIconProperty);
set => SetValue(UnCheckedIconProperty, value);
@ -81,13 +81,13 @@ public class ToggleIconButton : ToggleButton
ApplyIconToContent();
}
protected virtual void ConfigureIcon(PathIcon icon)
protected virtual void ConfigureIcon(Icon Icon)
{
icon.SetCurrentValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
icon.SetCurrentValue(VerticalAlignmentProperty, VerticalAlignment.Center);
UIStructureUtils.SetTemplateParent(icon, this);
BindUtils.RelayBind(this, IconWidthProperty, icon, WidthProperty);
BindUtils.RelayBind(this, IconHeightProperty, icon, HeightProperty);
Icon.SetCurrentValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
Icon.SetCurrentValue(VerticalAlignmentProperty, VerticalAlignment.Center);
UIStructureUtils.SetTemplateParent(Icon, this);
BindUtils.RelayBind(this, IconWidthProperty, Icon, WidthProperty);
BindUtils.RelayBind(this, IconHeightProperty, Icon, HeightProperty);
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
@ -103,24 +103,24 @@ public class ToggleIconButton : ToggleButton
change.Property == IsPointerOverProperty)
{
CollectStyleState();
var pathIcon = IsChecked.HasValue && IsChecked.Value ? CheckedIcon : UnCheckedIcon;
if (pathIcon is not null)
var Icon = IsChecked.HasValue && IsChecked.Value ? CheckedIcon : UnCheckedIcon;
if (Icon is not null)
{
if (_styleState.HasFlag(ControlStyleState.Enabled))
{
pathIcon.IconMode = IconMode.Normal;
Icon.IconMode = IconMode.Normal;
if (_styleState.HasFlag(ControlStyleState.Sunken))
{
pathIcon.IconMode = IconMode.Selected;
Icon.IconMode = IconMode.Selected;
}
else if (_styleState.HasFlag(ControlStyleState.MouseOver))
{
pathIcon.IconMode = IconMode.Active;
Icon.IconMode = IconMode.Active;
}
}
else
{
pathIcon.IconMode = IconMode.Disabled;
Icon.IconMode = IconMode.Disabled;
}
}
}
@ -129,7 +129,7 @@ public class ToggleIconButton : ToggleButton
if (change.Property == CheckedIconProperty ||
change.Property == UnCheckedIconProperty)
{
if (change.NewValue is PathIcon newIcon)
if (change.NewValue is Icon newIcon)
{
ConfigureIcon(newIcon);
ApplyIconToContent();

View File

@ -1,4 +1,4 @@
using AtomUI.Icon;
using AtomUI.IconPkg;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia.Controls;
@ -45,23 +45,23 @@ internal class ToggleIconButtonTheme : BaseControlTheme
new Style(selector => selector.Nesting().PropertyEquals(InputElement.IsEnabledProperty, true));
{
{
var iconStyle = new Style(selector => selector.Nesting().Template().OfType<PathIcon>());
iconStyle.Add(PathIcon.IconModeProperty, IconMode.Normal);
var iconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
iconStyle.Add(Icon.IconModeProperty, IconMode.Normal);
enabledStyle.Add(iconStyle);
}
var hoverStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Selected));
{
var iconStyle = new Style(selector => selector.Nesting().Template().OfType<PathIcon>());
iconStyle.Add(PathIcon.IconModeProperty, IconMode.Active);
var iconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
iconStyle.Add(Icon.IconModeProperty, IconMode.Active);
hoverStyle.Add(iconStyle);
}
enabledStyle.Add(hoverStyle);
var checkedStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Selected));
{
var iconStyle = new Style(selector => selector.Nesting().Template().OfType<PathIcon>());
iconStyle.Add(PathIcon.IconModeProperty, IconMode.Selected);
var iconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
iconStyle.Add(Icon.IconModeProperty, IconMode.Selected);
checkedStyle.Add(iconStyle);
}
enabledStyle.Add(checkedStyle);
@ -71,8 +71,8 @@ internal class ToggleIconButtonTheme : BaseControlTheme
var disabledStyle =
new Style(selector => selector.Nesting().PropertyEquals(InputElement.IsEnabledProperty, false));
{
var iconStyle = new Style(selector => selector.Nesting().Template().OfType<PathIcon>());
iconStyle.Add(PathIcon.IconModeProperty, IconMode.Disabled);
var iconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
iconStyle.Add(Icon.IconModeProperty, IconMode.Disabled);
disabledStyle.Add(iconStyle);
}
Add(disabledStyle);

View File

@ -1,6 +1,6 @@
using AtomUI.Media;
using AtomUI.Controls.Utils;
using AtomUI.Media;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;

View File

@ -1,9 +1,8 @@
using System.Globalization;
using AtomUI.Controls.Utils;
using AtomUI.Media;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;

View File

@ -1,6 +1,8 @@
using AtomUI.Theme;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Data;
@ -112,15 +114,12 @@ internal class CalendarItemTheme : BaseControlTheme
protected virtual IconButton BuildPreviousButton()
{
var previousButtonIcon = new PathIcon
{
Kind = "DoubleLeftOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, PathIcon.NormalFilledBrushProperty,
var previousButtonIcon = AntDesignIconPackage.DoubleLeftOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextDescription);
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
var previousButton = new IconButton
@ -138,15 +137,12 @@ internal class CalendarItemTheme : BaseControlTheme
protected virtual IconButton BuildPreviousMonthButton()
{
var previousMonthButtonIcon = new PathIcon
{
Kind = "LeftOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, PathIcon.NormalFilledBrushProperty,
var previousMonthButtonIcon = AntDesignIconPackage.LeftOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextDescription);
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
var previousMonthButton = new IconButton
@ -164,15 +160,12 @@ internal class CalendarItemTheme : BaseControlTheme
protected virtual IconButton BuildNextButton()
{
var nextButtonIcon = new PathIcon
{
Kind = "DoubleRightOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, PathIcon.NormalFilledBrushProperty,
var nextButtonIcon = AntDesignIconPackage.DoubleRightOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextDescription);
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
var nextButton = new IconButton
@ -189,15 +182,12 @@ internal class CalendarItemTheme : BaseControlTheme
protected virtual IconButton BuildNextMonthButton()
{
var nextMonthButtonIcon = new PathIcon
{
Kind = "RightOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, PathIcon.NormalFilledBrushProperty,
var nextMonthButtonIcon = AntDesignIconPackage.RightOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextDescription);
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
var nextMonthButton = new IconButton
{

View File

@ -1,6 +1,6 @@
using AtomUI.Media;
using AtomUI.Controls.Utils;
using AtomUI.Media;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using Avalonia.Animation;
using Avalonia.Controls.Primitives;

View File

@ -2,8 +2,6 @@
using AtomUI.Media;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;

View File

@ -178,6 +178,14 @@ public class Collapse : SelectingItemsControl
SetupCollapseBorderThickness(collapseItem, index);
}
}
protected override void ContainerIndexChangedOverride(Control container, int oldIndex, int newIndex)
{
if (container is CollapseItem collapseItem)
{
SetupCollapseBorderThickness(collapseItem, newIndex);
}
}
private void SetupCollapseBorderThickness(CollapseItem collapseItem, int index)
{

View File

@ -1,9 +1,10 @@
using AtomUI.Controls.Utils;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.MotionScene;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Automation.Peers;
using Avalonia.Controls;
@ -25,8 +26,8 @@ public class CollapseItem : HeaderedContentControl, ISelectable
public static readonly StyledProperty<bool> IsShowExpandIconProperty =
AvaloniaProperty.Register<CollapseItem, bool>(nameof(IsShowExpandIcon), true);
public static readonly StyledProperty<PathIcon?> ExpandIconProperty =
AvaloniaProperty.Register<CollapseItem, PathIcon?>(nameof(ExpandIcon));
public static readonly StyledProperty<Icon?> ExpandIconProperty =
AvaloniaProperty.Register<CollapseItem, Icon?>(nameof(ExpandIcon));
public static readonly StyledProperty<object?> AddOnContentProperty =
AvaloniaProperty.Register<CollapseItem, object?>(nameof(AddOnContent));
@ -46,7 +47,7 @@ public class CollapseItem : HeaderedContentControl, ISelectable
set => SetValue(IsShowExpandIconProperty, value);
}
public PathIcon? ExpandIcon
public Icon? ExpandIcon
{
get => GetValue(ExpandIconProperty);
set => SetValue(ExpandIconProperty, value);
@ -269,7 +270,7 @@ public class CollapseItem : HeaderedContentControl, ISelectable
}
else if (change.Property == ExpandIconProperty)
{
var oldExpandIcon = change.GetOldValue<PathIcon?>();
var oldExpandIcon = change.GetOldValue<Icon?>();
if (oldExpandIcon is not null)
{
UIStructureUtils.SetTemplateParent(oldExpandIcon, null);
@ -308,9 +309,8 @@ public class CollapseItem : HeaderedContentControl, ISelectable
}
InAnimating = true;
var slideDownInMotionConfig = MotionFactory.BuildSlideUpInMotion(MotionDuration, new CubicEaseOut(),
FillMode.Forward);
MotionInvoker.Invoke(_motionActor, slideDownInMotionConfig, () =>
var motion = new SlideUpInMotion(MotionDuration, new CubicEaseOut());
MotionInvoker.Invoke(_motionActor, motion, () =>
{
_motionActor.SetCurrentValue(IsVisibleProperty, true);
}, () =>
@ -333,9 +333,8 @@ public class CollapseItem : HeaderedContentControl, ISelectable
}
InAnimating = true;
var slideDownOutMotionConfig = MotionFactory.BuildSlideUpOutMotion(MotionDuration, new CubicEaseIn(),
FillMode.Forward);
MotionInvoker.Invoke(_motionActor, slideDownOutMotionConfig, null, () =>
var motion = new SlideUpOutMotion(MotionDuration, new CubicEaseIn());
MotionInvoker.Invoke(_motionActor, motion, null, () =>
{
_motionActor.SetCurrentValue(IsVisibleProperty, false);
InAnimating = false;
@ -346,11 +345,8 @@ public class CollapseItem : HeaderedContentControl, ISelectable
{
if (ExpandIcon is null)
{
ExpandIcon = new PathIcon
{
Kind = "RightOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(ExpandIcon, PathIcon.DisabledFilledBrushProperty,
ExpandIcon = AntDesignIconPackage.RightOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(ExpandIcon, Icon.DisabledFilledBrushProperty,
GlobalTokenResourceKey.ColorTextDisabled);
}

View File

@ -1,8 +1,8 @@
using AtomUI.Controls.Primitives;
using AtomUI.IconPkg;
using AtomUI.MotionScene;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
@ -174,7 +174,7 @@ internal class CollapseItemTheme : BaseControlTheme
// ExpandIcon
var expandIconStyle =
new Style(selector => selector.Nesting().Template().Name(ExpandButtonPart).Descendant().OfType<PathIcon>());
new Style(selector => selector.Nesting().Template().Name(ExpandButtonPart).Descendant().OfType<Icon>());
expandIconStyle.Add(Layoutable.WidthProperty, GlobalTokenResourceKey.IconSizeSM);
expandIconStyle.Add(Layoutable.HeightProperty, GlobalTokenResourceKey.IconSizeSM);
commonStyle.Add(expandIconStyle);
@ -335,7 +335,7 @@ internal class CollapseItemTheme : BaseControlTheme
private void BuildAddOnContentStyle()
{
var addOnContentStyle = new Style(selector => selector.Nesting().Template().Name(AddOnContentPresenterPart)
.Descendant().OfType<PathIcon>());
.Descendant().OfType<Icon>());
addOnContentStyle.Add(Layoutable.WidthProperty, GlobalTokenResourceKey.IconSize);
addOnContentStyle.Add(Layoutable.HeightProperty, GlobalTokenResourceKey.IconSize);
Add(addOnContentStyle);

View File

@ -1,7 +1,7 @@
using AtomUI.Media;
using AtomUI.Controls.Utils;
using AtomUI.Media;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;

View File

@ -1,6 +1,8 @@
using AtomUI.Theme;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Documents;
@ -97,14 +99,11 @@ internal class ComboBoxTheme : BaseControlTheme
spinnerHandleDecorator.RegisterInNameScope(scope);
var decreaseButtonIcon = new PathIcon
{
Kind = "DownOutlined"
};
var decreaseButtonIcon = AntDesignIconPackage.DownOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(decreaseButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(decreaseButtonIcon, Icon.ActiveFilledBrushProperty,
ButtonSpinnerTokenResourceKey.HandleHoverColor);
TokenResourceBinder.CreateGlobalTokenBinding(decreaseButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(decreaseButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorPrimaryActive);
var openButton = new IconButton

View File

@ -1,6 +1,6 @@
using AtomUI.Media;
using AtomUI.Controls.Utils;
using AtomUI.Media;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;

View File

@ -1,9 +1,8 @@
using System.Globalization;
using AtomUI.Controls.Utils;
using AtomUI.Media;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;

View File

@ -1,7 +1,9 @@
using AtomUI.Data;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
@ -164,15 +166,12 @@ internal class CalendarItemTheme : BaseControlTheme
protected virtual IconButton BuildPreviousButton(string name)
{
var previousButtonIcon = new PathIcon
{
Kind = "DoubleLeftOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, PathIcon.NormalFilledBrushProperty,
var previousButtonIcon = AntDesignIconPackage.DoubleLeftOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextDescription);
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
var previousButton = new IconButton
@ -190,15 +189,12 @@ internal class CalendarItemTheme : BaseControlTheme
protected virtual IconButton BuildPreviousMonthButton(string name)
{
var previousMonthButtonIcon = new PathIcon
{
Kind = "LeftOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, PathIcon.NormalFilledBrushProperty,
var previousMonthButtonIcon = AntDesignIconPackage.LeftOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextDescription);
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(previousMonthButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
var previousMonthButton = new IconButton
@ -216,15 +212,12 @@ internal class CalendarItemTheme : BaseControlTheme
protected virtual IconButton BuildNextButton(string name)
{
var nextButtonIcon = new PathIcon
{
Kind = "DoubleRightOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, PathIcon.NormalFilledBrushProperty,
var nextButtonIcon = AntDesignIconPackage.DoubleRightOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextDescription);
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
var nextButton = new IconButton
@ -241,15 +234,12 @@ internal class CalendarItemTheme : BaseControlTheme
protected virtual IconButton BuildNextMonthButton(string name)
{
var nextMonthButtonIcon = new PathIcon
{
Kind = "RightOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, PathIcon.NormalFilledBrushProperty,
var nextMonthButtonIcon = AntDesignIconPackage.RightOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextDescription);
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(nextMonthButtonIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
var nextMonthButton = new IconButton
{

View File

@ -1,6 +1,6 @@
using AtomUI.Data;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;

View File

@ -1,4 +1,6 @@
using AtomUI.Controls.Internal;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme.Styling;
using Avalonia.Controls;
using Avalonia.Styling;
@ -12,12 +14,9 @@ internal class DatePickerTheme : InfoPickerInputTheme
{
}
protected override PathIcon BuildInfoIcon(InfoPickerInput infoPickerInput, INameScope scope)
protected override Icon BuildInfoIcon(InfoPickerInput infoPickerInput, INameScope scope)
{
return new PathIcon()
{
Kind = "CalendarOutlined"
};
return AntDesignIconPackage.CalendarOutlined();
}
protected override void BuildStyles()

View File

@ -1,4 +1,6 @@
using AtomUI.Controls.Internal;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme.Styling;
using Avalonia.Controls;
using Avalonia.Styling;
@ -12,12 +14,9 @@ internal class RangeDatePickerTheme : RangeInfoPickerInputTheme
{
}
protected override PathIcon BuildInfoIcon(InfoPickerInput infoPickerInput, INameScope scope)
protected override Icon BuildInfoIcon(InfoPickerInput infoPickerInput, INameScope scope)
{
return new PathIcon()
{
Kind = "CalendarOutlined"
};
return AntDesignIconPackage.CalendarOutlined();
}
protected override void BuildStyles()

View File

@ -2,6 +2,6 @@ namespace AtomUI.Controls;
public enum DrawerOpenMode
{
Overlay,
Push,
Overlay = 0,
Push = 1,
}

View File

@ -1,6 +1,6 @@
using AtomUI.Media;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;

View File

@ -63,14 +63,12 @@ internal class EmptyIndicatorTheme : BaseControlTheme
var sizeSmallAndMiddleStyle = new Style(selector => Selectors.Or(
selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Middle),
selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Small)));
sizeSmallAndMiddleStyle.Add(EmptyIndicator.DescriptionMarginProperty,
new DynamicResourceExtension(GlobalTokenResourceKey.MarginXS));
sizeSmallAndMiddleStyle.Add(EmptyIndicator.DescriptionMarginProperty, GlobalTokenResourceKey.MarginXS);
Add(sizeSmallAndMiddleStyle);
var sizeLargeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Large));
sizeLargeStyle.Add(EmptyIndicator.DescriptionMarginProperty,
new DynamicResourceExtension(GlobalTokenResourceKey.MarginSM));
sizeLargeStyle.Add(EmptyIndicator.DescriptionMarginProperty, GlobalTokenResourceKey.MarginSM);
Add(sizeLargeStyle);
BuildSvgStyle();
@ -83,8 +81,7 @@ internal class EmptyIndicatorTheme : BaseControlTheme
var largeSizeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Large));
var svgStyle = new Style(selector => svgSelector);
svgStyle.Add(Layoutable.HeightProperty,
new DynamicResourceExtension(EmptyIndicatorTokenResourceKey.EmptyImgHeight));
svgStyle.Add(Layoutable.HeightProperty, EmptyIndicatorTokenResourceKey.EmptyImgHeight);
largeSizeStyle.Add(svgStyle);
Add(largeSizeStyle);
}
@ -93,8 +90,7 @@ internal class EmptyIndicatorTheme : BaseControlTheme
var middleSizeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Middle));
var svgStyle = new Style(selector => svgSelector);
svgStyle.Add(Layoutable.HeightProperty,
new DynamicResourceExtension(EmptyIndicatorTokenResourceKey.EmptyImgHeightMD));
svgStyle.Add(Layoutable.HeightProperty, EmptyIndicatorTokenResourceKey.EmptyImgHeightMD);
middleSizeStyle.Add(svgStyle);
Add(middleSizeStyle);
}
@ -103,8 +99,7 @@ internal class EmptyIndicatorTheme : BaseControlTheme
var smallSizeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Small));
var svgStyle = new Style(selector => svgSelector);
svgStyle.Add(Layoutable.HeightProperty,
new DynamicResourceExtension(EmptyIndicatorTokenResourceKey.EmptyImgHeightSM));
svgStyle.Add(Layoutable.HeightProperty, EmptyIndicatorTokenResourceKey.EmptyImgHeightSM);
smallSizeStyle.Add(svgStyle);
Add(smallSizeStyle);
}

View File

@ -1,10 +1,10 @@
using AtomUI.Controls.Utils;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.MotionScene;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
@ -44,8 +44,8 @@ public class Expander : AvaloniaExpander
public static readonly StyledProperty<bool> IsShowExpandIconProperty =
AvaloniaProperty.Register<Expander, bool>(nameof(IsShowExpandIcon), true);
public static readonly StyledProperty<PathIcon?> ExpandIconProperty =
AvaloniaProperty.Register<Expander, PathIcon?>(nameof(ExpandIcon));
public static readonly StyledProperty<Icon?> ExpandIconProperty =
AvaloniaProperty.Register<Expander, Icon?>(nameof(ExpandIcon));
public static readonly StyledProperty<object?> AddOnContentProperty =
AvaloniaProperty.Register<Expander, object?>(nameof(AddOnContent));
@ -77,7 +77,7 @@ public class Expander : AvaloniaExpander
set => SetValue(IsShowExpandIconProperty, value);
}
public PathIcon? ExpandIcon
public Icon? ExpandIcon
{
get => GetValue(ExpandIconProperty);
set => SetValue(ExpandIconProperty, value);
@ -194,6 +194,7 @@ public class Expander : AvaloniaExpander
{
return;
}
IsExpanded = !IsExpanded;
};
}
@ -204,7 +205,7 @@ public class Expander : AvaloniaExpander
base.OnPropertyChanged(change);
if (change.Property == ExpandIconProperty)
{
var oldExpandIcon = change.GetOldValue<PathIcon?>();
var oldExpandIcon = change.GetOldValue<Icon?>();
if (oldExpandIcon is not null)
{
UIStructureUtils.SetTemplateParent(oldExpandIcon, null);
@ -268,11 +269,8 @@ public class Expander : AvaloniaExpander
{
if (ExpandIcon is null)
{
ExpandIcon = new PathIcon
{
Kind = "RightOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(ExpandIcon, PathIcon.DisabledFilledBrushProperty,
ExpandIcon = AntDesignIconPackage.RightOutlined();
TokenResourceBinder.CreateGlobalTokenBinding(ExpandIcon, Icon.DisabledFilledBrushProperty,
GlobalTokenResourceKey.ColorTextDisabled);
}
@ -294,6 +292,7 @@ public class Expander : AvaloniaExpander
{
return;
}
IsExpanded = !IsExpanded;
}
}
@ -311,52 +310,46 @@ public class Expander : AvaloniaExpander
CollapseItemContent();
}
}
private void ExpandItemContent()
{
if (_motionActor is null || _animating)
{
return;
}
if (!_enableAnimation)
{
_motionActor.IsVisible = true;
return;
}
_animating = true;
var expandMotionConfig = MotionFactory.BuildExpandMotion(DirectionFromExpandDirection(ExpandDirection),
var motion = new ExpandMotion(DirectionFromExpandDirection(ExpandDirection),
MotionDuration,
new CubicEaseOut(),
FillMode.Forward);
MotionInvoker.Invoke(_motionActor, expandMotionConfig, () =>
{
_motionActor.SetCurrentValue(IsVisibleProperty, true);
}, () =>
{
_animating = false;
});
new CubicEaseOut());
MotionInvoker.Invoke(_motionActor, motion, () => { _motionActor.SetCurrentValue(IsVisibleProperty, true); },
() => { _animating = false; });
}
private void CollapseItemContent()
{
if (_motionActor is null || _animating)
{
return;
}
if (!_enableAnimation)
{
_motionActor.IsVisible = false;
return;
}
_animating = true;
var slideDownOutMotionConfig = MotionFactory.BuildCollapseMotion(DirectionFromExpandDirection(ExpandDirection),
var motion = new CollapseMotion(DirectionFromExpandDirection(ExpandDirection),
MotionDuration,
new CubicEaseIn(),
FillMode.Forward);
MotionInvoker.Invoke(_motionActor, slideDownOutMotionConfig, null, () =>
new CubicEaseIn());
MotionInvoker.Invoke(_motionActor, motion, null, () =>
{
_motionActor.SetCurrentValue(IsVisibleProperty, false);
_animating = false;
@ -371,6 +364,8 @@ public class Expander : AvaloniaExpander
ExpandDirection.Up => Direction.Top,
ExpandDirection.Right => Direction.Right,
ExpandDirection.Down => Direction.Bottom,
_ => throw new ArgumentOutOfRangeException(nameof(expandDirection), expandDirection,
"Invalid value for ExpandDirection")
};
}

View File

@ -1,8 +1,8 @@
using AtomUI.Controls.Primitives;
using AtomUI.IconPkg;
using AtomUI.MotionScene;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
@ -199,7 +199,7 @@ internal class ExpanderTheme : BaseControlTheme
// ExpandIcon
var expandIconStyle = new Style(selector =>
selector.Nesting().Template().Name(ExpandButtonPart).Descendant().OfType<PathIcon>());
selector.Nesting().Template().Name(ExpandButtonPart).Descendant().OfType<Icon>());
expandIconStyle.Add(Layoutable.WidthProperty, GlobalTokenResourceKey.IconSizeSM);
expandIconStyle.Add(Layoutable.HeightProperty, GlobalTokenResourceKey.IconSizeSM);
commonStyle.Add(expandIconStyle);
@ -487,7 +487,7 @@ internal class ExpanderTheme : BaseControlTheme
private void BuildAddOnContentStyle()
{
var addOnContentStyle = new Style(selector =>
selector.Nesting().Template().Name(AddOnContentPresenterPart).Descendant().OfType<PathIcon>());
selector.Nesting().Template().Name(AddOnContentPresenterPart).Descendant().OfType<Icon>());
addOnContentStyle.Add(Layoutable.WidthProperty, GlobalTokenResourceKey.IconSize);
addOnContentStyle.Add(Layoutable.HeightProperty, GlobalTokenResourceKey.IconSize);
Add(addOnContentStyle);

View File

@ -1,12 +1,11 @@
using System.ComponentModel;
using System.Reactive.Disposables;
using AtomUI.Data;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Data;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Metadata;
@ -26,7 +25,7 @@ public class Flyout : PopupFlyoutBase
/// 是否显示指示箭头
/// </summary>
public static readonly StyledProperty<bool> IsShowArrowProperty =
ArrowDecoratedBox.IsShowArrowProperty.AddOwner<PopupFlyoutBase>();
ArrowDecoratedBox.IsShowArrowProperty.AddOwner<Flyout>();
public static readonly StyledProperty<BoxShadows> MaskShadowsProperty =
Border.BoxShadowProperty.AddOwner<Flyout>();
@ -320,6 +319,7 @@ public class Flyout : PopupFlyoutBase
var offsetX = HorizontalOffset;
var offsetY = VerticalOffset;
if (IsPointAtCenter)
{
offsetX += pointAtCenterOffset.X;

View File

@ -1,6 +1,6 @@
using AtomUI.Data;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives.PopupPositioning;

View File

@ -1,6 +1,6 @@
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;

View File

@ -1,7 +1,7 @@
using AtomUI.Controls.Utils;
using AtomUI.IconPkg;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
@ -28,8 +28,8 @@ public class GroupBox : ContentControl
public static readonly StyledProperty<IBrush?> HeaderTitleColorProperty =
AvaloniaProperty.Register<GroupBox, IBrush?>(nameof(HeaderTitleColor));
public static readonly StyledProperty<PathIcon?> HeaderIconProperty
= AvaloniaProperty.Register<GroupBox, PathIcon?>(nameof(HeaderIcon));
public static readonly StyledProperty<Icon?> HeaderIconProperty
= AvaloniaProperty.Register<GroupBox, Icon?>(nameof(HeaderIcon));
public static readonly StyledProperty<GroupBoxTitlePosition> HeaderTitlePositionProperty =
AvaloniaProperty.Register<GroupBox, GroupBoxTitlePosition>(nameof(HeaderTitlePosition));
@ -55,7 +55,7 @@ public class GroupBox : ContentControl
set => SetValue(HeaderTitleColorProperty, value);
}
public PathIcon? HeaderIcon
public Icon? HeaderIcon
{
get => GetValue(HeaderIconProperty);
set => SetValue(HeaderIconProperty, value);

View File

@ -1,4 +1,5 @@
using AtomUI.Theme;
using AtomUI.IconPkg;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia;
using Avalonia.Controls;
@ -172,7 +173,7 @@ internal class GroupBoxTheme : BaseControlTheme
protected override void BuildInstanceStyles(Control control)
{
var iconStyle = new Style(selector => selector.Name(HeaderIconPart).Descendant().OfType<PathIcon>());
var iconStyle = new Style(selector => selector.Name(HeaderIconPart).Descendant().OfType<Icon>());
iconStyle.Add(Layoutable.WidthProperty, GlobalTokenResourceKey.IconSizeLG);
iconStyle.Add(Layoutable.HeightProperty, GlobalTokenResourceKey.IconSizeLG);
iconStyle.Add(Layoutable.VerticalAlignmentProperty, VerticalAlignment.Center);

View File

@ -1,4 +1,5 @@
using AtomUI.Theme.Styling;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme.Styling;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
@ -17,10 +18,7 @@ internal class SearchEditDecoratedBoxTheme : AddOnDecoratedBoxTheme
protected override void BuildRightAddOn(Grid layout, INameScope scope)
{
var searchIcon = new PathIcon
{
Kind = "SearchOutlined"
};
var searchIcon = AntDesignIconPackage.SearchOutlined();
var searchButton = new Button
{

View File

@ -1,6 +1,6 @@
using AtomUI.Data;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Diagnostics;

View File

@ -1,4 +1,5 @@
using AtomUI.Data;
using AtomUI.IconPkg;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia;
@ -70,7 +71,7 @@ internal class InfoPickerInputTheme : BaseControlTheme
return pickerInnerBox;
}
protected virtual PathIcon? BuildInfoIcon(InfoPickerInput infoPickerInput, INameScope scope)
protected virtual Icon? BuildInfoIcon(InfoPickerInput infoPickerInput, INameScope scope)
{
return default;
}

View File

@ -1,4 +1,5 @@
using Avalonia;
using AtomUI.IconPkg;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
@ -11,8 +12,8 @@ internal class PickerClearUpButton : TemplatedControl
public static readonly StyledProperty<bool> IsInClearModeProperty =
AvaloniaProperty.Register<PickerClearUpButton, bool>(nameof(IsInClearMode));
public static readonly StyledProperty<PathIcon?> IconProperty =
AvaloniaProperty.Register<PickerClearUpButton, PathIcon?>(nameof(Icon));
public static readonly StyledProperty<Icon?> IconProperty =
AvaloniaProperty.Register<PickerClearUpButton, Icon?>(nameof(Icon));
public bool IsInClearMode
{
@ -20,7 +21,7 @@ internal class PickerClearUpButton : TemplatedControl
set => SetValue(IsInClearModeProperty, value);
}
public PathIcon? Icon
public Icon? Icon
{
get => GetValue(IconProperty);
set => SetValue(IconProperty, value);

View File

@ -1,6 +1,8 @@
using AtomUI.Theme;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
@ -48,10 +50,7 @@ internal class PickerClearUpButtonTheme : BaseControlTheme
private void BuildClearButton(Panel layout, INameScope scope)
{
var closeIcon = new PathIcon
{
Kind = "CloseCircleFilled"
};
var closeIcon = AntDesignIconPackage.CloseCircleFilled();
var clearButton = new IconButton
{
Name = ClearButtonPart,
@ -62,11 +61,11 @@ internal class PickerClearUpButtonTheme : BaseControlTheme
GlobalTokenResourceKey.IconSize);
TokenResourceBinder.CreateGlobalTokenBinding(clearButton, IconButton.IconWidthProperty,
GlobalTokenResourceKey.IconSize);
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextQuaternary);
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, PathIcon.ActiveFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, Icon.ActiveFilledBrushProperty,
GlobalTokenResourceKey.ColorTextTertiary);
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, PathIcon.SelectedFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(closeIcon, Icon.SelectedFilledBrushProperty,
GlobalTokenResourceKey.ColorText);
clearButton.RegisterInNameScope(scope);
@ -74,13 +73,13 @@ internal class PickerClearUpButtonTheme : BaseControlTheme
PickerClearUpButton.IsInClearModeProperty);
layout.Children.Add(clearButton);
}
protected override void BuildInstanceStyles(Control control)
{
var iconStyle = new Style(selector => selector.Name(InfoIconContentPart).Child().OfType<PathIcon>());
iconStyle.Add(PathIcon.WidthProperty, GlobalTokenResourceKey.IconSize);
iconStyle.Add(PathIcon.HeightProperty, GlobalTokenResourceKey.IconSize);
iconStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorTextQuaternary);
var iconStyle = new Style(selector => selector.Name(InfoIconContentPart).Child().OfType<Icon>());
iconStyle.Add(Icon.WidthProperty, GlobalTokenResourceKey.IconSize);
iconStyle.Add(Icon.HeightProperty, GlobalTokenResourceKey.IconSize);
iconStyle.Add(Icon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorTextQuaternary);
control.Styles.Add(iconStyle);
}
}

View File

@ -1,4 +1,4 @@
using AtomUI.Theme.Utils;
using AtomUI.Controls.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;

View File

@ -1,5 +1,7 @@
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Controls.Templates;
@ -35,17 +37,14 @@ internal class RangeInfoPickerInputTheme : InfoPickerInputTheme
}
};
var arrowIcon = new PathIcon
{
Kind = "SwapRightOutlined",
Name = RangePickerArrowPart
};
var arrowIcon = AntDesignIconPackage.SwapRightOutlined();
arrowIcon.Name = RangePickerArrowPart;
TokenResourceBinder.CreateGlobalTokenBinding(arrowIcon, Layoutable.HeightProperty,
GlobalTokenResourceKey.IconSize);
TokenResourceBinder.CreateGlobalTokenBinding(arrowIcon, Layoutable.WidthProperty,
GlobalTokenResourceKey.IconSize);
TokenResourceBinder.CreateGlobalTokenBinding(arrowIcon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(arrowIcon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorTextQuaternary);
var rangeStartTextBox = BuildPickerTextBox(InfoInputBoxPart);

View File

@ -1,5 +1,5 @@
using AtomUI.Media;
using AtomUI.Theme.Utils;
using AtomUI.Controls.Utils;
using AtomUI.Media;
using Avalonia;
using Avalonia.Animation;
using Avalonia.LogicalTree;

View File

@ -1,4 +1,5 @@
using AtomUI.Controls.Utils;
using AtomUI.IconPkg;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
@ -24,8 +25,8 @@ public class LoadingIndicator : TemplatedControl, ISizeTypeAware
public static readonly StyledProperty<bool> IsShowLoadingMsgProperty =
AvaloniaProperty.Register<LoadingIndicator, bool>(nameof(IsShowLoadingMsg));
public static readonly StyledProperty<PathIcon?> CustomIndicatorIconProperty =
AvaloniaProperty.Register<LoadingIndicator, PathIcon?>(nameof(CustomIndicatorIcon));
public static readonly StyledProperty<Icon?> CustomIndicatorIconProperty =
AvaloniaProperty.Register<LoadingIndicator, Icon?>(nameof(CustomIndicatorIcon));
public static readonly StyledProperty<TimeSpan?> MotionDurationProperty =
AvaloniaProperty.Register<LoadingIndicator, TimeSpan?>(nameof(MotionDuration));
@ -51,7 +52,7 @@ public class LoadingIndicator : TemplatedControl, ISizeTypeAware
set => SetValue(IsShowLoadingMsgProperty, value);
}
public PathIcon? CustomIndicatorIcon
public Icon? CustomIndicatorIcon
{
get => GetValue(CustomIndicatorIconProperty);
set => SetValue(CustomIndicatorIconProperty, value);
@ -182,7 +183,7 @@ public class LoadingIndicator : TemplatedControl, ISizeTypeAware
{
if (VisualRoot is not null)
{
var oldCustomIcon = e.GetOldValue<PathIcon?>();
var oldCustomIcon = e.GetOldValue<Icon?>();
if (oldCustomIcon is not null)
{
_mainContainer?.Children.Remove(oldCustomIcon);

View File

@ -1,4 +1,4 @@
using AtomUI.Icon;
using AtomUI.IconPkg;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia.Animation.Easings;
@ -63,15 +63,15 @@ internal class LoadingIndicatorTheme : BaseControlTheme
private void BuildCustomIconStyle()
{
var customIconStyle = new Style(selector => selector.Nesting().Template().OfType<PathIcon>());
customIconStyle.Add(PathIcon.IconModeProperty, IconMode.Normal);
var customIconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
customIconStyle.Add(Icon.IconModeProperty, IconMode.Normal);
customIconStyle.Add(Layoutable.VerticalAlignmentProperty, VerticalAlignment.Center);
customIconStyle.Add(Layoutable.HorizontalAlignmentProperty, HorizontalAlignment.Center);
Add(customIconStyle);
var largeSizeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(LoadingIndicator.SizeTypeProperty, SizeType.Large));
var largeIconStyle = new Style(selector => selector.Nesting().Template().OfType<PathIcon>());
var largeIconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
largeIconStyle.Add(Layoutable.WidthProperty, LoadingIndicator.LARGE_INDICATOR_SIZE);
largeIconStyle.Add(Layoutable.HeightProperty, LoadingIndicator.LARGE_INDICATOR_SIZE);
largeSizeStyle.Add(largeIconStyle);
@ -79,7 +79,7 @@ internal class LoadingIndicatorTheme : BaseControlTheme
var middleSizeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(LoadingIndicator.SizeTypeProperty, SizeType.Middle));
var middleIconStyle = new Style(selector => selector.Nesting().Template().OfType<PathIcon>());
var middleIconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
middleIconStyle.Add(Layoutable.WidthProperty, LoadingIndicator.MIDDLE_INDICATOR_SIZE);
middleIconStyle.Add(Layoutable.HeightProperty, LoadingIndicator.MIDDLE_INDICATOR_SIZE);
middleSizeStyle.Add(middleIconStyle);
@ -87,7 +87,7 @@ internal class LoadingIndicatorTheme : BaseControlTheme
var smallSizeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(LoadingIndicator.SizeTypeProperty, SizeType.Small));
var smallIconStyle = new Style(selector => selector.Nesting().Template().OfType<PathIcon>());
var smallIconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
smallIconStyle.Add(Layoutable.WidthProperty, LoadingIndicator.SMALL_INDICATOR_SIZE);
smallIconStyle.Add(Layoutable.HeightProperty, LoadingIndicator.SMALL_INDICATOR_SIZE);
smallSizeStyle.Add(smallIconStyle);

View File

@ -1,4 +1,5 @@
using AtomUI.Data;
using AtomUI.IconPkg;
using Avalonia;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
@ -21,7 +22,7 @@ public class LoadingMask : AvaloniaObject, IDisposable
public static readonly StyledProperty<bool> IsShowLoadingMsgProperty =
LoadingIndicator.IsShowLoadingMsgProperty.AddOwner<LoadingMask>();
public static readonly StyledProperty<PathIcon?> CustomIndicatorIconProperty =
public static readonly StyledProperty<Icon?> CustomIndicatorIconProperty =
LoadingIndicator.CustomIndicatorIconProperty.AddOwner<LoadingMask>();
public static readonly StyledProperty<TimeSpan?> MotionDurationProperty =
@ -48,7 +49,7 @@ public class LoadingMask : AvaloniaObject, IDisposable
set => SetValue(IsShowLoadingMsgProperty, value);
}
public PathIcon? CustomIndicatorIcon
public Icon? CustomIndicatorIcon
{
get => GetValue(CustomIndicatorIconProperty);
set => SetValue(CustomIndicatorIconProperty, value);

View File

@ -1,5 +1,5 @@
using AtomUI.Data;
using AtomUI.Theme.Styling;
using AtomUI.IconPkg;
using Avalonia;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
@ -20,7 +20,7 @@ public class LoadingMaskHost : Control
public static readonly StyledProperty<bool> IsShowLoadingMsgProperty =
LoadingIndicator.IsShowLoadingMsgProperty.AddOwner<LoadingMaskHost>();
public static readonly StyledProperty<PathIcon?> CustomIndicatorIconProperty =
public static readonly StyledProperty<Icon?> CustomIndicatorIconProperty =
LoadingIndicator.CustomIndicatorIconProperty.AddOwner<LoadingMaskHost>();
public static readonly StyledProperty<TimeSpan?> MotionDurationProperty =
@ -53,7 +53,7 @@ public class LoadingMaskHost : Control
set => SetValue(IsShowLoadingMsgProperty, value);
}
public PathIcon? CustomIndicatorIcon
public Icon? CustomIndicatorIcon
{
get => GetValue(CustomIndicatorIconProperty);
set => SetValue(CustomIndicatorIconProperty, value);

View File

@ -1,3 +1,4 @@
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;

View File

@ -1,5 +1,5 @@
using AtomUI.Data;
using AtomUI.Utils;
using AtomUI.Theme.Data;
using Avalonia;
using Avalonia.Controls;
using Avalonia.LogicalTree;

View File

@ -1,7 +1,7 @@
using AtomUI.Data;
using AtomUI.Media;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
@ -89,11 +89,11 @@ public class MenuItem : AvaloniaMenuItem
}
else if (e.Property == IconProperty)
{
if (Icon is not null && Icon is PathIcon pathIcon)
if (Icon is not null && Icon is IconPkg.Icon icon)
{
TokenResourceBinder.CreateTokenBinding(pathIcon, WidthProperty, MenuTokenResourceKey.ItemIconSize);
TokenResourceBinder.CreateTokenBinding(pathIcon, HeightProperty, MenuTokenResourceKey.ItemIconSize);
TokenResourceBinder.CreateTokenBinding(pathIcon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateTokenBinding(icon, WidthProperty, MenuTokenResourceKey.ItemIconSize);
TokenResourceBinder.CreateTokenBinding(icon, HeightProperty, MenuTokenResourceKey.ItemIconSize);
TokenResourceBinder.CreateTokenBinding(icon, IconPkg.Icon.NormalFilledBrushProperty,
MenuTokenResourceKey.ItemColor);
}
}

View File

@ -1,7 +1,8 @@
using AtomUI.Media;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Media;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
@ -141,14 +142,12 @@ internal class MenuItemTheme : BaseControlTheme
MenuItem.KeyGestureConverter);
inputGestureText.RegisterInNameScope(scope);
var menuIndicatorIcon = new PathIcon
{
Name = MenuIndicatorIconPart,
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Center,
Kind = "RightOutlined"
};
var menuIndicatorIcon = AntDesignIconPackage.RightOutlined();
menuIndicatorIcon.Name = MenuIndicatorIconPart;
menuIndicatorIcon.HorizontalAlignment = HorizontalAlignment.Right;
menuIndicatorIcon.VerticalAlignment = VerticalAlignment.Center;
TokenResourceBinder.CreateGlobalTokenBinding(menuIndicatorIcon, Layoutable.WidthProperty,
GlobalTokenResourceKey.IconSizeXS);
TokenResourceBinder.CreateGlobalTokenBinding(menuIndicatorIcon, Layoutable.HeightProperty,

View File

@ -1,9 +1,9 @@
using AtomUI.Data;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Media;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia.Animation;
using Avalonia.Controls;
@ -39,10 +39,7 @@ internal class MenuScrollViewerTheme : BaseControlTheme
var scrollUpButton = new IconButton
{
Name = ScrollUpButtonPart,
Icon = new PathIcon
{
Kind = "UpOutlined"
},
Icon = AntDesignIconPackage.UpOutlined(),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Transitions = transitions,
@ -58,10 +55,7 @@ internal class MenuScrollViewerTheme : BaseControlTheme
var scrollDownButton = new IconButton
{
Name = ScrollDownButtonPart,
Icon = new PathIcon
{
Kind = "DownOutlined"
},
Icon = AntDesignIconPackage.DownOutlined(),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Transitions = transitions,

View File

@ -1,6 +1,6 @@
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;

View File

@ -1,4 +1,6 @@
namespace AtomUI.Controls;
using AtomUI.IconPkg;
namespace AtomUI.Controls;
public interface IMessage
{
@ -10,7 +12,7 @@ public interface IMessage
/// <summary>
/// 自定义图标
/// </summary>
PathIcon? Icon { get; }
Icon? Icon { get; }
/// <summary>
/// Gets the <see cref="MessageType" /> of the notification.

View File

@ -1,16 +1,17 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using AtomUI.IconPkg;
namespace AtomUI.Controls;
public class Message : IMessage, INotifyPropertyChanged
{
private string _content;
private PathIcon? _icon;
private Icon? _icon;
public Message(string content,
MessageType type = MessageType.Information,
PathIcon? icon = null,
Icon? icon = null,
TimeSpan? expiration = null,
Action? onClose = null)
{
@ -35,7 +36,7 @@ public class Message : IMessage, INotifyPropertyChanged
}
}
public PathIcon? Icon
public Icon? Icon
{
get => _icon;

View File

@ -1,9 +1,9 @@
using AtomUI.Icon;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.MotionScene;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
@ -49,8 +49,8 @@ public class MessageCard : TemplatedControl
public static readonly RoutedEvent<RoutedEventArgs> MessageClosedEvent =
RoutedEvent.Register<MessageCard, RoutedEventArgs>(nameof(MessageClosed), RoutingStrategies.Bubble);
public static readonly StyledProperty<PathIcon?> IconProperty
= AvaloniaProperty.Register<MessageCard, PathIcon?>(nameof(Icon));
public static readonly StyledProperty<Icon?> IconProperty
= AvaloniaProperty.Register<MessageCard, Icon?>(nameof(Icon));
public static readonly StyledProperty<string> MessageProperty =
AvaloniaProperty.Register<NotificationCard, string>(nameof(Message));
@ -91,7 +91,7 @@ public class MessageCard : TemplatedControl
remove => RemoveHandler(MessageClosedEvent, value);
}
public PathIcon? Icon
public Icon? Icon
{
get => GetValue(IconProperty);
set => SetValue(IconProperty, value);
@ -198,9 +198,8 @@ public class MessageCard : TemplatedControl
if (_motionActor is not null)
{
_motionActor.IsVisible = false;
var moveUpInMotionConfig = MotionFactory.BuildMoveUpInMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseOut(),
FillMode.Forward);
MotionInvoker.Invoke(_motionActor, moveUpInMotionConfig, () =>
var motion = new MoveUpInMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseOut());
MotionInvoker.Invoke(_motionActor, motion, () =>
{
_motionActor.IsVisible = true;
});
@ -211,9 +210,8 @@ public class MessageCard : TemplatedControl
{
if (_motionActor is not null)
{
var moveUpOutMotionConfig = MotionFactory.BuildMoveUpOutMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseIn(),
FillMode.Forward);
MotionInvoker.Invoke(_motionActor, moveUpOutMotionConfig, null, () =>
var motion = new MoveUpOutMotion(AnimationMaxOffsetY, _openCloseMotionDuration, new CubicEaseIn());
MotionInvoker.Invoke(_motionActor, motion, null, () =>
{
IsClosed = true;
});
@ -251,69 +249,54 @@ public class MessageCard : TemplatedControl
}
}
private void SetupMessageIconColor(PathIcon icon)
private void SetupMessageIconColor(Icon Icon)
{
if (MessageType == MessageType.Error)
{
TokenResourceBinder.CreateGlobalTokenBinding(icon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(Icon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorError);
}
else if (MessageType == MessageType.Information ||
MessageType == MessageType.Loading)
{
TokenResourceBinder.CreateGlobalTokenBinding(icon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(Icon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorPrimary);
}
else if (MessageType == MessageType.Success)
{
TokenResourceBinder.CreateGlobalTokenBinding(icon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(Icon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorSuccess);
}
else if (MessageType == MessageType.Warning)
{
TokenResourceBinder.CreateGlobalTokenBinding(icon, PathIcon.NormalFilledBrushProperty,
TokenResourceBinder.CreateGlobalTokenBinding(Icon, Icon.NormalFilledBrushProperty,
GlobalTokenResourceKey.ColorWarning);
}
}
private void SetupMessageIcon()
{
PathIcon? icon = null;
Icon? icon = null;
if (MessageType == MessageType.Information)
{
icon = new PathIcon
{
Kind = "InfoCircleFilled"
};
icon = AntDesignIconPackage.InfoCircleFilled();
}
else if (MessageType == MessageType.Success)
{
icon = new PathIcon
{
Kind = "CheckCircleFilled"
};
icon = AntDesignIconPackage.CheckCircleFilled();
}
else if (MessageType == MessageType.Error)
{
icon = new PathIcon
{
Kind = "CloseCircleFilled"
};
icon = AntDesignIconPackage.CloseCircleFilled();
}
else if (MessageType == MessageType.Warning)
{
icon = new PathIcon
{
Kind = "ExclamationCircleFilled"
};
icon = AntDesignIconPackage.ExclamationCircleFilled();
}
else if (MessageType == MessageType.Loading)
{
icon = new PathIcon
{
Kind = "LoadingOutlined",
LoadingAnimation = IconAnimation.Spin
};
icon = AntDesignIconPackage.LoadingOutlined();
icon.LoadingAnimation = IconAnimation.Spin;
}
if (icon is not null)

View File

@ -1,11 +1,9 @@
using AtomUI.Controls.Primitives;
using AtomUI.IconPkg;
using AtomUI.MotionScene;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
@ -146,7 +144,7 @@ internal class MessageCardTheme : BaseControlTheme
protected override void BuildInstanceStyles(Control control)
{
var iconStyle = new Style(selector => selector.Name(IconContentPart).Child().OfType<PathIcon>());
var iconStyle = new Style(selector => selector.Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Layoutable.WidthProperty, MessageTokenResourceKey.MessageIconSize);
iconStyle.Add(Layoutable.HeightProperty, MessageTokenResourceKey.MessageIconSize);
control.Styles.Add(iconStyle);

View File

@ -1,8 +1,9 @@
using AtomUI.Icon;
using AtomUI.IconPkg;
using AtomUI.IconPkg.AntDesign;
using AtomUI.Media;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
@ -154,15 +155,12 @@ internal class BaseNavMenuItemTheme : BaseControlTheme
protected virtual Control BuildMenuIndicatorIcon(INameScope scope)
{
var menuIndicatorIcon = new PathIcon
{
Name = MenuIndicatorIconPart,
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Center,
Kind = "RightOutlined"
};
var menuIndicatorIcon = AntDesignIconPackage.RightOutlined();
menuIndicatorIcon.Name = MenuIndicatorIconPart;
menuIndicatorIcon.HorizontalAlignment = HorizontalAlignment.Right;
menuIndicatorIcon.VerticalAlignment = VerticalAlignment.Center;
CreateTemplateParentBinding(menuIndicatorIcon, PathIcon.IsEnabledProperty, NavMenuItem.IsEnabledProperty);
CreateTemplateParentBinding(menuIndicatorIcon, Icon.IsEnabledProperty, NavMenuItem.IsEnabledProperty);
TokenResourceBinder.CreateGlobalTokenBinding(menuIndicatorIcon, Layoutable.WidthProperty,
NavMenuTokenResourceKey.MenuArrowSize);
@ -293,9 +291,9 @@ internal class BaseNavMenuItemTheme : BaseControlTheme
{
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconPart));
menuIndicatorStyle.Add(Visual.IsVisibleProperty, true);
menuIndicatorStyle.Add(PathIcon.NormalFilledBrushProperty, NavMenuTokenResourceKey.ItemColor);
menuIndicatorStyle.Add(PathIcon.SelectedFilledBrushProperty, NavMenuTokenResourceKey.ItemSelectedColor);
menuIndicatorStyle.Add(PathIcon.DisabledFilledBrushProperty, NavMenuTokenResourceKey.ItemDisabledColor);
menuIndicatorStyle.Add(Icon.NormalFilledBrushProperty, NavMenuTokenResourceKey.ItemColor);
menuIndicatorStyle.Add(Icon.SelectedFilledBrushProperty, NavMenuTokenResourceKey.ItemSelectedColor);
menuIndicatorStyle.Add(Icon.DisabledFilledBrushProperty, NavMenuTokenResourceKey.ItemDisabledColor);
// 设置颜色
Add(menuIndicatorStyle);
@ -304,18 +302,18 @@ internal class BaseNavMenuItemTheme : BaseControlTheme
var darkCommonStyle = new Style(selector => selector.Nesting().PropertyEquals(NavMenuItem.IsDarkStyleProperty, true));
{
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconPart));
menuIndicatorStyle.Add(PathIcon.NormalFilledBrushProperty, NavMenuTokenResourceKey.DarkItemColor);
menuIndicatorStyle.Add(PathIcon.SelectedFilledBrushProperty, NavMenuTokenResourceKey.DarkItemSelectedColor);
menuIndicatorStyle.Add(PathIcon.DisabledFilledBrushProperty, NavMenuTokenResourceKey.DarkItemDisabledColor);
menuIndicatorStyle.Add(Icon.NormalFilledBrushProperty, NavMenuTokenResourceKey.DarkItemColor);
menuIndicatorStyle.Add(Icon.SelectedFilledBrushProperty, NavMenuTokenResourceKey.DarkItemSelectedColor);
menuIndicatorStyle.Add(Icon.DisabledFilledBrushProperty, NavMenuTokenResourceKey.DarkItemDisabledColor);
darkCommonStyle.Add(menuIndicatorStyle);
}
Add(darkCommonStyle);
}
var selectedStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Selected));
{
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconPart));
menuIndicatorStyle.Add(PathIcon.IconModeProperty, IconMode.Selected);
menuIndicatorStyle.Add(Icon.IconModeProperty, IconMode.Selected);
selectedStyle.Add(menuIndicatorStyle);
}
Add(selectedStyle);

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